]> git.lizzy.rs Git - rust.git/commitdiff
Merge remote-tracking branch 'erickt/master'
authorBrian Anderson <banderson@mozilla.com>
Sun, 5 Feb 2012 23:15:21 +0000 (15:15 -0800)
committerBrian Anderson <banderson@mozilla.com>
Sun, 5 Feb 2012 23:15:21 +0000 (15:15 -0800)
Conflicts:
src/libcore/vec.rs
src/libstd/getopts.rs

300 files changed:
.gitmodules
AUTHORS.txt
configure
doc/tutorial.md
man/rustc.1
mk/install.mk
mk/libuv/ia32/mac/Makefile
mk/libuv/ia32/mac/Makefile-e [deleted file]
mk/libuv/ia32/mac/gyp-mac-tool
mk/libuv/ia32/mac/src/libuv/run-benchmarks.target.mk
mk/libuv/ia32/mac/src/libuv/run-tests.target.mk
mk/libuv/ia32/mac/src/libuv/uv.target.mk
mk/libuv/ia32/unix/Makefile
mk/libuv/ia32/unix/Makefile-e [deleted file]
mk/libuv/ia32/unix/src/libuv/run-benchmarks.target.mk
mk/libuv/ia32/unix/src/libuv/run-tests.target.mk
mk/libuv/ia32/unix/src/libuv/uv.target.mk
mk/libuv/ia32/win/Makefile
mk/libuv/ia32/win/Makefile-e [deleted file]
mk/libuv/ia32/win/src/libuv/run-benchmarks.target.mk
mk/libuv/ia32/win/src/libuv/run-tests.target.mk
mk/libuv/ia32/win/src/libuv/uv.target.mk
mk/libuv/ia32/win/src/libuv/uv.target.mk.bak [new file with mode: 0644]
mk/libuv/x86_64/freebsd/Makefile [deleted file]
mk/libuv/x86_64/freebsd/src/libuv/run-benchmarks.target.mk [deleted file]
mk/libuv/x86_64/freebsd/src/libuv/run-tests.target.mk [deleted file]
mk/libuv/x86_64/freebsd/src/libuv/uv.Makefile [deleted file]
mk/libuv/x86_64/freebsd/src/libuv/uv.target.mk [deleted file]
mk/libuv/x86_64/mac/Makefile
mk/libuv/x86_64/mac/Makefile-e [deleted file]
mk/libuv/x86_64/mac/gyp-mac-tool
mk/libuv/x86_64/mac/src/libuv/run-benchmarks.target.mk
mk/libuv/x86_64/mac/src/libuv/run-benchmarks.target.mk-e [deleted file]
mk/libuv/x86_64/mac/src/libuv/run-tests.target.mk
mk/libuv/x86_64/mac/src/libuv/run-tests.target.mk-e [deleted file]
mk/libuv/x86_64/mac/src/libuv/uv.target.mk
mk/libuv/x86_64/mac/src/libuv/uv.target.mk-e [deleted file]
mk/libuv/x86_64/unix/Makefile
mk/libuv/x86_64/unix/Makefile-e [deleted file]
mk/libuv/x86_64/unix/src/libuv/run-benchmarks.target.mk
mk/libuv/x86_64/unix/src/libuv/run-tests.target.mk
mk/libuv/x86_64/unix/src/libuv/uv.target.mk
mk/libuv/x86_64/win/Makefile
mk/libuv/x86_64/win/Makefile-e [deleted file]
mk/libuv/x86_64/win/src/libuv/run-benchmarks.target.mk
mk/libuv/x86_64/win/src/libuv/run-tests.target.mk
mk/libuv/x86_64/win/src/libuv/uv.target.mk
mk/platform.mk
mk/rt.mk
src/cargo/cargo.rs
src/comp/back/abi.rs
src/comp/back/link.rs
src/comp/back/rpath.rs
src/comp/back/upcall.rs
src/comp/driver/diagnostic.rs
src/comp/driver/driver.rs
src/comp/driver/rustc.rs
src/comp/driver/session.rs
src/comp/front/attr.rs
src/comp/front/config.rs
src/comp/front/test.rs
src/comp/lib/llvm.rs
src/comp/metadata/creader.rs
src/comp/metadata/csearch.rs
src/comp/metadata/decoder.rs
src/comp/metadata/encoder.rs
src/comp/metadata/tydecode.rs
src/comp/metadata/tyencode.rs
src/comp/middle/alias.rs
src/comp/middle/ast_map.rs
src/comp/middle/block_use.rs
src/comp/middle/check_alt.rs
src/comp/middle/check_const.rs
src/comp/middle/debuginfo.rs
src/comp/middle/gc.rs [deleted file]
src/comp/middle/kind.rs
src/comp/middle/last_use.rs
src/comp/middle/lint.rs
src/comp/middle/mut.rs
src/comp/middle/pat_util.rs
src/comp/middle/resolve.rs
src/comp/middle/shape.rs
src/comp/middle/trans/alt.rs
src/comp/middle/trans/base.rs
src/comp/middle/trans/build.rs
src/comp/middle/trans/closure.rs
src/comp/middle/trans/common.rs
src/comp/middle/trans/impl.rs
src/comp/middle/trans/tvec.rs
src/comp/middle/trans/uniq.rs
src/comp/middle/tstate/auxiliary.rs
src/comp/middle/tstate/collect_locals.rs
src/comp/middle/tstate/pre_post_conditions.rs
src/comp/middle/tstate/states.rs
src/comp/middle/ty.rs
src/comp/middle/typeck.rs
src/comp/rustc.rc
src/comp/syntax/ast.rs
src/comp/syntax/ast_util.rs
src/comp/syntax/codemap.rs
src/comp/syntax/ext/base.rs
src/comp/syntax/ext/build.rs [new file with mode: 0644]
src/comp/syntax/ext/concat_idents.rs
src/comp/syntax/ext/env.rs
src/comp/syntax/ext/expand.rs
src/comp/syntax/ext/fmt.rs
src/comp/syntax/ext/ident_to_str.rs
src/comp/syntax/ext/log_syntax.rs
src/comp/syntax/ext/qquote.rs [new file with mode: 0644]
src/comp/syntax/ext/simplext.rs
src/comp/syntax/fold.rs
src/comp/syntax/parse/eval.rs
src/comp/syntax/parse/lexer.rs
src/comp/syntax/parse/parser.rs
src/comp/syntax/parse/token.rs
src/comp/syntax/print/pprust.rs
src/comp/syntax/visit.rs
src/comp/util/common.rs
src/comp/util/filesearch.rs
src/comp/util/ppaux.rs
src/compiletest/common.rs
src/compiletest/compiletest.rs
src/compiletest/errors.rs
src/compiletest/header.rs
src/compiletest/procsrv.rs
src/compiletest/runtest.rs
src/etc/apple-darwin.supp [new file with mode: 0644]
src/etc/ctags.rust
src/etc/gen-intrinsics
src/etc/gyp-uv
src/etc/pkg/rust.nsi [deleted file]
src/etc/x86.supp
src/fuzzer/fuzzer.rs
src/libcore/char.rs
src/libcore/comm.rs
src/libcore/core.rc
src/libcore/core.rs
src/libcore/ctypes.rs
src/libcore/extfmt.rs
src/libcore/float.rs
src/libcore/iter.rs [new file with mode: 0644]
src/libcore/math.rs
src/libcore/str.rs
src/libcore/sys.rs
src/libcore/task.rs
src/libcore/vec.rs
src/libstd/c_vec.rs
src/libstd/deque.rs
src/libstd/ebml.rs
src/libstd/freebsd_os.rs
src/libstd/fs.rs
src/libstd/fun_treemap.rs
src/libstd/generic_os.rs
src/libstd/getopts.rs
src/libstd/io.rs
src/libstd/json.rs
src/libstd/linux_os.rs
src/libstd/list.rs
src/libstd/macos_os.rs
src/libstd/map.rs
src/libstd/md4.rs
src/libstd/rand.rs
src/libstd/rope.rs
src/libstd/run_program.rs
src/libstd/smallintmap.rs
src/libstd/sort.rs
src/libstd/tempfile.rs
src/libstd/test.rs
src/libstd/treemap.rs
src/libstd/ufind.rs
src/libstd/uv.rs
src/libstd/uvtmp.rs
src/libstd/win32_os.rs
src/libuv
src/rt/boxed_region.cpp [new file with mode: 0644]
src/rt/boxed_region.h [new file with mode: 0644]
src/rt/intrinsics/intrinsics.cpp
src/rt/intrinsics/intrinsics.i386.ll.in
src/rt/intrinsics/intrinsics.x86_64.ll.in
src/rt/memory_region.h
src/rt/rust.cpp
src/rt/rust_builtin.cpp
src/rt/rust_cc.cpp
src/rt/rust_crate_cache.cpp
src/rt/rust_gc.cpp [deleted file]
src/rt/rust_gc.h [deleted file]
src/rt/rust_internal.h
src/rt/rust_kernel.cpp
src/rt/rust_kernel.h
src/rt/rust_log.cpp
src/rt/rust_log.h
src/rt/rust_port.cpp
src/rt/rust_scheduler.cpp
src/rt/rust_scheduler.h
src/rt/rust_shape.cpp
src/rt/rust_shape.h
src/rt/rust_srv.cpp
src/rt/rust_task.cpp
src/rt/rust_task.h
src/rt/rust_task_list.cpp
src/rt/rust_task_list.h
src/rt/rust_task_thread.cpp [new file with mode: 0644]
src/rt/rust_task_thread.h [new file with mode: 0644]
src/rt/rust_timer.cpp [deleted file]
src/rt/rust_upcall.cpp
src/rt/rust_upcall.h
src/rt/rust_util.h
src/rt/rust_uvtmp.cpp
src/rt/rustrt.def.in
src/rt/sync/lock_and_signal.cpp
src/rt/sync/lock_and_signal.h
src/rt/test/rust_test_harness.cpp [deleted file]
src/rt/test/rust_test_harness.h [deleted file]
src/rt/test/rust_test_runtime.cpp [deleted file]
src/rt/test/rust_test_runtime.h [deleted file]
src/rt/test/rust_test_util.cpp [deleted file]
src/rt/test/rust_test_util.h [deleted file]
src/rustdoc/astsrv.rs
src/rustdoc/attr_parser.rs
src/rustdoc/attr_pass.rs
src/rustdoc/demo.rs
src/rustdoc/desc_pass.rs
src/rustdoc/desc_to_brief_pass.rs
src/rustdoc/doc.rs
src/rustdoc/extract.rs
src/rustdoc/fold.rs
src/rustdoc/markdown_pass.rs
src/rustdoc/parse.rs
src/rustdoc/path_pass.rs
src/rustdoc/prune_undoc_details_pass.rs [new file with mode: 0644]
src/rustdoc/prune_undoc_items_pass.rs [new file with mode: 0644]
src/rustdoc/prune_undoc_pass.rs [deleted file]
src/rustdoc/prune_unexported_pass.rs
src/rustdoc/rustdoc.rc
src/rustdoc/rustdoc.rs
src/rustdoc/sort_item_name_pass.rs [new file with mode: 0644]
src/rustdoc/sort_item_type_pass.rs [new file with mode: 0644]
src/rustdoc/sort_pass.rs [new file with mode: 0644]
src/rustdoc/trim_pass.rs
src/rustdoc/tystr_pass.rs
src/rustdoc/unindent_pass.rs
src/snapshots.txt
src/test/bench/shootout-ackermann.rs
src/test/bench/shootout-fibo.rs
src/test/bench/shootout-mandelbrot.rs [new file with mode: 0644]
src/test/bench/shootout-threadring.rs [new file with mode: 0644]
src/test/bench/task-perf-word-count-generic.rs
src/test/bench/task-perf-word-count.rs
src/test/compile-fail/ext-noname.rs
src/test/compile-fail/fn-constraint.rs
src/test/compile-fail/mode-inference-fail.rs [new file with mode: 0644]
src/test/compile-fail/native-type-mismatch.rs [deleted file]
src/test/compile-fail/no-constraint-prop.rs
src/test/compile-fail/non-exhaustive-match-nested.rs [new file with mode: 0644]
src/test/compile-fail/non-exhaustive-match.rs [new file with mode: 0644]
src/test/compile-fail/pattern-tyvar-2.rs
src/test/compile-fail/pattern-tyvar.rs
src/test/compile-fail/tag-that-dare-not-speak-its-name.rs
src/test/compile-fail/unsupported-cast.rs
src/test/pretty/block-disambig.rs
src/test/pretty/record-trailing-comma.rs
src/test/run-fail/fn-constraint.rs
src/test/run-fail/morestack2.rs
src/test/run-fail/morestack4.rs
src/test/run-fail/non-exhaustive-match.rs [deleted file]
src/test/run-pass/alias-uninit-value.rs
src/test/run-pass/alt-join.rs
src/test/run-pass/alt-path.rs
src/test/run-pass/bind-native.rs
src/test/run-pass/binops.rs
src/test/run-pass/block-arg-in-ternary.rs [deleted file]
src/test/run-pass/classes.rs [new file with mode: 0644]
src/test/run-pass/closure-inference.rs [new file with mode: 0644]
src/test/run-pass/closure-inference2.rs [new file with mode: 0644]
src/test/run-pass/constraint-prop-expr-move.rs
src/test/run-pass/constraint-prop-move.rs
src/test/run-pass/constraint-prop-swap.rs
src/test/run-pass/constraint-prop.rs
src/test/run-pass/enum-disr-val-pretty.rs
src/test/run-pass/fn-constraint.rs
src/test/run-pass/hashmap-memory.rs
src/test/run-pass/iface-generic.rs
src/test/run-pass/issue-1660.rs [new file with mode: 0644]
src/test/run-pass/issue-511.rs
src/test/run-pass/item-attributes.rs
src/test/run-pass/method-attributes.rs [new file with mode: 0644]
src/test/run-pass/morestack5.rs
src/test/run-pass/morestack6.rs
src/test/run-pass/native-dupe.rs
src/test/run-pass/native-opaque-type.rs [deleted file]
src/test/run-pass/nested-pattern.rs
src/test/run-pass/operator-overloading.rs
src/test/run-pass/qquote.rs [new file with mode: 0644]
src/test/run-pass/shape_intrinsic_tag_then_rec.rs
src/test/run-pass/supported-cast.rs
src/test/run-pass/task-comm-12.rs
src/test/run-pass/task-pin.rs [deleted file]
src/test/run-pass/ternary.rs [deleted file]
src/test/run-pass/utf8_chars.rs
src/test/run-pass/weird-exprs.rs

index bd5c14b7f469c393e931be5a88b83e7f33aa8388..d750f8eb5b7813df48138cbc7d5aeb04e772cba7 100644 (file)
@@ -3,4 +3,4 @@
        url = git://github.com/brson/llvm.git
 [submodule "src/libuv"]
        path = src/libuv
-       url = git://github.com/joyent/libuv
+       url = git://github.com/graydon/libuv.git
index 3fd634894d5985bcfd07231392bb5a844b5720d7..c0292daddbc4bbcc5678a9fb4d617722b523da4b 100644 (file)
@@ -59,6 +59,7 @@ Sean Stangl <sstangl@mozilla.com>
 startling <tdixon51793@gmail.com>
 Stefan Plantikow <stefan.plantikow@googlemail.com>
 Taras Shpot <mrshpot@gmail.com>
+Ted Horst <ted.horst@earthlink.net>
 Tim Chevalier <chevalier@alum.wellesley.edu>
 Tycho Sci <tychosci@gmail.com>
 Wade Mealing <wmealing@gmail.com>
index 9d4a54109612bc3b8fcf17b15ea55db5bbfec54f..10770c07b748fd0244b4ba3645c0bad1feaa7a51 100755 (executable)
--- a/configure
+++ b/configure
@@ -267,8 +267,8 @@ opt mingw-cross 0 "cross-compile for win32 using mingw"
 opt clang 0 "prefer clang to gcc for building the runtime"
 valopt prefix "/usr/local" "set installation prefix"
 valopt llvm-root "" "set LLVM root"
-valopt host-triple "$DEFAULT_HOST_TRIPLE" "primary LLVM host triple"
-valopt target-triples "" "LLVM target triples (defaults to host if unset)"
+valopt host-triple "${DEFAULT_HOST_TRIPLE}" "LLVM host triple"
+valopt target-triples "${CFG_HOST_TRIPLE}" "LLVM target triples"
 
 if [ $HELP -eq 1 ]
 then
@@ -356,23 +356,10 @@ else
     CFG_C_COMPILER="gcc"
 fi
 
-if [ -z "$CFG_PREFIX" ]
-then
-    CFG_PREFIX=/usr/local
-fi
-
-if [ -z "$CFG_HOST_TRIPLE" ]
-then
-    CFG_HOST_TRIPLE="$DEFAULT_HOST_TRIPLE"
-fi
-
-if [ -z "$CFG_TARGET_TRIPLES" ]
-then
-    CFG_TARGET_TRIPLES="${CFG_HOST_TRIPLE}"
-else
-    CFG_TARGET_TRIPLES="$(echo $CFG_TARGET_TRIPLES | tr ',' ' ')"
-fi
+# a little post-processing of various config values
 
+CFG_PREFIX=${CFG_PREFIX%/}
+CFG_TARGET_TRIPLES="$(echo $CFG_TARGET_TRIPLES | tr ',' ' ')"
 case $CFG_TARGET_TRIPLES in
     (*$CFG_HOST_TRIPLE*) ;;
     (*) err "Host triple is not among the target triples." ;;
@@ -480,6 +467,8 @@ cd ${CFG_SRC_DIR}
 
 if [ -z $CFG_DISABLE_MANAGE_SUBMODULES ]
 then
+msg "git: submodule sync"
+"${CFG_GIT}" submodule sync --quiet
 SUBMODULE_STATUS=$("${CFG_GIT}" submodule status)
 NEED_INIT_COUNT=$(echo "$SUBMODULE_STATUS" | grep -c "^-")
 NEED_UPDATE_COUNT=$(echo "$SUBMODULE_STATUS" | grep -c "^+")
@@ -628,10 +617,9 @@ putvar CFG_BUILD_DIR
 putvar CFG_OSTYPE
 putvar CFG_CPUTYPE
 putvar CFG_CONFIGURE_ARGS
-putvar CFG_HOST_TRIPLE
+putvar CFG_PREFIX
 putvar CFG_TARGET_TRIPLES
 putvar CFG_C_COMPILER
-putvar CFG_PREFIX
 putvar CFG_LIBDIR
 
 # Setting this again because it may have been changed
index 29862e7ba5b6f4a5673728d5c33672fbd41bdf9f..ad6dd68d82392e3ffab871d3316fe474608a6b7f 100644 (file)
@@ -473,13 +473,6 @@ The comparison operators are the traditional `==`, `!=`, `<`, `>`,
 `<=`, and `>=`. Short-circuiting (lazy) boolean operators are written
 `&&` (and) and `||` (or).
 
-Rust has a ternary conditional operator `?:`, as in:
-
-~~~~
-let badness = 12;
-let message = badness < 10 ? "error" : "FATAL ERROR";
-~~~~
-
 For type casting, Rust uses the binary `as` operator, which has a
 precedence between the bitwise combination operators (`&`, `|`, `^`)
 and the comparison operators. It takes an expression on the left side,
@@ -1792,6 +1785,7 @@ fn world() -> str { "world" }
 ~~~~
 ## ignore
 // main.rs
+use std;
 use mylib;
 fn main() { std::io::println("hello " + mylib::world()); }
 ~~~~
index 741f9a2cba8b962bf0a080b9a5709803597b6b40..5780bad00c1b9f63c73591b146cadb54f91aa152 100644 (file)
@@ -1,6 +1,8 @@
-.TH RUSTC "1" "October 2011" "Rust" "User Commands"
+.TH RUSTC "1" "January 2012" "Rust" "User Commands"
+
 .SH NAME
 rustc \- rust compiler
+
 .SH SYNOPSIS
 rustc [\fB-h\fR] [\fB-v\fR] [\fB-o\fR \fIoutfile\fR]
       [\fB--lib\fR] [\fB--static\fR] [\fB-L\fR \fIpath\fR]
@@ -8,130 +10,125 @@ rustc [\fB-h\fR] [\fB-v\fR] [\fB-o\fR \fIoutfile\fR]
 .PP
 Only the most commonly-used options are listed here. All options are listed and
 described below.
+
 .SH DESCRIPTION
 This program is a compiler for the Rust language, available at
 <\fBhttps://www.rust-lang.org\fR>.
+
 .SH OPTIONS
 .TP
-\fB-h, --help\fR:
-Display help.
+\fB--bin\fR
+Compile an executable crate (default)
 .TP
-\fB-v, --version\fR:
-Display version information.
+\fB-c\fR
+Compile and assemble, but do not link
 .TP
-\fB-o\fR \fIfilename\fR:
-Write output to \fIfilename\fR. The default
-output filename for \fBfoo.rs\fR is otherwise \fBfoo\fR plus any
-platform-specific extension (when compiling a binary), a
-platform-specific name, e.g. \fBlibfoo.so\fR (when compiling a
-library), \fBfoo.o\fR (when using \fB-c\fR), \fBfoo.s\fR (when using
-\fB-S\fR) or \fBfoo.bc\fR (when using \fB--emit-llvm\fR), and \fBfoo.ll\fR
-(when using both \fB-S\fR and \fB--emit-llvm\fR).
+\fB--cfg <cfgspec>\fR
+Configure the compilation environment
 .TP
-\fB--lib\fR:
-Compile and link a library crate into a shared object.
+\fB--emit-llvm\fR
+Produce an LLVM bitcode file
 .TP
-\fB--static\fR:
-Produce a statically-linked binary, or generate a static
-library.
+\fB-g\fR
+Produce debug info
 .TP
-\fB--pretty\fR \fI[type]\fR:
-Pretty-print the input. Valid \fItype\fRs are:
-.RS
+\fB--gc\fR
+Garbage collect shared data (experimental/temporary)
 .TP
-\fBnormal\fR: Un-annotated source (default).
+\fB-h --help\fR
+Display this message
 .TP
-\fBexpanded\fR: Crates expanded.
+\fB-L <path>\fR
+Add a directory to the library search path
 .TP
-\fBtyped\fR: Crates expanded, all expressions annotated with types.
+\fB--lib\fR
+Compile a library crate
 .TP
-\fBidentified\fR: Fully parenthesized, ast nodes and blocks annotated with IDs.
-.RE
+\fB--ls\fR
+List the symbols defined by a compiled librar crate
 .TP
-\fB--ls\fR:
-Lists symbols defined by the specified \fBcompiled\fR library.
+\fB--no-asm-comments\fR
+Do not add comments into the assembly source
 .TP
-\fB-L\fR \fIpath\fR:
-Adds \fIpath\fR to the library search path.
+\fB--no-lint-ctypes\fR
+Suppress warnings for possibly incorrect ctype usage
 .TP
-\fB--noverify\fR:
-Disables LLVM verification pass, which does sanity checking of
-bitcode generated by rustc. Using this option gives a slight speedup, at the
-cost of vastly reduced ability to catch rustc bugs. See
-<\fBhttp://llvm.org/docs/Passes.html\fR> for a list of properties checked.
+\fB--no-trans\fR
+Run all passes except translation; no output
 .TP
-\fB--parse-only\fR:
-Run the parse phase only. If parsing succeeds, produces no
-output.
+\fB--no-verify\fR
+Suppress LLVM verification step (slight speedup)
+(see http://llvm.org/docs/Passes.html for detail)
 .TP
-\fB--no-trans\fR:
-Run all passes except translation. Produces no output.
+\fB-O\fR
+Equivalent to --opt-level=2
 .TP
-\fB-g\fR:
-Produce debug info.
+\fB-o <filename>\fR
+Write output to <filename>
 .TP
-\fB--opt-level\fR \fIlevel\fR:
-Set optimization level to \fIlevel\fR.
+\fB--opt-level <lvl>\fR
+Optimize with possible levels 0-3
 .TP
-\fB-O\fR:
-Equal to --opt-level=2
+\fB--out-dir <dir>\fR
+Write output to compiler-chosen filename in <dir>
 .TP
-\fB-S\fR:
-Compile to assembly, but do not assemble or link.
+\fB--parse-only\fR
+Parse only; do not compile, assemble, or link
 .TP
-\fB-c\fR:
-Compile and assemble, but do not link.
+\fB--pretty [type]\fR
+Pretty-print the input instead of compiling; valid types are: \fBnormal\fR (un-annotated source), \fBexpanded\fR (crates expanded), \fBtyped\fR (crates expanded, with type annotations), or \fBidentified\fR (fully parenthesized, AST nodes and blocks with IDs)
 .TP
-\fB--emit-llvm\fR:
-Generate output files in LLVM format. When used with \fB-S\fR this generate LLVM
-intermediate language assembly files, otherwise this generates LLVM bitcode
-format object files. 
+\fB-S\fR
+Compile only; do not assemble or link
 .TP
-\fB--save-temps\fR:
-For foo.rs, save generated bitcode before optimization to
-\fBfoo.bc\fR, bitcode after optimization to \fBfoo.opt.bc\fR, and the generated
-object file to \fBfoo.o\fR.
+\fB--save-temps\fR
+Write intermediate files (.bc, .opt.bc, .o) in addition to normal output
 .TP
-\fB--stats\fR:
-Print statistics about compilation.
+\fB--static\fR
+Use or produce static libraries or binaries
 .TP
-\fB--cfg\fR \fIcfgspec\fR:
-Provide a crate config spec.
+\fB--stats\fR
+Print compilation statistics
 .TP
-\fB--time-passes\fR:
-Print runtimes of compilation phases.
+\fB--sysroot <path>\fR
+Override the system root
 .TP
-\fB--time-llvm-passes\fR:
-Print runtimes of llvm phases.
+\fB--test\fR
+Build test harness
 .TP
-\fB--sysroot\fR \fIpath\fR:
-Set the system root. Default is the directory above
-rustc's.
+\fB--target <triple>\fR
+Target cpu-manufacturer-kernel[-os] to compile for (default: host triple)
+(see http://sources.redhat.com/autobook/autobook/autobook_17.html for detail)
 .TP
-\fB--target\fR \fIgnu-config-name\fR:
-Set the compilation target, which is a
-string of the form \fBcpu\fR-\fBmanufacturer\fR-\fBkernel\fR[-\fBos\fR]. Example
-values include "i686-unknown-linux-gnu" and "mips-idt-ecoff"; see
-<\fBhttp://sources.redhat.com/autobook/autobook/autobook_17.html\fR>. If not
-supplied, the host triple is used (see \fB--version\fR output).
+\fB--time-passes\fR
+Time the individual phases of the compiler
 .TP
-\fB--test\fR:
-Build a test harness.
+\fB--time-llvm-passes\fR
+Time the individual phases of the LLVM backend
 .TP
-\fB--gc\fR:
-\fBEXPERIMENTAL\fR. Garbage-collect shared data.
+\fB-v --version\fR
+Print version info and exit
 .TP
-\fB--warn-unused-imports\fR:
-Warn about unnecessary imports.
-.TP
-\fB--no-lint-ctypes\fR:
-Disables checking of possibly incorrect usage of Rust int or uint types in
-native function declarations, where types defined in libcore::ctypes should be
-used instead. Ctypes check emits warnings by default.
+\fB--warn-unused-imports\fR
+Warn about unnecessary imports
+
+.SH "EXAMPLES"
+To build an executable from a source file with a main function:
+    $ rustc -o hello hello.rs
+
+To build a library from a source file:
+    $ rustc --lib hello-lib.rs
+
+To build either with a crate (.rc) file:
+    $ rustc hello.rc
+
 .SH "BUGS"
 See \fBhttps://github.com/mozilla/rust/issues\fR for a list of known bugs.
+
 .SH "AUTHOR"
 See \fBAUTHORS.txt\fR in the rust source distribution. Graydon Hoare
 <\fIgraydon@mozilla.com\fR> is the project leader.
+
 .SH "COPYRIGHT"
 See \fBLICENSE.txt\fR in the rust source distribution.
+
index 9a5ad5a6c9fbbf7186f4045df6f02a00b76ae16d..47e75d439d7000d3f4eb49500a554ffc43742e90 100644 (file)
@@ -5,10 +5,10 @@
 # Installation macro. Call with source directory as arg 1,
 # destination directory as arg 2, and filename/libname-glob as arg 3
 ifdef VERBOSE
- INSTALL = install -m755 -T $(1)/$(3) $(2)/$(3)
+ INSTALL = install -m755 $(1)/$(3) $(2)/$(3)
  INSTALL_LIB = install -m644 `ls -rt1 $(1)/$(3) | tail -1` $(2)/
 else
- INSTALL = $(Q)$(call E, install: $(2)/$(3)) && install -m755 -T $(1)/$(3) $(2)/$(3)
+ INSTALL = $(Q)$(call E, install: $(2)/$(3)) && install -m755 $(1)/$(3) $(2)/$(3)
  INSTALL_LIB = $(Q)$(call E, install_lib: $(2)/$(3)) &&                    \
               install -m644 `ls -rt1 $(1)/$(3) | tail -1` $(2)/
 endif
@@ -44,6 +44,7 @@ install-target-$(1)-host-$(2): $$(SREQ$$(ISTAGE)_T_$(1)_H_$(2))
                $$(TL$(1)$(2)),$$(PTL$(1)$(2)),$$(LIBRUSTC_GLOB))
        $$(Q)$$(call INSTALL,$$(TL$(1)$(2)),$$(PTL$(1)$(2)),intrinsics.bc)
        $$(Q)$$(call INSTALL,$$(TL$(1)$(2)),$$(PTL$(1)$(2)),libmorestack.a)
+
 endef
 
 $(foreach target,$(CFG_TARGET_TRIPLES), \
@@ -80,3 +81,23 @@ install-host: $(SREQ$(ISTAGE)_T_$(CFG_HOST_TRIPLE)_H_$(CFG_HOST_TRIPLE))
             $(PREFIX_ROOT)/share/man/man1,rustc.1)
 
 install-targets: $(INSTALL_TARGET_RULES)
+
+
+HOST_LIB_FROM_HL_GLOB = \
+  $(patsubst $(HL)/%,$(PHL)/%,$(wildcard $(HL)/$(1)))
+
+uninstall:
+       $(Q)rm -f $(PHB)/rustc$(X)
+       $(Q)rm -f $(PHB)/cargo$(X)
+       $(Q)rm -f $(PHB)/rustdoc$(X)
+       $(Q)rm -f $(PHL)/$(CFG_RUSTLLVM)
+       $(Q)rm -f $(PHL)/$(CFG_RUNTIME)
+       $(Q)for i in \
+          $(call HOST_LIB_FROM_HL_GLOB,$(CORELIB_GLOB)) \
+          $(call HOST_LIB_FROM_HL_GLOB,$(STDLIB_GLOB)) \
+          $(call HOST_LIB_FROM_HL_GLOB,$(LIBRUSTC_GLOB)) \
+        ; \
+        do rm -f $$i ; \
+        done
+       $(Q)rm -Rf $(PHL)/rustc
+       $(Q)rm -f $(PREFIX_ROOT)/share/man/man1/rustc.1
index 22b574234f99911dcadce533591cb56443158641..002fef0390ab81294d53eff840ed64835a1036b2 100644 (file)
@@ -8,6 +8,7 @@ MAKEFLAGS=-r
 
 # The source directory tree.
 srcdir := ../../../..
+abs_srcdir := $(abspath $(srcdir))
 
 # The name of the builddir.
 builddir_name ?= out
@@ -20,7 +21,7 @@ else
 endif
 
 # Specify BUILDTYPE=Release on the command line for a release build.
-BUILDTYPE ?= Default
+BUILDTYPE ?= Debug
 
 # Directory all our build output goes into.
 # Note that this must be two directories beneath src/ for unit tests to pass,
@@ -147,7 +148,7 @@ cmd_objcxx = $(CXX.$(TOOLSET)) $(GYP_OBJCXXFLAGS) $(DEPFLAGS) -c -o $@ $<
 quiet_cmd_pch_c = CXX($(TOOLSET)) $@
 cmd_pch_c = $(CC.$(TOOLSET)) $(GYP_PCH_CFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $<
 quiet_cmd_pch_cc = CXX($(TOOLSET)) $@
-cmd_pch_cc = $(CC.$(TOOLSET)) $(GYP_PCH_CCFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $<
+cmd_pch_cc = $(CC.$(TOOLSET)) $(GYP_PCH_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $<
 quiet_cmd_pch_m = CXX($(TOOLSET)) $@
 cmd_pch_m = $(CC.$(TOOLSET)) $(GYP_PCH_OBJCFLAGS) $(DEPFLAGS) -c -o $@ $<
 quiet_cmd_pch_mm = CXX($(TOOLSET)) $@
@@ -162,6 +163,9 @@ cmd_mac_tool = ./gyp-mac-tool $(4) $< "$@"
 quiet_cmd_mac_package_framework = PACKAGE FRAMEWORK $@
 cmd_mac_package_framework = ./gyp-mac-tool package-framework "$@" $(4)
 
+quiet_cmd_infoplist = INFOPLIST $@
+cmd_infoplist = $(CC.$(TOOLSET)) -E -P -Wno-trigraphs -x c $(INFOPLIST_DEFINES) "$<" -o "$@"
+
 quiet_cmd_touch = TOUCH $@
 cmd_touch = touch $@
 
@@ -262,8 +266,8 @@ $(if $(or $(command_changed),$(prereq_changed)),
 )
 endef
 
-# Declare "all" target first so it is the default, even though we don't have the
-# deps yet.
+# Declare the "all" target first so it is the default,
+# even though we don't have the deps yet.
 .PHONY: all
 all:
 
@@ -343,9 +347,9 @@ ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
   include src/libuv/uv.target.mk
 endif
 
-quiet_cmd_regen_makefile = ACTION Regenerating $@
-cmd_regen_makefile = ./src/libuv/build/gyp/gyp -fmake --ignore-environment "--toplevel-dir=." "--depth=." "--generator-output=mk/libuv/ia32/mac" "-Dlibrary=static_library" "-Dtarget_arch=ia32" "-DOS=mac" src/libuv/uv.gyp
-Makefile: $(srcdir)/src/libuv/uv.gyp
+#quiet_cmd_regen_makefile = ACTION Regenerating $@
+#cmd_regen_makefile = ./src/libuv/build/gyp/gyp -fmake --ignore-environment "--toplevel-dir=." -Isrc/libuv/common.gypi "--depth=." "--generator-output=mk/libuv/ia32/mac" "-Ddefault_configuration=Default" "-Dcomponent=static_library" "-Dlibrary=static_library" "-Dtarget_arch=ia32" "-DOS=mac" src/libuv/uv.gyp
+#Makefile: $(srcdir)/src/libuv/uv.gyp $(srcdir)/src/libuv/common.gypi
 #      $(call do_cmd,regen_makefile)
 
 # "all" is a concatenation of the "all" targets from all the included
diff --git a/mk/libuv/ia32/mac/Makefile-e b/mk/libuv/ia32/mac/Makefile-e
deleted file mode 100644 (file)
index 6aca32e..0000000
+++ /dev/null
@@ -1,375 +0,0 @@
-# We borrow heavily from the kernel build setup, though we are simpler since
-# we don't have Kconfig tweaking settings on us.
-
-# The implicit make rules have it looking for RCS files, among other things.
-# We instead explicitly write all the rules we care about.
-# It's even quicker (saves ~200ms) to pass -r on the command line.
-MAKEFLAGS=-r
-
-# The source directory tree.
-srcdir := ../../../..
-
-# The name of the builddir.
-builddir_name ?= out
-
-# The V=1 flag on command line makes us verbosely print command lines.
-ifdef V
-  quiet=
-else
-  quiet=quiet_
-endif
-
-# Specify BUILDTYPE=Release on the command line for a release build.
-BUILDTYPE ?= Default
-
-# Directory all our build output goes into.
-# Note that this must be two directories beneath src/ for unit tests to pass,
-# as they reach into the src/ directory for data with relative paths.
-builddir ?= $(builddir_name)/$(BUILDTYPE)
-abs_builddir := $(abspath $(builddir))
-depsdir := $(builddir)/.deps
-
-# Object output directory.
-obj := $(builddir)/obj
-abs_obj := $(abspath $(obj))
-
-# We build up a list of every single one of the targets so we can slurp in the
-# generated dependency rule Makefiles in one pass.
-all_deps :=
-
-
-
-# C++ apps need to be linked with g++.
-#
-# Note: flock is used to seralize linking. Linking is a memory-intensive
-# process so running parallel links can often lead to thrashing.  To disable
-# the serialization, override LINK via an envrionment variable as follows:
-#
-#   export LINK=g++
-#
-# This will allow make to invoke N linker processes as specified in -jN.
-LINK ?= ./gyp-mac-tool flock $(builddir)/linker.lock $(CXX)
-
-CC.target ?= $(CC)
-CFLAGS.target ?= $(CFLAGS)
-CXX.target ?= $(CXX)
-CXXFLAGS.target ?= $(CXXFLAGS)
-LINK.target ?= $(LINK)
-LDFLAGS.target ?= $(LDFLAGS) 
-AR.target ?= $(AR)
-ARFLAGS.target ?= crs
-
-# N.B.: the logic of which commands to run should match the computation done
-# in gyp's make.py where ARFLAGS.host etc. is computed.
-# TODO(evan): move all cross-compilation logic to gyp-time so we don't need
-# to replicate this environment fallback in make as well.
-CC.host ?= gcc
-CFLAGS.host ?=
-CXX.host ?= g++
-CXXFLAGS.host ?=
-LINK.host ?= g++
-LDFLAGS.host ?=
-AR.host ?= ar
-ARFLAGS.host := crs
-
-# Define a dir function that can handle spaces.
-# http://www.gnu.org/software/make/manual/make.html#Syntax-of-Functions
-# "leading spaces cannot appear in the text of the first argument as written.
-# These characters can be put into the argument value by variable substitution."
-empty :=
-space := $(empty) $(empty)
-
-# http://stackoverflow.com/questions/1189781/using-make-dir-or-notdir-on-a-path-with-spaces
-replace_spaces = $(subst $(space),?,$1)
-unreplace_spaces = $(subst ?,$(space),$1)
-dirx = $(call unreplace_spaces,$(dir $(call replace_spaces,$1)))
-
-# Flags to make gcc output dependency info.  Note that you need to be
-# careful here to use the flags that ccache and distcc can understand.
-# We write to a dep file on the side first and then rename at the end
-# so we can't end up with a broken dep file.
-depfile = $(depsdir)/$(call replace_spaces,$@).d
-DEPFLAGS = -MMD -MF $(depfile).raw
-
-# We have to fixup the deps output in a few ways.
-# (1) the file output should mention the proper .o file.
-# ccache or distcc lose the path to the target, so we convert a rule of
-# the form:
-#   foobar.o: DEP1 DEP2
-# into
-#   path/to/foobar.o: DEP1 DEP2
-# (2) we want missing files not to cause us to fail to build.
-# We want to rewrite
-#   foobar.o: DEP1 DEP2 \
-#               DEP3
-# to
-#   DEP1:
-#   DEP2:
-#   DEP3:
-# so if the files are missing, they're just considered phony rules.
-# We have to do some pretty insane escaping to get those backslashes
-# and dollar signs past make, the shell, and sed at the same time.
-# Doesn't work with spaces, but that's fine: .d files have spaces in
-# their names replaced with other characters.
-define fixup_dep
-# The depfile may not exist if the input file didn't have any #includes.
-touch $(depfile).raw
-# Fixup path as in (1).
-sed -e "s|^$(notdir $@)|$@|" $(depfile).raw >> $(depfile)
-# Add extra rules as in (2).
-# We remove slashes and replace spaces with new lines;
-# remove blank lines;
-# delete the first line and append a colon to the remaining lines.
-sed -e 's|\\||' -e 'y| |\n|' $(depfile).raw |\
-  grep -v '^$$'                             |\
-  sed -e 1d -e 's|$$|:|'                     \
-    >> $(depfile)
-rm $(depfile).raw
-endef
-
-# Command definitions:
-# - cmd_foo is the actual command to run;
-# - quiet_cmd_foo is the brief-output summary of the command.
-
-quiet_cmd_cc = CC($(TOOLSET)) $@
-cmd_cc = $(CC.$(TOOLSET)) $(GYP_CFLAGS) $(DEPFLAGS) $(CFLAGS.$(TOOLSET)) -c -o $@ $<
-
-quiet_cmd_cxx = CXX($(TOOLSET)) $@
-cmd_cxx = $(CXX.$(TOOLSET)) $(GYP_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $<
-
-quiet_cmd_objc = CXX($(TOOLSET)) $@
-cmd_objc = $(CC.$(TOOLSET)) $(GYP_OBJCFLAGS) $(DEPFLAGS) -c -o $@ $<
-
-quiet_cmd_objcxx = CXX($(TOOLSET)) $@
-cmd_objcxx = $(CXX.$(TOOLSET)) $(GYP_OBJCXXFLAGS) $(DEPFLAGS) -c -o $@ $<
-
-# Commands for precompiled header files.
-quiet_cmd_pch_c = CXX($(TOOLSET)) $@
-cmd_pch_c = $(CC.$(TOOLSET)) $(GYP_PCH_CFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $<
-quiet_cmd_pch_cc = CXX($(TOOLSET)) $@
-cmd_pch_cc = $(CC.$(TOOLSET)) $(GYP_PCH_CCFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $<
-quiet_cmd_pch_m = CXX($(TOOLSET)) $@
-cmd_pch_m = $(CC.$(TOOLSET)) $(GYP_PCH_OBJCFLAGS) $(DEPFLAGS) -c -o $@ $<
-quiet_cmd_pch_mm = CXX($(TOOLSET)) $@
-cmd_pch_mm = $(CC.$(TOOLSET)) $(GYP_PCH_OBJCXXFLAGS) $(DEPFLAGS) -c -o $@ $<
-
-# gyp-mac-tool is written next to the root Makefile by gyp.
-# Use $(4) for the command, since $(2) and $(3) are used as flag by do_cmd
-# already.
-quiet_cmd_mac_tool = MACTOOL $(4) $<
-cmd_mac_tool = ./gyp-mac-tool $(4) $< "$@"
-
-quiet_cmd_mac_package_framework = PACKAGE FRAMEWORK $@
-cmd_mac_package_framework = ./gyp-mac-tool package-framework "$@" $(4)
-
-quiet_cmd_touch = TOUCH $@
-cmd_touch = touch $@
-
-quiet_cmd_copy = COPY $@
-# send stderr to /dev/null to ignore messages when linking directories.
-cmd_copy = ln -f "$<" "$@" 2>/dev/null || (rm -rf "$@" && cp -af "$<" "$@")
-
-quiet_cmd_alink = LIBTOOL-STATIC $@
-cmd_alink = rm -f $@ && libtool -static -o $@ $(filter %.o,$^)
-
-quiet_cmd_link = LINK($(TOOLSET)) $@
-cmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o "$@" $(LD_INPUTS) $(LIBS)
-
-# TODO(thakis): Find out and document the difference between shared_library and
-# loadable_module on mac.
-quiet_cmd_solink = SOLINK($(TOOLSET)) $@
-cmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o "$@" $(LD_INPUTS) $(LIBS)
-
-# TODO(thakis): The solink_module rule is likely wrong. Xcode seems to pass
-# -bundle -single_module here (for osmesa.so).
-quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@
-cmd_solink_module = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ $(filter-out FORCE_DO_CMD, $^) $(LIBS)
-
-
-# Define an escape_quotes function to escape single quotes.
-# This allows us to handle quotes properly as long as we always use
-# use single quotes and escape_quotes.
-escape_quotes = $(subst ','\'',$(1))
-# This comment is here just to include a ' to unconfuse syntax highlighting.
-# Define an escape_vars function to escape '$' variable syntax.
-# This allows us to read/write command lines with shell variables (e.g.
-# $LD_LIBRARY_PATH), without triggering make substitution.
-escape_vars = $(subst $$,$$$$,$(1))
-# Helper that expands to a shell command to echo a string exactly as it is in
-# make. This uses printf instead of echo because printf's behaviour with respect
-# to escape sequences is more portable than echo's across different shells
-# (e.g., dash, bash).
-exact_echo = printf '%s\n' '$(call escape_quotes,$(1))'
-
-# Helper to compare the command we're about to run against the command
-# we logged the last time we ran the command.  Produces an empty
-# string (false) when the commands match.
-# Tricky point: Make has no string-equality test function.
-# The kernel uses the following, but it seems like it would have false
-# positives, where one string reordered its arguments.
-#   arg_check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \
-#                       $(filter-out $(cmd_$@), $(cmd_$(1))))
-# We instead substitute each for the empty string into the other, and
-# say they're equal if both substitutions produce the empty string.
-# .d files contain ? instead of spaces, take that into account.
-command_changed = $(or $(subst $(cmd_$(1)),,$(cmd_$(call replace_spaces,$@))),\
-                       $(subst $(cmd_$(call replace_spaces,$@)),,$(cmd_$(1))))
-
-# Helper that is non-empty when a prerequisite changes.
-# Normally make does this implicitly, but we force rules to always run
-# so we can check their command lines.
-#   $? -- new prerequisites
-#   $| -- order-only dependencies
-prereq_changed = $(filter-out FORCE_DO_CMD,$(filter-out $|,$?))
-
-# Helper that executes all postbuilds, and deletes the output file when done
-# if any of the postbuilds failed.
-define do_postbuilds
-  @E=0;\
-  for p in $(POSTBUILDS); do\
-    eval $$p;\
-    F=$$?;\
-    if [ $$F -ne 0 ]; then\
-      E=$$F;\
-    fi;\
-  done;\
-  if [ $$E -ne 0 ]; then\
-    rm -rf "$@";\
-    exit $$E;\
-  fi
-endef
-
-# do_cmd: run a command via the above cmd_foo names, if necessary.
-# Should always run for a given target to handle command-line changes.
-# Second argument, if non-zero, makes it do asm/C/C++ dependency munging.
-# Third argument, if non-zero, makes it do POSTBUILDS processing.
-# Note: We intentionally do NOT call dirx for depfile, since it contains ? for
-# spaces already and dirx strips the ? characters.
-define do_cmd
-$(if $(or $(command_changed),$(prereq_changed)),
-  @$(call exact_echo,  $($(quiet)cmd_$(1)))
-  @mkdir -p "$(call dirx,$@)" "$(dir $(depfile))"
-  $(if $(findstring flock,$(word 2,$(cmd_$1))),
-    @$(cmd_$(1))
-    @echo "  $(quiet_cmd_$(1)): Finished",
-    @$(cmd_$(1))
-  )
-  @$(call exact_echo,$(call escape_vars,cmd_$(call replace_spaces,$@) := $(cmd_$(1)))) > $(depfile)
-  @$(if $(2),$(fixup_dep))
-  $(if $(and $(3), $(POSTBUILDS)),
-    $(call do_postbuilds)
-  )
-)
-endef
-
-# Declare "all" target first so it is the default, even though we don't have the
-# deps yet.
-.PHONY: all
-all:
-
-# Use FORCE_DO_CMD to force a target to run.  Should be coupled with
-# do_cmd.
-.PHONY: FORCE_DO_CMD
-FORCE_DO_CMD:
-
-TOOLSET := target
-# Suffix rules, putting all outputs into $(obj).
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.c FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cc FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cpp FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cxx FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.m FORCE_DO_CMD
-       @$(call do_cmd,objc,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.mm FORCE_DO_CMD
-       @$(call do_cmd,objcxx,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.S FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.s FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-
-# Try building from generated source, too.
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.c FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cc FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cpp FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cxx FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.m FORCE_DO_CMD
-       @$(call do_cmd,objc,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.mm FORCE_DO_CMD
-       @$(call do_cmd,objcxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.S FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.s FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-
-$(obj).$(TOOLSET)/%.o: $(obj)/%.c FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.cc FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.cpp FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.cxx FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.m FORCE_DO_CMD
-       @$(call do_cmd,objc,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.mm FORCE_DO_CMD
-       @$(call do_cmd,objcxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.S FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.s FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-
-
-ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
-    $(findstring $(join ^,$(prefix)),\
-                 $(join ^,src/libuv/run-benchmarks.target.mk)))),)
-  include src/libuv/run-benchmarks.target.mk
-endif
-ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
-    $(findstring $(join ^,$(prefix)),\
-                 $(join ^,src/libuv/run-tests.target.mk)))),)
-  include src/libuv/run-tests.target.mk
-endif
-ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
-    $(findstring $(join ^,$(prefix)),\
-                 $(join ^,src/libuv/uv.target.mk)))),)
-  include src/libuv/uv.target.mk
-endif
-
-quiet_cmd_regen_makefile = ACTION Regenerating $@
-cmd_regen_makefile = ./src/libuv/build/gyp/gyp -fmake --ignore-environment "--toplevel-dir=." "--depth=." "--generator-output=mk/libuv/ia32/mac" "-Dlibrary=static_library" "-Dtarget_arch=ia32" "-DOS=mac" src/libuv/uv.gyp
-Makefile: $(srcdir)/src/libuv/uv.gyp
-       $(call do_cmd,regen_makefile)
-
-# "all" is a concatenation of the "all" targets from all the included
-# sub-makefiles. This is just here to clarify.
-all:
-
-# Add in dependency-tracking rules.  $(all_deps) is the list of every single
-# target in our tree. Only consider the ones with .d (dependency) info:
-d_files := $(wildcard $(foreach f,$(all_deps),$(depsdir)/$(f).d))
-ifneq ($(d_files),)
-  # Rather than include each individual .d file, concatenate them into a
-  # single file which make is able to load faster.  We split this into
-  # commands that take 1000 files at a time to avoid overflowing the
-  # command line.
-  $(shell cat $(wordlist 1,1000,$(d_files)) > $(depsdir)/all.deps)
-
-  ifneq ($(word 1001,$(d_files)),)
-    $(error Found unprocessed dependency files (gyp didn't generate enough rules!))
-  endif
-
-  # make looks for ways to re-generate included makefiles, but in our case, we
-  # don't have a direct way. Explicitly telling make that it has nothing to do
-  # for them makes it go faster.
-  $(depsdir)/all.deps: ;
-
-  include $(depsdir)/all.deps
-endif
index 7eb894b23ef66b97de39288e0fa4d5794b5e2a97..bd4059840ea8a6efa2825d0f5ea849e60f15b16b 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python
 # Generated by gyp. Do not edit.
 # Copyright (c) 2011 Google Inc. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
@@ -17,10 +17,12 @@ import string
 import subprocess
 import sys
 
+
 def main(args):
   executor = MacTool()
   executor.Dispatch(args)
 
+
 class MacTool(object):
   """This class performs all the Mac tooling steps. The methods can either be
   executed directly, or dispatched from an argument list."""
@@ -74,12 +76,14 @@ class MacTool(object):
     if not plist:
       return
 
+    # Only create PkgInfo for executable types.
+    package_type = plist['CFBundlePackageType']
+    if package_type != 'APPL':
+      return
+
     # The format of PkgInfo is eight characters, representing the bundle type
-    # and bundle signature, each four characters. If either is missing, four
+    # and bundle signature, each four characters. If that is missing, four
     # '?' characters are used instead.
-    package_type = plist['CFBundlePackageType']
-    if len(package_type) != 4:
-      package_type = '?' * 4
     signature_code = plist['CFBundleSignature']
     if len(signature_code) != 4:
       signature_code = '?' * 4
@@ -184,5 +188,6 @@ class MacTool(object):
     else:
       return None
 
+
 if __name__ == '__main__':
   sys.exit(main(sys.argv[1:]))
index 64d150f24fc1344ac0cfd3bca8ff2647279f749f..b8cc0a1c483ec1c92b32eced1e061ec00b73d65d 100644 (file)
@@ -2,31 +2,77 @@
 
 TOOLSET := target
 TARGET := run-benchmarks
-DEFS_Default := '-D_LARGEFILE_SOURCE' \
+DEFS_Debug := '-D_LARGEFILE_SOURCE' \
        '-D_FILE_OFFSET_BITS=64' \
        '-D_GNU_SOURCE' \
-       '-DEIO_STACKSIZE=262144'
+       '-DEIO_STACKSIZE=262144' \
+       '-DDEBUG' \
+       '-D_DEBUG' \
+       '-DEV_VERIFY=2'
 
 # Flags passed to all source files.
-CFLAGS_Default := -fasm-blocks \
-       -mpascal-strings \
-       -Os \
+CFLAGS_Debug := -Os \
        -gdwarf-2 \
-       -arch i386
+       -fvisibility=hidden \
+       -Wnewline-eof \
+       -arch i386 \
+       -fno-strict-aliasing \
+       -Wall \
+       -Wendif-labels \
+       -W \
+       -Wno-unused-parameter
 
 # Flags passed to only C files.
-CFLAGS_C_Default := 
+CFLAGS_C_Debug := 
 
 # Flags passed to only C++ files.
-CFLAGS_CC_Default := 
+CFLAGS_CC_Debug := -fno-rtti \
+       -fno-exceptions \
+       -fvisibility-inlines-hidden \
+       -fno-threadsafe-statics
 
 # Flags passed to only ObjC files.
-CFLAGS_OBJC_Default := 
+CFLAGS_OBJC_Debug := 
 
 # Flags passed to only ObjC++ files.
-CFLAGS_OBJCC_Default := 
+CFLAGS_OBJCC_Debug := 
 
-INCS_Default := -I$(srcdir)/src/libuv/include
+INCS_Debug := -I$(srcdir)/src/libuv/include
+
+DEFS_Release := '-D_LARGEFILE_SOURCE' \
+       '-D_FILE_OFFSET_BITS=64' \
+       '-D_GNU_SOURCE' \
+       '-DEIO_STACKSIZE=262144' \
+       '-DNDEBUG'
+
+# Flags passed to all source files.
+CFLAGS_Release := -Os \
+       -gdwarf-2 \
+       -fvisibility=hidden \
+       -Wnewline-eof \
+       -arch i386 \
+       -fno-strict-aliasing \
+       -Wall \
+       -Wendif-labels \
+       -W \
+       -Wno-unused-parameter
+
+# Flags passed to only C files.
+CFLAGS_C_Release := 
+
+# Flags passed to only C++ files.
+CFLAGS_CC_Release := -fno-rtti \
+       -fno-exceptions \
+       -fvisibility-inlines-hidden \
+       -fno-threadsafe-statics
+
+# Flags passed to only ObjC files.
+CFLAGS_OBJC_Release := 
+
+# Flags passed to only ObjC++ files.
+CFLAGS_OBJCC_Release := 
+
+INCS_Release := -I$(srcdir)/src/libuv/include
 
 OBJS := $(obj).target/$(TARGET)/src/libuv/test/benchmark-ares.o \
        $(obj).target/$(TARGET)/src/libuv/test/benchmark-getaddrinfo.o \
@@ -35,6 +81,7 @@ OBJS := $(obj).target/$(TARGET)/src/libuv/test/benchmark-ares.o \
        $(obj).target/$(TARGET)/src/libuv/test/benchmark-pump.o \
        $(obj).target/$(TARGET)/src/libuv/test/benchmark-sizes.o \
        $(obj).target/$(TARGET)/src/libuv/test/benchmark-spawn.o \
+       $(obj).target/$(TARGET)/src/libuv/test/benchmark-thread.o \
        $(obj).target/$(TARGET)/src/libuv/test/benchmark-tcp-write-batch.o \
        $(obj).target/$(TARGET)/src/libuv/test/benchmark-udp-packet-storm.o \
        $(obj).target/$(TARGET)/src/libuv/test/dns-server.o \
@@ -53,10 +100,10 @@ $(OBJS): | $(builddir)/libuv.a
 # CFLAGS et al overrides must be target-local.
 # See "Target-specific Variable Values" in the GNU Make manual.
 $(OBJS): TOOLSET := $(TOOLSET)
-$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
-$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
-$(OBJS): GYP_OBJCFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE)) $(CFLAGS_OBJC_$(BUILDTYPE))
-$(OBJS): GYP_OBJCXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE)) $(CFLAGS_OBJCC_$(BUILDTYPE))
+$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
+$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
+$(OBJS): GYP_OBJCFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE)) $(CFLAGS_OBJC_$(BUILDTYPE))
+$(OBJS): GYP_OBJCXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE)) $(CFLAGS_OBJCC_$(BUILDTYPE))
 
 # Suffix rules, putting all outputs into $(obj).
 
@@ -73,7 +120,12 @@ $(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.c FORCE_DO_CMD
 
 # End of this set of suffix rules
 ### Rules for final target.
-LDFLAGS_Default := -arch i386 \
+LDFLAGS_Debug := -Wl,-search_paths_first \
+       -arch i386 \
+       -L$(builddir)
+
+LDFLAGS_Release := -Wl,-search_paths_first \
+       -arch i386 \
        -L$(builddir)
 
 LIBS := -framework Carbon \
index 5a5730b0f65845c7386d0f6c1565aa70b7bf4dfd..be0c2c60856339d4ebd5ffe72969bab27fb998b2 100644 (file)
@@ -2,42 +2,91 @@
 
 TOOLSET := target
 TARGET := run-tests
-DEFS_Default := '-D_LARGEFILE_SOURCE' \
+DEFS_Debug := '-D_LARGEFILE_SOURCE' \
        '-D_FILE_OFFSET_BITS=64' \
        '-D_GNU_SOURCE' \
-       '-DEIO_STACKSIZE=262144'
+       '-DEIO_STACKSIZE=262144' \
+       '-DDEBUG' \
+       '-D_DEBUG' \
+       '-DEV_VERIFY=2'
 
 # Flags passed to all source files.
-CFLAGS_Default := -fasm-blocks \
-       -mpascal-strings \
-       -Os \
+CFLAGS_Debug := -Os \
        -gdwarf-2 \
-       -arch i386
+       -fvisibility=hidden \
+       -Wnewline-eof \
+       -arch i386 \
+       -fno-strict-aliasing \
+       -Wall \
+       -Wendif-labels \
+       -W \
+       -Wno-unused-parameter
 
 # Flags passed to only C files.
-CFLAGS_C_Default := 
+CFLAGS_C_Debug := 
 
 # Flags passed to only C++ files.
-CFLAGS_CC_Default := 
+CFLAGS_CC_Debug := -fno-rtti \
+       -fno-exceptions \
+       -fvisibility-inlines-hidden \
+       -fno-threadsafe-statics
 
 # Flags passed to only ObjC files.
-CFLAGS_OBJC_Default := 
+CFLAGS_OBJC_Debug := 
 
 # Flags passed to only ObjC++ files.
-CFLAGS_OBJCC_Default := 
+CFLAGS_OBJCC_Debug := 
 
-INCS_Default := -I$(srcdir)/src/libuv/include
+INCS_Debug := -I$(srcdir)/src/libuv/include
+
+DEFS_Release := '-D_LARGEFILE_SOURCE' \
+       '-D_FILE_OFFSET_BITS=64' \
+       '-D_GNU_SOURCE' \
+       '-DEIO_STACKSIZE=262144' \
+       '-DNDEBUG'
+
+# Flags passed to all source files.
+CFLAGS_Release := -Os \
+       -gdwarf-2 \
+       -fvisibility=hidden \
+       -Wnewline-eof \
+       -arch i386 \
+       -fno-strict-aliasing \
+       -Wall \
+       -Wendif-labels \
+       -W \
+       -Wno-unused-parameter
+
+# Flags passed to only C files.
+CFLAGS_C_Release := 
+
+# Flags passed to only C++ files.
+CFLAGS_CC_Release := -fno-rtti \
+       -fno-exceptions \
+       -fvisibility-inlines-hidden \
+       -fno-threadsafe-statics
+
+# Flags passed to only ObjC files.
+CFLAGS_OBJC_Release := 
+
+# Flags passed to only ObjC++ files.
+CFLAGS_OBJCC_Release := 
+
+INCS_Release := -I$(srcdir)/src/libuv/include
 
 OBJS := $(obj).target/$(TARGET)/src/libuv/test/blackhole-server.o \
        $(obj).target/$(TARGET)/src/libuv/test/echo-server.o \
        $(obj).target/$(TARGET)/src/libuv/test/run-tests.o \
        $(obj).target/$(TARGET)/src/libuv/test/runner.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-get-loadavg.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-util.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-async.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-error.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-callback-stack.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-connection-fail.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-cwd-and-chdir.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-delayed-accept.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-eio-overflow.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-fail-always.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-fs.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-fs-event.o \
@@ -49,12 +98,15 @@ OBJS := $(obj).target/$(TARGET)/src/libuv/test/blackhole-server.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-hrtime.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-idle.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-ipc.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-ipc-threads.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-loop-handles.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-multiple-listen.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-pass-always.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-ping-pong.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-pipe-bind-error.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-pipe-connect-error.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-platform-output.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-process-title.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-ref.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-shutdown-eof.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-spawn.o \
@@ -69,13 +121,17 @@ OBJS := $(obj).target/$(TARGET)/src/libuv/test/blackhole-server.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-tcp-write-to-half-open-connection.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-tcp-writealot.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-threadpool.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-mutexes.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-thread.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-timer-again.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-timer.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-tty.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-udp-dgram-too-big.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-udp-ipv6.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-udp-options.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-udp-send-and-recv.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-udp-multicast-join.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-counters-init.o \
        $(obj).target/$(TARGET)/src/libuv/test/runner-unix.o
 
 # Add to the list of files we specially track dependencies for.
@@ -87,10 +143,10 @@ $(OBJS): | $(builddir)/libuv.a
 # CFLAGS et al overrides must be target-local.
 # See "Target-specific Variable Values" in the GNU Make manual.
 $(OBJS): TOOLSET := $(TOOLSET)
-$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
-$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
-$(OBJS): GYP_OBJCFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE)) $(CFLAGS_OBJC_$(BUILDTYPE))
-$(OBJS): GYP_OBJCXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE)) $(CFLAGS_OBJCC_$(BUILDTYPE))
+$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
+$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
+$(OBJS): GYP_OBJCFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE)) $(CFLAGS_OBJC_$(BUILDTYPE))
+$(OBJS): GYP_OBJCXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE)) $(CFLAGS_OBJCC_$(BUILDTYPE))
 
 # Suffix rules, putting all outputs into $(obj).
 
@@ -107,7 +163,12 @@ $(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.c FORCE_DO_CMD
 
 # End of this set of suffix rules
 ### Rules for final target.
-LDFLAGS_Default := -arch i386 \
+LDFLAGS_Debug := -Wl,-search_paths_first \
+       -arch i386 \
+       -L$(builddir)
+
+LDFLAGS_Release := -Wl,-search_paths_first \
+       -arch i386 \
        -L$(builddir)
 
 LIBS := -framework Carbon \
index 28f911f4dc70f8d331cc4f1e60024ddf57ee915e..98386060982485385f87aab97f6a571ef67e2bc5 100644 (file)
@@ -2,34 +2,87 @@
 
 TOOLSET := target
 TARGET := uv
-DEFS_Default := '-D_LARGEFILE_SOURCE' \
+DEFS_Debug := '-D_LARGEFILE_SOURCE' \
        '-D_FILE_OFFSET_BITS=64' \
        '-D_GNU_SOURCE' \
        '-DEIO_STACKSIZE=262144' \
        '-DHAVE_CONFIG_H' \
        '-DEV_CONFIG_H="config_darwin.h"' \
-       '-DEIO_CONFIG_H="config_darwin.h"'
+       '-DEIO_CONFIG_H="config_darwin.h"' \
+       '-DDEBUG' \
+       '-D_DEBUG' \
+       '-DEV_VERIFY=2'
 
 # Flags passed to all source files.
-CFLAGS_Default := -fasm-blocks \
-       -mpascal-strings \
-       -Os \
+CFLAGS_Debug := -Os \
        -gdwarf-2 \
-       -arch i386
+       -fvisibility=hidden \
+       -Wnewline-eof \
+       -arch i386 \
+       -fno-strict-aliasing \
+       -Wall \
+       -Wendif-labels \
+       -W \
+       -Wno-unused-parameter
 
 # Flags passed to only C files.
-CFLAGS_C_Default := 
+CFLAGS_C_Debug := 
 
 # Flags passed to only C++ files.
-CFLAGS_CC_Default := 
+CFLAGS_CC_Debug := -fno-rtti \
+       -fno-exceptions \
+       -fvisibility-inlines-hidden \
+       -fno-threadsafe-statics
 
 # Flags passed to only ObjC files.
-CFLAGS_OBJC_Default := 
+CFLAGS_OBJC_Debug := 
 
 # Flags passed to only ObjC++ files.
-CFLAGS_OBJCC_Default := 
+CFLAGS_OBJCC_Debug := 
 
-INCS_Default := -I$(srcdir)/src/libuv/include \
+INCS_Debug := -I$(srcdir)/src/libuv/include \
+       -I$(srcdir)/src/libuv/include/uv-private \
+       -I$(srcdir)/src/libuv/src \
+       -I$(srcdir)/src/libuv/src/unix/ev \
+       -I$(srcdir)/src/libuv/src/ares/config_darwin
+
+DEFS_Release := '-D_LARGEFILE_SOURCE' \
+       '-D_FILE_OFFSET_BITS=64' \
+       '-D_GNU_SOURCE' \
+       '-DEIO_STACKSIZE=262144' \
+       '-DHAVE_CONFIG_H' \
+       '-DEV_CONFIG_H="config_darwin.h"' \
+       '-DEIO_CONFIG_H="config_darwin.h"' \
+       '-DNDEBUG'
+
+# Flags passed to all source files.
+CFLAGS_Release := -Os \
+       -gdwarf-2 \
+       -fvisibility=hidden \
+       -Wnewline-eof \
+       -arch i386 \
+       -fno-strict-aliasing \
+       -Wall \
+       -Wendif-labels \
+       -W \
+       -Wno-unused-parameter
+
+# Flags passed to only C files.
+CFLAGS_C_Release := 
+
+# Flags passed to only C++ files.
+CFLAGS_CC_Release := -fno-rtti \
+       -fno-exceptions \
+       -fvisibility-inlines-hidden \
+       -fno-threadsafe-statics
+
+# Flags passed to only ObjC files.
+CFLAGS_OBJC_Release := 
+
+# Flags passed to only ObjC++ files.
+CFLAGS_OBJCC_Release := 
+
+INCS_Release := -I$(srcdir)/src/libuv/include \
        -I$(srcdir)/src/libuv/include/uv-private \
        -I$(srcdir)/src/libuv/src \
        -I$(srcdir)/src/libuv/src/unix/ev \
@@ -91,6 +144,7 @@ OBJS := $(obj).target/$(TARGET)/src/libuv/src/uv-common.o \
        $(obj).target/$(TARGET)/src/libuv/src/unix/cares.o \
        $(obj).target/$(TARGET)/src/libuv/src/unix/dl.o \
        $(obj).target/$(TARGET)/src/libuv/src/unix/error.o \
+       $(obj).target/$(TARGET)/src/libuv/src/unix/thread.o \
        $(obj).target/$(TARGET)/src/libuv/src/unix/process.o \
        $(obj).target/$(TARGET)/src/libuv/src/unix/eio/eio.o \
        $(obj).target/$(TARGET)/src/libuv/src/unix/ev/ev.o \
@@ -103,10 +157,10 @@ all_deps += $(OBJS)
 # CFLAGS et al overrides must be target-local.
 # See "Target-specific Variable Values" in the GNU Make manual.
 $(OBJS): TOOLSET := $(TOOLSET)
-$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
-$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
-$(OBJS): GYP_OBJCFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE)) $(CFLAGS_OBJC_$(BUILDTYPE))
-$(OBJS): GYP_OBJCXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE)) $(CFLAGS_OBJCC_$(BUILDTYPE))
+$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
+$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
+$(OBJS): GYP_OBJCFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE)) $(CFLAGS_OBJC_$(BUILDTYPE))
+$(OBJS): GYP_OBJCXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE)) $(CFLAGS_OBJCC_$(BUILDTYPE))
 
 # Suffix rules, putting all outputs into $(obj).
 
@@ -123,7 +177,10 @@ $(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.c FORCE_DO_CMD
 
 # End of this set of suffix rules
 ### Rules for final target.
-LDFLAGS_Default := -arch i386 \
+LDFLAGS_Debug := -arch i386 \
+       -L$(builddir)
+
+LDFLAGS_Release := -arch i386 \
        -L$(builddir)
 
 LIBS := -lm
index 66a9e7d2058215c3eef4ee7178c7fbbed87dd9a2..4369fdb9a23b3f2481d18b80fad86cac7405031a 100644 (file)
@@ -8,6 +8,7 @@ MAKEFLAGS=-r
 
 # The source directory tree.
 srcdir := ../../../..
+abs_srcdir := $(abspath $(srcdir))
 
 # The name of the builddir.
 builddir_name ?= out
@@ -20,7 +21,7 @@ else
 endif
 
 # Specify BUILDTYPE=Release on the command line for a release build.
-BUILDTYPE ?= Default
+BUILDTYPE ?= Debug
 
 # Directory all our build output goes into.
 # Note that this must be two directories beneath src/ for unit tests to pass,
@@ -252,8 +253,8 @@ $(if $(or $(command_changed),$(prereq_changed)),
 )
 endef
 
-# Declare "all" target first so it is the default, even though we don't have the
-# deps yet.
+# Declare the "all" target first so it is the default,
+# even though we don't have the deps yet.
 .PHONY: all
 all:
 
@@ -321,9 +322,9 @@ ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
   include src/libuv/uv.target.mk
 endif
 
-quiet_cmd_regen_makefile = ACTION Regenerating $@
-cmd_regen_makefile = ./src/libuv/build/gyp/gyp -fmake --ignore-environment "--toplevel-dir=." "--depth=." "--generator-output=mk/libuv/ia32/unix" "-Dlibrary=static_library" "-Dtarget_arch=ia32" "-DOS=linux" src/libuv/uv.gyp
-Makefile: $(srcdir)/src/libuv/uv.gyp
+#quiet_cmd_regen_makefile = ACTION Regenerating $@
+#cmd_regen_makefile = ./src/libuv/build/gyp/gyp -fmake --ignore-environment "--toplevel-dir=." -Isrc/libuv/common.gypi "--depth=." "--generator-output=mk/libuv/ia32/unix" "-Ddefault_configuration=Default" "-Dcomponent=static_library" "-Dlibrary=static_library" "-Dtarget_arch=ia32" "-DOS=linux" src/libuv/uv.gyp
+#Makefile: $(srcdir)/src/libuv/uv.gyp $(srcdir)/src/libuv/common.gypi
 #      $(call do_cmd,regen_makefile)
 
 # "all" is a concatenation of the "all" targets from all the included
diff --git a/mk/libuv/ia32/unix/Makefile-e b/mk/libuv/ia32/unix/Makefile-e
deleted file mode 100644 (file)
index ffbb106..0000000
+++ /dev/null
@@ -1,353 +0,0 @@
-# We borrow heavily from the kernel build setup, though we are simpler since
-# we don't have Kconfig tweaking settings on us.
-
-# The implicit make rules have it looking for RCS files, among other things.
-# We instead explicitly write all the rules we care about.
-# It's even quicker (saves ~200ms) to pass -r on the command line.
-MAKEFLAGS=-r
-
-# The source directory tree.
-srcdir := ../../../..
-
-# The name of the builddir.
-builddir_name ?= out
-
-# The V=1 flag on command line makes us verbosely print command lines.
-ifdef V
-  quiet=
-else
-  quiet=quiet_
-endif
-
-# Specify BUILDTYPE=Release on the command line for a release build.
-BUILDTYPE ?= Default
-
-# Directory all our build output goes into.
-# Note that this must be two directories beneath src/ for unit tests to pass,
-# as they reach into the src/ directory for data with relative paths.
-builddir ?= $(builddir_name)/$(BUILDTYPE)
-abs_builddir := $(abspath $(builddir))
-depsdir := $(builddir)/.deps
-
-# Object output directory.
-obj := $(builddir)/obj
-abs_obj := $(abspath $(obj))
-
-# We build up a list of every single one of the targets so we can slurp in the
-# generated dependency rule Makefiles in one pass.
-all_deps :=
-
-
-
-# C++ apps need to be linked with g++.
-#
-# Note: flock is used to seralize linking. Linking is a memory-intensive
-# process so running parallel links can often lead to thrashing.  To disable
-# the serialization, override LINK via an envrionment variable as follows:
-#
-#   export LINK=g++
-#
-# This will allow make to invoke N linker processes as specified in -jN.
-LINK ?= flock $(builddir)/linker.lock $(CXX)
-
-CC.target ?= $(CC)
-CFLAGS.target ?= $(CFLAGS)
-CXX.target ?= $(CXX)
-CXXFLAGS.target ?= $(CXXFLAGS)
-LINK.target ?= $(LINK)
-LDFLAGS.target ?= $(LDFLAGS) 
-AR.target ?= $(AR)
-ARFLAGS.target ?= crsT
-
-# N.B.: the logic of which commands to run should match the computation done
-# in gyp's make.py where ARFLAGS.host etc. is computed.
-# TODO(evan): move all cross-compilation logic to gyp-time so we don't need
-# to replicate this environment fallback in make as well.
-CC.host ?= gcc
-CFLAGS.host ?=
-CXX.host ?= g++
-CXXFLAGS.host ?=
-LINK.host ?= g++
-LDFLAGS.host ?=
-AR.host ?= ar
-ARFLAGS.host := crsT
-
-# Define a dir function that can handle spaces.
-# http://www.gnu.org/software/make/manual/make.html#Syntax-of-Functions
-# "leading spaces cannot appear in the text of the first argument as written.
-# These characters can be put into the argument value by variable substitution."
-empty :=
-space := $(empty) $(empty)
-
-# http://stackoverflow.com/questions/1189781/using-make-dir-or-notdir-on-a-path-with-spaces
-replace_spaces = $(subst $(space),?,$1)
-unreplace_spaces = $(subst ?,$(space),$1)
-dirx = $(call unreplace_spaces,$(dir $(call replace_spaces,$1)))
-
-# Flags to make gcc output dependency info.  Note that you need to be
-# careful here to use the flags that ccache and distcc can understand.
-# We write to a dep file on the side first and then rename at the end
-# so we can't end up with a broken dep file.
-depfile = $(depsdir)/$(call replace_spaces,$@).d
-DEPFLAGS = -MMD -MF $(depfile).raw
-
-# We have to fixup the deps output in a few ways.
-# (1) the file output should mention the proper .o file.
-# ccache or distcc lose the path to the target, so we convert a rule of
-# the form:
-#   foobar.o: DEP1 DEP2
-# into
-#   path/to/foobar.o: DEP1 DEP2
-# (2) we want missing files not to cause us to fail to build.
-# We want to rewrite
-#   foobar.o: DEP1 DEP2 \
-#               DEP3
-# to
-#   DEP1:
-#   DEP2:
-#   DEP3:
-# so if the files are missing, they're just considered phony rules.
-# We have to do some pretty insane escaping to get those backslashes
-# and dollar signs past make, the shell, and sed at the same time.
-# Doesn't work with spaces, but that's fine: .d files have spaces in
-# their names replaced with other characters.
-define fixup_dep
-# The depfile may not exist if the input file didn't have any #includes.
-touch $(depfile).raw
-# Fixup path as in (1).
-sed -e "s|^$(notdir $@)|$@|" $(depfile).raw >> $(depfile)
-# Add extra rules as in (2).
-# We remove slashes and replace spaces with new lines;
-# remove blank lines;
-# delete the first line and append a colon to the remaining lines.
-sed -e 's|\\||' -e 'y| |\n|' $(depfile).raw |\
-  grep -v '^$$'                             |\
-  sed -e 1d -e 's|$$|:|'                     \
-    >> $(depfile)
-rm $(depfile).raw
-endef
-
-# Command definitions:
-# - cmd_foo is the actual command to run;
-# - quiet_cmd_foo is the brief-output summary of the command.
-
-quiet_cmd_cc = CC($(TOOLSET)) $@
-cmd_cc = $(CC.$(TOOLSET)) $(GYP_CFLAGS) $(DEPFLAGS) $(CFLAGS.$(TOOLSET)) -c -o $@ $<
-
-quiet_cmd_cxx = CXX($(TOOLSET)) $@
-cmd_cxx = $(CXX.$(TOOLSET)) $(GYP_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $<
-
-quiet_cmd_touch = TOUCH $@
-cmd_touch = touch $@
-
-quiet_cmd_copy = COPY $@
-# send stderr to /dev/null to ignore messages when linking directories.
-cmd_copy = ln -f "$<" "$@" 2>/dev/null || (rm -rf "$@" && cp -af "$<" "$@")
-
-quiet_cmd_alink = AR($(TOOLSET)) $@
-cmd_alink = rm -f $@ && $(AR.$(TOOLSET)) $(ARFLAGS.$(TOOLSET)) $@ $(filter %.o,$^)
-
-# Due to circular dependencies between libraries :(, we wrap the
-# special "figure out circular dependencies" flags around the entire
-# input list during linking.
-quiet_cmd_link = LINK($(TOOLSET)) $@
-cmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ -Wl,--start-group $(LD_INPUTS) -Wl,--end-group $(LIBS)
-
-# We support two kinds of shared objects (.so):
-# 1) shared_library, which is just bundling together many dependent libraries
-# into a link line.
-# 2) loadable_module, which is generating a module intended for dlopen().
-#
-# They differ only slightly:
-# In the former case, we want to package all dependent code into the .so.
-# In the latter case, we want to package just the API exposed by the
-# outermost module.
-# This means shared_library uses --whole-archive, while loadable_module doesn't.
-# (Note that --whole-archive is incompatible with the --start-group used in
-# normal linking.)
-
-# Other shared-object link notes:
-# - Set SONAME to the library filename so our binaries don't reference
-# the local, absolute paths used on the link command-line.
-quiet_cmd_solink = SOLINK($(TOOLSET)) $@
-cmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--whole-archive $(LD_INPUTS) -Wl,--no-whole-archive $(LIBS)
-
-quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@
-cmd_solink_module = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--start-group $(filter-out FORCE_DO_CMD, $^) -Wl,--end-group $(LIBS)
-
-
-# Define an escape_quotes function to escape single quotes.
-# This allows us to handle quotes properly as long as we always use
-# use single quotes and escape_quotes.
-escape_quotes = $(subst ','\'',$(1))
-# This comment is here just to include a ' to unconfuse syntax highlighting.
-# Define an escape_vars function to escape '$' variable syntax.
-# This allows us to read/write command lines with shell variables (e.g.
-# $LD_LIBRARY_PATH), without triggering make substitution.
-escape_vars = $(subst $$,$$$$,$(1))
-# Helper that expands to a shell command to echo a string exactly as it is in
-# make. This uses printf instead of echo because printf's behaviour with respect
-# to escape sequences is more portable than echo's across different shells
-# (e.g., dash, bash).
-exact_echo = printf '%s\n' '$(call escape_quotes,$(1))'
-
-# Helper to compare the command we're about to run against the command
-# we logged the last time we ran the command.  Produces an empty
-# string (false) when the commands match.
-# Tricky point: Make has no string-equality test function.
-# The kernel uses the following, but it seems like it would have false
-# positives, where one string reordered its arguments.
-#   arg_check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \
-#                       $(filter-out $(cmd_$@), $(cmd_$(1))))
-# We instead substitute each for the empty string into the other, and
-# say they're equal if both substitutions produce the empty string.
-# .d files contain ? instead of spaces, take that into account.
-command_changed = $(or $(subst $(cmd_$(1)),,$(cmd_$(call replace_spaces,$@))),\
-                       $(subst $(cmd_$(call replace_spaces,$@)),,$(cmd_$(1))))
-
-# Helper that is non-empty when a prerequisite changes.
-# Normally make does this implicitly, but we force rules to always run
-# so we can check their command lines.
-#   $? -- new prerequisites
-#   $| -- order-only dependencies
-prereq_changed = $(filter-out FORCE_DO_CMD,$(filter-out $|,$?))
-
-# Helper that executes all postbuilds, and deletes the output file when done
-# if any of the postbuilds failed.
-define do_postbuilds
-  @E=0;\
-  for p in $(POSTBUILDS); do\
-    eval $$p;\
-    F=$$?;\
-    if [ $$F -ne 0 ]; then\
-      E=$$F;\
-    fi;\
-  done;\
-  if [ $$E -ne 0 ]; then\
-    rm -rf "$@";\
-    exit $$E;\
-  fi
-endef
-
-# do_cmd: run a command via the above cmd_foo names, if necessary.
-# Should always run for a given target to handle command-line changes.
-# Second argument, if non-zero, makes it do asm/C/C++ dependency munging.
-# Third argument, if non-zero, makes it do POSTBUILDS processing.
-# Note: We intentionally do NOT call dirx for depfile, since it contains ? for
-# spaces already and dirx strips the ? characters.
-define do_cmd
-$(if $(or $(command_changed),$(prereq_changed)),
-  @$(call exact_echo,  $($(quiet)cmd_$(1)))
-  @mkdir -p "$(call dirx,$@)" "$(dir $(depfile))"
-  $(if $(findstring flock,$(word 1,$(cmd_$1))),
-    @$(cmd_$(1))
-    @echo "  $(quiet_cmd_$(1)): Finished",
-    @$(cmd_$(1))
-  )
-  @$(call exact_echo,$(call escape_vars,cmd_$(call replace_spaces,$@) := $(cmd_$(1)))) > $(depfile)
-  @$(if $(2),$(fixup_dep))
-  $(if $(and $(3), $(POSTBUILDS)),
-    $(call do_postbuilds)
-  )
-)
-endef
-
-# Declare "all" target first so it is the default, even though we don't have the
-# deps yet.
-.PHONY: all
-all:
-
-# Use FORCE_DO_CMD to force a target to run.  Should be coupled with
-# do_cmd.
-.PHONY: FORCE_DO_CMD
-FORCE_DO_CMD:
-
-TOOLSET := target
-# Suffix rules, putting all outputs into $(obj).
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.c FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cc FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cpp FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cxx FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.S FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.s FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-
-# Try building from generated source, too.
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.c FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cc FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cpp FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cxx FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.S FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.s FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-
-$(obj).$(TOOLSET)/%.o: $(obj)/%.c FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.cc FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.cpp FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.cxx FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.S FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.s FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-
-
-ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
-    $(findstring $(join ^,$(prefix)),\
-                 $(join ^,src/libuv/run-benchmarks.target.mk)))),)
-  include src/libuv/run-benchmarks.target.mk
-endif
-ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
-    $(findstring $(join ^,$(prefix)),\
-                 $(join ^,src/libuv/run-tests.target.mk)))),)
-  include src/libuv/run-tests.target.mk
-endif
-ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
-    $(findstring $(join ^,$(prefix)),\
-                 $(join ^,src/libuv/uv.target.mk)))),)
-  include src/libuv/uv.target.mk
-endif
-
-quiet_cmd_regen_makefile = ACTION Regenerating $@
-cmd_regen_makefile = ./src/libuv/build/gyp/gyp -fmake --ignore-environment "--toplevel-dir=." "--depth=." "--generator-output=mk/libuv/ia32/unix" "-Dlibrary=static_library" "-Dtarget_arch=ia32" "-DOS=linux" src/libuv/uv.gyp
-Makefile: $(srcdir)/src/libuv/uv.gyp
-       $(call do_cmd,regen_makefile)
-
-# "all" is a concatenation of the "all" targets from all the included
-# sub-makefiles. This is just here to clarify.
-all:
-
-# Add in dependency-tracking rules.  $(all_deps) is the list of every single
-# target in our tree. Only consider the ones with .d (dependency) info:
-d_files := $(wildcard $(foreach f,$(all_deps),$(depsdir)/$(f).d))
-ifneq ($(d_files),)
-  # Rather than include each individual .d file, concatenate them into a
-  # single file which make is able to load faster.  We split this into
-  # commands that take 1000 files at a time to avoid overflowing the
-  # command line.
-  $(shell cat $(wordlist 1,1000,$(d_files)) > $(depsdir)/all.deps)
-
-  ifneq ($(word 1001,$(d_files)),)
-    $(error Found unprocessed dependency files (gyp didn't generate enough rules!))
-  endif
-
-  # make looks for ways to re-generate included makefiles, but in our case, we
-  # don't have a direct way. Explicitly telling make that it has nothing to do
-  # for them makes it go faster.
-  $(depsdir)/all.deps: ;
-
-  include $(depsdir)/all.deps
-endif
index b5680d2c557c7ffc7ea924bb22fc0ea05d30fba4..25b01014e79d4d77388813a41830e8d1ad32d84a 100644 (file)
@@ -2,21 +2,57 @@
 
 TOOLSET := target
 TARGET := run-benchmarks
-DEFS_Default := '-D_LARGEFILE_SOURCE' \
+DEFS_Debug := '-D_LARGEFILE_SOURCE' \
        '-D_FILE_OFFSET_BITS=64' \
        '-D_GNU_SOURCE' \
-       '-DEIO_STACKSIZE=262144'
+       '-DEIO_STACKSIZE=262144' \
+       '-DDEBUG' \
+       '-D_DEBUG' \
+       '-DEV_VERIFY=2'
 
 # Flags passed to all source files.
-CFLAGS_Default := -pthread
+CFLAGS_Debug := -pthread \
+       -Wall \
+       -ansi \
+       -pthread \
+       -fvisibility=hidden \
+       -g \
+       -O0
 
 # Flags passed to only C files.
-CFLAGS_C_Default := 
+CFLAGS_C_Debug := 
 
 # Flags passed to only C++ files.
-CFLAGS_CC_Default := 
+CFLAGS_CC_Debug := -fno-rtti \
+       -fno-exceptions
 
-INCS_Default := -I$(srcdir)/src/libuv/include
+INCS_Debug := -I$(srcdir)/src/libuv/include
+
+DEFS_Release := '-D_LARGEFILE_SOURCE' \
+       '-D_FILE_OFFSET_BITS=64' \
+       '-D_GNU_SOURCE' \
+       '-DEIO_STACKSIZE=262144' \
+       '-DNDEBUG'
+
+# Flags passed to all source files.
+CFLAGS_Release := -pthread \
+       -Wall \
+       -ansi \
+       -pthread \
+       -fvisibility=hidden \
+       -O3 \
+       -fomit-frame-pointer \
+       -fdata-sections \
+       -ffunction-sections
+
+# Flags passed to only C files.
+CFLAGS_C_Release := 
+
+# Flags passed to only C++ files.
+CFLAGS_CC_Release := -fno-rtti \
+       -fno-exceptions
+
+INCS_Release := -I$(srcdir)/src/libuv/include
 
 OBJS := $(obj).target/$(TARGET)/src/libuv/test/benchmark-ares.o \
        $(obj).target/$(TARGET)/src/libuv/test/benchmark-getaddrinfo.o \
@@ -25,6 +61,7 @@ OBJS := $(obj).target/$(TARGET)/src/libuv/test/benchmark-ares.o \
        $(obj).target/$(TARGET)/src/libuv/test/benchmark-pump.o \
        $(obj).target/$(TARGET)/src/libuv/test/benchmark-sizes.o \
        $(obj).target/$(TARGET)/src/libuv/test/benchmark-spawn.o \
+       $(obj).target/$(TARGET)/src/libuv/test/benchmark-thread.o \
        $(obj).target/$(TARGET)/src/libuv/test/benchmark-tcp-write-batch.o \
        $(obj).target/$(TARGET)/src/libuv/test/benchmark-udp-packet-storm.o \
        $(obj).target/$(TARGET)/src/libuv/test/dns-server.o \
@@ -43,8 +80,8 @@ $(OBJS): | $(obj).target/src/libuv/libuv.a
 # CFLAGS et al overrides must be target-local.
 # See "Target-specific Variable Values" in the GNU Make manual.
 $(OBJS): TOOLSET := $(TOOLSET)
-$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
-$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
+$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
+$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
 
 # Suffix rules, putting all outputs into $(obj).
 
@@ -61,7 +98,9 @@ $(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.c FORCE_DO_CMD
 
 # End of this set of suffix rules
 ### Rules for final target.
-LDFLAGS_Default := 
+LDFLAGS_Debug := -pthread
+
+LDFLAGS_Release := -pthread
 
 LIBS := -lrt
 
index 34bc8551b44da5d28326438c2f3e677563f6e3a0..a2fe0d2065e230c637dd3c17a8cb946dfad41850 100644 (file)
@@ -2,32 +2,71 @@
 
 TOOLSET := target
 TARGET := run-tests
-DEFS_Default := '-D_LARGEFILE_SOURCE' \
+DEFS_Debug := '-D_LARGEFILE_SOURCE' \
        '-D_FILE_OFFSET_BITS=64' \
        '-D_GNU_SOURCE' \
-       '-DEIO_STACKSIZE=262144'
+       '-DEIO_STACKSIZE=262144' \
+       '-DDEBUG' \
+       '-D_DEBUG' \
+       '-DEV_VERIFY=2'
 
 # Flags passed to all source files.
-CFLAGS_Default := -pthread
+CFLAGS_Debug := -pthread \
+       -Wall \
+       -ansi \
+       -pthread \
+       -fvisibility=hidden \
+       -g \
+       -O0
 
 # Flags passed to only C files.
-CFLAGS_C_Default := 
+CFLAGS_C_Debug := 
 
 # Flags passed to only C++ files.
-CFLAGS_CC_Default := 
+CFLAGS_CC_Debug := -fno-rtti \
+       -fno-exceptions
 
-INCS_Default := -I$(srcdir)/src/libuv/include
+INCS_Debug := -I$(srcdir)/src/libuv/include
+
+DEFS_Release := '-D_LARGEFILE_SOURCE' \
+       '-D_FILE_OFFSET_BITS=64' \
+       '-D_GNU_SOURCE' \
+       '-DEIO_STACKSIZE=262144' \
+       '-DNDEBUG'
+
+# Flags passed to all source files.
+CFLAGS_Release := -pthread \
+       -Wall \
+       -ansi \
+       -pthread \
+       -fvisibility=hidden \
+       -O3 \
+       -fomit-frame-pointer \
+       -fdata-sections \
+       -ffunction-sections
+
+# Flags passed to only C files.
+CFLAGS_C_Release := 
+
+# Flags passed to only C++ files.
+CFLAGS_CC_Release := -fno-rtti \
+       -fno-exceptions
+
+INCS_Release := -I$(srcdir)/src/libuv/include
 
 OBJS := $(obj).target/$(TARGET)/src/libuv/test/blackhole-server.o \
        $(obj).target/$(TARGET)/src/libuv/test/echo-server.o \
        $(obj).target/$(TARGET)/src/libuv/test/run-tests.o \
        $(obj).target/$(TARGET)/src/libuv/test/runner.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-get-loadavg.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-util.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-async.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-error.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-callback-stack.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-connection-fail.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-cwd-and-chdir.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-delayed-accept.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-eio-overflow.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-fail-always.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-fs.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-fs-event.o \
@@ -39,12 +78,15 @@ OBJS := $(obj).target/$(TARGET)/src/libuv/test/blackhole-server.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-hrtime.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-idle.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-ipc.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-ipc-threads.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-loop-handles.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-multiple-listen.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-pass-always.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-ping-pong.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-pipe-bind-error.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-pipe-connect-error.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-platform-output.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-process-title.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-ref.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-shutdown-eof.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-spawn.o \
@@ -59,13 +101,17 @@ OBJS := $(obj).target/$(TARGET)/src/libuv/test/blackhole-server.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-tcp-write-to-half-open-connection.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-tcp-writealot.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-threadpool.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-mutexes.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-thread.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-timer-again.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-timer.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-tty.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-udp-dgram-too-big.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-udp-ipv6.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-udp-options.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-udp-send-and-recv.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-udp-multicast-join.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-counters-init.o \
        $(obj).target/$(TARGET)/src/libuv/test/runner-unix.o
 
 # Add to the list of files we specially track dependencies for.
@@ -77,8 +123,8 @@ $(OBJS): | $(obj).target/src/libuv/libuv.a
 # CFLAGS et al overrides must be target-local.
 # See "Target-specific Variable Values" in the GNU Make manual.
 $(OBJS): TOOLSET := $(TOOLSET)
-$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
-$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
+$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
+$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
 
 # Suffix rules, putting all outputs into $(obj).
 
@@ -95,7 +141,9 @@ $(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.c FORCE_DO_CMD
 
 # End of this set of suffix rules
 ### Rules for final target.
-LDFLAGS_Default := 
+LDFLAGS_Debug := -pthread
+
+LDFLAGS_Release := -pthread
 
 LIBS := -lrt
 
index 65c2cf17b839d0747c4347fdce19b8fc3b5eb4c5..60e0e8fd2def64a48356d5b48390bab1906ae4a5 100644 (file)
@@ -2,30 +2,79 @@
 
 TOOLSET := target
 TARGET := uv
-DEFS_Default := '-D_LARGEFILE_SOURCE' \
+DEFS_Debug := '-D_LARGEFILE_SOURCE' \
        '-D_FILE_OFFSET_BITS=64' \
        '-D_GNU_SOURCE' \
        '-DEIO_STACKSIZE=262144' \
        '-DHAVE_CONFIG_H' \
        '-DEV_CONFIG_H="config_linux.h"' \
-       '-DEIO_CONFIG_H="config_linux.h"'
+       '-DEIO_CONFIG_H="config_linux.h"' \
+       '-DDEBUG' \
+       '-D_DEBUG' \
+       '-DEV_VERIFY=2'
 
 # Flags passed to all source files.
-CFLAGS_Default := -pthread \
+CFLAGS_Debug := -pthread \
+       -Wall \
+       -ansi \
+       -pthread \
+       -fvisibility=hidden \
+       -g \
+       --std=gnu89 \
+       -pedantic \
+       -Wall \
+       -Wextra \
+       -Wno-unused-parameter \
+       -g \
+       -O0
+
+# Flags passed to only C files.
+CFLAGS_C_Debug := 
+
+# Flags passed to only C++ files.
+CFLAGS_CC_Debug := -fno-rtti \
+       -fno-exceptions
+
+INCS_Debug := -I$(srcdir)/src/libuv/include \
+       -I$(srcdir)/src/libuv/include/uv-private \
+       -I$(srcdir)/src/libuv/src \
+       -I$(srcdir)/src/libuv/src/unix/ev \
+       -I$(srcdir)/src/libuv/src/ares/config_linux
+
+DEFS_Release := '-D_LARGEFILE_SOURCE' \
+       '-D_FILE_OFFSET_BITS=64' \
+       '-D_GNU_SOURCE' \
+       '-DEIO_STACKSIZE=262144' \
+       '-DHAVE_CONFIG_H' \
+       '-DEV_CONFIG_H="config_linux.h"' \
+       '-DEIO_CONFIG_H="config_linux.h"' \
+       '-DNDEBUG'
+
+# Flags passed to all source files.
+CFLAGS_Release := -pthread \
+       -Wall \
+       -ansi \
+       -pthread \
+       -fvisibility=hidden \
        -g \
        --std=gnu89 \
        -pedantic \
        -Wall \
        -Wextra \
-       -Wno-unused-parameter
+       -Wno-unused-parameter \
+       -O3 \
+       -fomit-frame-pointer \
+       -fdata-sections \
+       -ffunction-sections
 
 # Flags passed to only C files.
-CFLAGS_C_Default := 
+CFLAGS_C_Release := 
 
 # Flags passed to only C++ files.
-CFLAGS_CC_Default := 
+CFLAGS_CC_Release := -fno-rtti \
+       -fno-exceptions
 
-INCS_Default := -I$(srcdir)/src/libuv/include \
+INCS_Release := -I$(srcdir)/src/libuv/include \
        -I$(srcdir)/src/libuv/include/uv-private \
        -I$(srcdir)/src/libuv/src \
        -I$(srcdir)/src/libuv/src/unix/ev \
@@ -87,6 +136,7 @@ OBJS := $(obj).target/$(TARGET)/src/libuv/src/uv-common.o \
        $(obj).target/$(TARGET)/src/libuv/src/unix/cares.o \
        $(obj).target/$(TARGET)/src/libuv/src/unix/dl.o \
        $(obj).target/$(TARGET)/src/libuv/src/unix/error.o \
+       $(obj).target/$(TARGET)/src/libuv/src/unix/thread.o \
        $(obj).target/$(TARGET)/src/libuv/src/unix/process.o \
        $(obj).target/$(TARGET)/src/libuv/src/unix/eio/eio.o \
        $(obj).target/$(TARGET)/src/libuv/src/unix/ev/ev.o \
@@ -98,8 +148,8 @@ all_deps += $(OBJS)
 # CFLAGS et al overrides must be target-local.
 # See "Target-specific Variable Values" in the GNU Make manual.
 $(OBJS): TOOLSET := $(TOOLSET)
-$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
-$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
+$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
+$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
 
 # Suffix rules, putting all outputs into $(obj).
 
@@ -116,7 +166,9 @@ $(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.c FORCE_DO_CMD
 
 # End of this set of suffix rules
 ### Rules for final target.
-LDFLAGS_Default := 
+LDFLAGS_Debug := -pthread
+
+LDFLAGS_Release := -pthread
 
 LIBS := -lm
 
index d24668d336d69fe039c13c7e2004069f07b1d516..8a6222228d891cc85a085544f4e2230a695cff68 100644 (file)
@@ -8,6 +8,7 @@ MAKEFLAGS=-r
 
 # The source directory tree.
 srcdir := ../../../..
+abs_srcdir := $(abspath $(srcdir))
 
 # The name of the builddir.
 builddir_name ?= out
@@ -20,7 +21,7 @@ else
 endif
 
 # Specify BUILDTYPE=Release on the command line for a release build.
-BUILDTYPE ?= Default
+BUILDTYPE ?= Debug
 
 # Directory all our build output goes into.
 # Note that this must be two directories beneath src/ for unit tests to pass,
@@ -252,8 +253,8 @@ $(if $(or $(command_changed),$(prereq_changed)),
 )
 endef
 
-# Declare "all" target first so it is the default, even though we don't have the
-# deps yet.
+# Declare the "all" target first so it is the default,
+# even though we don't have the deps yet.
 .PHONY: all
 all:
 
@@ -321,9 +322,9 @@ ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
   include src/libuv/uv.target.mk
 endif
 
-quiet_cmd_regen_makefile = ACTION Regenerating $@
-cmd_regen_makefile = ./src/libuv/build/gyp/gyp -fmake --ignore-environment "--toplevel-dir=." "--depth=." "--generator-output=mk/libuv/ia32/win" "-Dlibrary=static_library" "-Dtarget_arch=ia32" "-DOS=win" src/libuv/uv.gyp
-Makefile: $(srcdir)/src/libuv/uv.gyp
+#quiet_cmd_regen_makefile = ACTION Regenerating $@
+#cmd_regen_makefile = ./src/libuv/build/gyp/gyp -fmake --ignore-environment "--toplevel-dir=." -Isrc/libuv/common.gypi "--depth=." "--generator-output=mk/libuv/ia32/win" "-Ddefault_configuration=Default" "-Dcomponent=static_library" "-Dlibrary=static_library" "-Dtarget_arch=ia32" "-DOS=win" src/libuv/uv.gyp
+#Makefile: $(srcdir)/src/libuv/uv.gyp $(srcdir)/src/libuv/common.gypi
 #      $(call do_cmd,regen_makefile)
 
 # "all" is a concatenation of the "all" targets from all the included
diff --git a/mk/libuv/ia32/win/Makefile-e b/mk/libuv/ia32/win/Makefile-e
deleted file mode 100644 (file)
index 4c05b46..0000000
+++ /dev/null
@@ -1,353 +0,0 @@
-# We borrow heavily from the kernel build setup, though we are simpler since
-# we don't have Kconfig tweaking settings on us.
-
-# The implicit make rules have it looking for RCS files, among other things.
-# We instead explicitly write all the rules we care about.
-# It's even quicker (saves ~200ms) to pass -r on the command line.
-MAKEFLAGS=-r
-
-# The source directory tree.
-srcdir := ../../../..
-
-# The name of the builddir.
-builddir_name ?= out
-
-# The V=1 flag on command line makes us verbosely print command lines.
-ifdef V
-  quiet=
-else
-  quiet=quiet_
-endif
-
-# Specify BUILDTYPE=Release on the command line for a release build.
-BUILDTYPE ?= Default
-
-# Directory all our build output goes into.
-# Note that this must be two directories beneath src/ for unit tests to pass,
-# as they reach into the src/ directory for data with relative paths.
-builddir ?= $(builddir_name)/$(BUILDTYPE)
-abs_builddir := $(abspath $(builddir))
-depsdir := $(builddir)/.deps
-
-# Object output directory.
-obj := $(builddir)/obj
-abs_obj := $(abspath $(obj))
-
-# We build up a list of every single one of the targets so we can slurp in the
-# generated dependency rule Makefiles in one pass.
-all_deps :=
-
-
-
-# C++ apps need to be linked with g++.
-#
-# Note: flock is used to seralize linking. Linking is a memory-intensive
-# process so running parallel links can often lead to thrashing.  To disable
-# the serialization, override LINK via an envrionment variable as follows:
-#
-#   export LINK=g++
-#
-# This will allow make to invoke N linker processes as specified in -jN.
-LINK ?= flock $(builddir)/linker.lock $(CXX)
-
-CC.target ?= $(CC)
-CFLAGS.target ?= $(CFLAGS)
-CXX.target ?= $(CXX)
-CXXFLAGS.target ?= $(CXXFLAGS)
-LINK.target ?= $(LINK)
-LDFLAGS.target ?= $(LDFLAGS) 
-AR.target ?= $(AR)
-ARFLAGS.target ?= crsT
-
-# N.B.: the logic of which commands to run should match the computation done
-# in gyp's make.py where ARFLAGS.host etc. is computed.
-# TODO(evan): move all cross-compilation logic to gyp-time so we don't need
-# to replicate this environment fallback in make as well.
-CC.host ?= gcc
-CFLAGS.host ?=
-CXX.host ?= g++
-CXXFLAGS.host ?=
-LINK.host ?= g++
-LDFLAGS.host ?=
-AR.host ?= ar
-ARFLAGS.host := crsT
-
-# Define a dir function that can handle spaces.
-# http://www.gnu.org/software/make/manual/make.html#Syntax-of-Functions
-# "leading spaces cannot appear in the text of the first argument as written.
-# These characters can be put into the argument value by variable substitution."
-empty :=
-space := $(empty) $(empty)
-
-# http://stackoverflow.com/questions/1189781/using-make-dir-or-notdir-on-a-path-with-spaces
-replace_spaces = $(subst $(space),?,$1)
-unreplace_spaces = $(subst ?,$(space),$1)
-dirx = $(call unreplace_spaces,$(dir $(call replace_spaces,$1)))
-
-# Flags to make gcc output dependency info.  Note that you need to be
-# careful here to use the flags that ccache and distcc can understand.
-# We write to a dep file on the side first and then rename at the end
-# so we can't end up with a broken dep file.
-depfile = $(depsdir)/$(call replace_spaces,$@).d
-DEPFLAGS = -MMD -MF $(depfile).raw
-
-# We have to fixup the deps output in a few ways.
-# (1) the file output should mention the proper .o file.
-# ccache or distcc lose the path to the target, so we convert a rule of
-# the form:
-#   foobar.o: DEP1 DEP2
-# into
-#   path/to/foobar.o: DEP1 DEP2
-# (2) we want missing files not to cause us to fail to build.
-# We want to rewrite
-#   foobar.o: DEP1 DEP2 \
-#               DEP3
-# to
-#   DEP1:
-#   DEP2:
-#   DEP3:
-# so if the files are missing, they're just considered phony rules.
-# We have to do some pretty insane escaping to get those backslashes
-# and dollar signs past make, the shell, and sed at the same time.
-# Doesn't work with spaces, but that's fine: .d files have spaces in
-# their names replaced with other characters.
-define fixup_dep
-# The depfile may not exist if the input file didn't have any #includes.
-touch $(depfile).raw
-# Fixup path as in (1).
-sed -e "s|^$(notdir $@)|$@|" $(depfile).raw >> $(depfile)
-# Add extra rules as in (2).
-# We remove slashes and replace spaces with new lines;
-# remove blank lines;
-# delete the first line and append a colon to the remaining lines.
-sed -e 's|\\||' -e 'y| |\n|' $(depfile).raw |\
-  grep -v '^$$'                             |\
-  sed -e 1d -e 's|$$|:|'                     \
-    >> $(depfile)
-rm $(depfile).raw
-endef
-
-# Command definitions:
-# - cmd_foo is the actual command to run;
-# - quiet_cmd_foo is the brief-output summary of the command.
-
-quiet_cmd_cc = CC($(TOOLSET)) $@
-cmd_cc = $(CC.$(TOOLSET)) $(GYP_CFLAGS) $(DEPFLAGS) $(CFLAGS.$(TOOLSET)) -c -o $@ $<
-
-quiet_cmd_cxx = CXX($(TOOLSET)) $@
-cmd_cxx = $(CXX.$(TOOLSET)) $(GYP_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $<
-
-quiet_cmd_touch = TOUCH $@
-cmd_touch = touch $@
-
-quiet_cmd_copy = COPY $@
-# send stderr to /dev/null to ignore messages when linking directories.
-cmd_copy = ln -f "$<" "$@" 2>/dev/null || (rm -rf "$@" && cp -af "$<" "$@")
-
-quiet_cmd_alink = AR($(TOOLSET)) $@
-cmd_alink = rm -f $@ && $(AR.$(TOOLSET)) $(ARFLAGS.$(TOOLSET)) $@ $(filter %.o,$^)
-
-# Due to circular dependencies between libraries :(, we wrap the
-# special "figure out circular dependencies" flags around the entire
-# input list during linking.
-quiet_cmd_link = LINK($(TOOLSET)) $@
-cmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ -Wl,--start-group $(LD_INPUTS) -Wl,--end-group $(LIBS)
-
-# We support two kinds of shared objects (.so):
-# 1) shared_library, which is just bundling together many dependent libraries
-# into a link line.
-# 2) loadable_module, which is generating a module intended for dlopen().
-#
-# They differ only slightly:
-# In the former case, we want to package all dependent code into the .so.
-# In the latter case, we want to package just the API exposed by the
-# outermost module.
-# This means shared_library uses --whole-archive, while loadable_module doesn't.
-# (Note that --whole-archive is incompatible with the --start-group used in
-# normal linking.)
-
-# Other shared-object link notes:
-# - Set SONAME to the library filename so our binaries don't reference
-# the local, absolute paths used on the link command-line.
-quiet_cmd_solink = SOLINK($(TOOLSET)) $@
-cmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--whole-archive $(LD_INPUTS) -Wl,--no-whole-archive $(LIBS)
-
-quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@
-cmd_solink_module = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--start-group $(filter-out FORCE_DO_CMD, $^) -Wl,--end-group $(LIBS)
-
-
-# Define an escape_quotes function to escape single quotes.
-# This allows us to handle quotes properly as long as we always use
-# use single quotes and escape_quotes.
-escape_quotes = $(subst ','\'',$(1))
-# This comment is here just to include a ' to unconfuse syntax highlighting.
-# Define an escape_vars function to escape '$' variable syntax.
-# This allows us to read/write command lines with shell variables (e.g.
-# $LD_LIBRARY_PATH), without triggering make substitution.
-escape_vars = $(subst $$,$$$$,$(1))
-# Helper that expands to a shell command to echo a string exactly as it is in
-# make. This uses printf instead of echo because printf's behaviour with respect
-# to escape sequences is more portable than echo's across different shells
-# (e.g., dash, bash).
-exact_echo = printf '%s\n' '$(call escape_quotes,$(1))'
-
-# Helper to compare the command we're about to run against the command
-# we logged the last time we ran the command.  Produces an empty
-# string (false) when the commands match.
-# Tricky point: Make has no string-equality test function.
-# The kernel uses the following, but it seems like it would have false
-# positives, where one string reordered its arguments.
-#   arg_check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \
-#                       $(filter-out $(cmd_$@), $(cmd_$(1))))
-# We instead substitute each for the empty string into the other, and
-# say they're equal if both substitutions produce the empty string.
-# .d files contain ? instead of spaces, take that into account.
-command_changed = $(or $(subst $(cmd_$(1)),,$(cmd_$(call replace_spaces,$@))),\
-                       $(subst $(cmd_$(call replace_spaces,$@)),,$(cmd_$(1))))
-
-# Helper that is non-empty when a prerequisite changes.
-# Normally make does this implicitly, but we force rules to always run
-# so we can check their command lines.
-#   $? -- new prerequisites
-#   $| -- order-only dependencies
-prereq_changed = $(filter-out FORCE_DO_CMD,$(filter-out $|,$?))
-
-# Helper that executes all postbuilds, and deletes the output file when done
-# if any of the postbuilds failed.
-define do_postbuilds
-  @E=0;\
-  for p in $(POSTBUILDS); do\
-    eval $$p;\
-    F=$$?;\
-    if [ $$F -ne 0 ]; then\
-      E=$$F;\
-    fi;\
-  done;\
-  if [ $$E -ne 0 ]; then\
-    rm -rf "$@";\
-    exit $$E;\
-  fi
-endef
-
-# do_cmd: run a command via the above cmd_foo names, if necessary.
-# Should always run for a given target to handle command-line changes.
-# Second argument, if non-zero, makes it do asm/C/C++ dependency munging.
-# Third argument, if non-zero, makes it do POSTBUILDS processing.
-# Note: We intentionally do NOT call dirx for depfile, since it contains ? for
-# spaces already and dirx strips the ? characters.
-define do_cmd
-$(if $(or $(command_changed),$(prereq_changed)),
-  @$(call exact_echo,  $($(quiet)cmd_$(1)))
-  @mkdir -p "$(call dirx,$@)" "$(dir $(depfile))"
-  $(if $(findstring flock,$(word 1,$(cmd_$1))),
-    @$(cmd_$(1))
-    @echo "  $(quiet_cmd_$(1)): Finished",
-    @$(cmd_$(1))
-  )
-  @$(call exact_echo,$(call escape_vars,cmd_$(call replace_spaces,$@) := $(cmd_$(1)))) > $(depfile)
-  @$(if $(2),$(fixup_dep))
-  $(if $(and $(3), $(POSTBUILDS)),
-    $(call do_postbuilds)
-  )
-)
-endef
-
-# Declare "all" target first so it is the default, even though we don't have the
-# deps yet.
-.PHONY: all
-all:
-
-# Use FORCE_DO_CMD to force a target to run.  Should be coupled with
-# do_cmd.
-.PHONY: FORCE_DO_CMD
-FORCE_DO_CMD:
-
-TOOLSET := target
-# Suffix rules, putting all outputs into $(obj).
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.c FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cc FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cpp FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cxx FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.S FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.s FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-
-# Try building from generated source, too.
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.c FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cc FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cpp FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cxx FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.S FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.s FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-
-$(obj).$(TOOLSET)/%.o: $(obj)/%.c FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.cc FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.cpp FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.cxx FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.S FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.s FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-
-
-ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
-    $(findstring $(join ^,$(prefix)),\
-                 $(join ^,src/libuv/run-benchmarks.target.mk)))),)
-  include src/libuv/run-benchmarks.target.mk
-endif
-ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
-    $(findstring $(join ^,$(prefix)),\
-                 $(join ^,src/libuv/run-tests.target.mk)))),)
-  include src/libuv/run-tests.target.mk
-endif
-ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
-    $(findstring $(join ^,$(prefix)),\
-                 $(join ^,src/libuv/uv.target.mk)))),)
-  include src/libuv/uv.target.mk
-endif
-
-quiet_cmd_regen_makefile = ACTION Regenerating $@
-cmd_regen_makefile = ./src/libuv/build/gyp/gyp -fmake --ignore-environment "--toplevel-dir=." "--depth=." "--generator-output=mk/libuv/ia32/win" "-Dlibrary=static_library" "-Dtarget_arch=ia32" "-DOS=win" src/libuv/uv.gyp
-Makefile: $(srcdir)/src/libuv/uv.gyp
-       $(call do_cmd,regen_makefile)
-
-# "all" is a concatenation of the "all" targets from all the included
-# sub-makefiles. This is just here to clarify.
-all:
-
-# Add in dependency-tracking rules.  $(all_deps) is the list of every single
-# target in our tree. Only consider the ones with .d (dependency) info:
-d_files := $(wildcard $(foreach f,$(all_deps),$(depsdir)/$(f).d))
-ifneq ($(d_files),)
-  # Rather than include each individual .d file, concatenate them into a
-  # single file which make is able to load faster.  We split this into
-  # commands that take 1000 files at a time to avoid overflowing the
-  # command line.
-  $(shell cat $(wordlist 1,1000,$(d_files)) > $(depsdir)/all.deps)
-
-  ifneq ($(word 1001,$(d_files)),)
-    $(error Found unprocessed dependency files (gyp didn't generate enough rules!))
-  endif
-
-  # make looks for ways to re-generate included makefiles, but in our case, we
-  # don't have a direct way. Explicitly telling make that it has nothing to do
-  # for them makes it go faster.
-  $(depsdir)/all.deps: ;
-
-  include $(depsdir)/all.deps
-endif
index 68dc04f210593f7d201169aa0c53cda362827df8..25bf58f854886b60bb13d8e58485cddd463f426e 100644 (file)
@@ -2,18 +2,42 @@
 
 TOOLSET := target
 TARGET := run-benchmarks
-DEFS_Default := 
+DEFS_Debug := '-DWIN32' \
+       '-D_CRT_SECURE_NO_DEPRECATE' \
+       '-D_CRT_NONSTDC_NO_DEPRECATE' \
+       '-DDEBUG' \
+       '-D_DEBUG'
 
 # Flags passed to all source files.
-CFLAGS_Default := 
+CFLAGS_Debug := -g \
+       -O0
 
 # Flags passed to only C files.
-CFLAGS_C_Default := 
+CFLAGS_C_Debug := 
 
 # Flags passed to only C++ files.
-CFLAGS_CC_Default := 
+CFLAGS_CC_Debug := 
 
-INCS_Default := -I$(srcdir)/src/libuv/include
+INCS_Debug := -I$(srcdir)/src/libuv/include
+
+DEFS_Release := '-DWIN32' \
+       '-D_CRT_SECURE_NO_DEPRECATE' \
+       '-D_CRT_NONSTDC_NO_DEPRECATE' \
+       '-DNDEBUG'
+
+# Flags passed to all source files.
+CFLAGS_Release := -O3 \
+       -fomit-frame-pointer \
+       -fdata-sections \
+       -ffunction-sections
+
+# Flags passed to only C files.
+CFLAGS_C_Release := 
+
+# Flags passed to only C++ files.
+CFLAGS_CC_Release := 
+
+INCS_Release := -I$(srcdir)/src/libuv/include
 
 OBJS := $(obj).target/$(TARGET)/src/libuv/test/benchmark-ares.o \
        $(obj).target/$(TARGET)/src/libuv/test/benchmark-getaddrinfo.o \
@@ -22,6 +46,7 @@ OBJS := $(obj).target/$(TARGET)/src/libuv/test/benchmark-ares.o \
        $(obj).target/$(TARGET)/src/libuv/test/benchmark-pump.o \
        $(obj).target/$(TARGET)/src/libuv/test/benchmark-sizes.o \
        $(obj).target/$(TARGET)/src/libuv/test/benchmark-spawn.o \
+       $(obj).target/$(TARGET)/src/libuv/test/benchmark-thread.o \
        $(obj).target/$(TARGET)/src/libuv/test/benchmark-tcp-write-batch.o \
        $(obj).target/$(TARGET)/src/libuv/test/benchmark-udp-packet-storm.o \
        $(obj).target/$(TARGET)/src/libuv/test/dns-server.o \
@@ -40,8 +65,8 @@ $(OBJS): | $(obj).target/src/libuv/libuv.a
 # CFLAGS et al overrides must be target-local.
 # See "Target-specific Variable Values" in the GNU Make manual.
 $(OBJS): TOOLSET := $(TOOLSET)
-$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
-$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
+$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
+$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
 
 # Suffix rules, putting all outputs into $(obj).
 
@@ -58,10 +83,14 @@ $(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.c FORCE_DO_CMD
 
 # End of this set of suffix rules
 ### Rules for final target.
-LDFLAGS_Default := 
+LDFLAGS_Debug := 
+
+LDFLAGS_Release := 
 
 LIBS := ws2_32.lib \
-       -lws2_32.lib
+       -lws2_32.lib \
+       -lpsapi.lib \
+       -liphlpapi.lib
 
 $(builddir)/run-benchmarks: GYP_LDFLAGS := $(LDFLAGS_$(BUILDTYPE))
 $(builddir)/run-benchmarks: LIBS := $(LIBS)
index 9b09db73373df4434cfb0e2454f7ec7ce3fbaf6d..51b62f7a3e2d58f64a4e3c2f9b1e33b874894567 100644 (file)
@@ -2,29 +2,56 @@
 
 TOOLSET := target
 TARGET := run-tests
-DEFS_Default := 
+DEFS_Debug := '-DWIN32' \
+       '-D_CRT_SECURE_NO_DEPRECATE' \
+       '-D_CRT_NONSTDC_NO_DEPRECATE' \
+       '-DDEBUG' \
+       '-D_DEBUG'
 
 # Flags passed to all source files.
-CFLAGS_Default := 
+CFLAGS_Debug := -g \
+       -O0
 
 # Flags passed to only C files.
-CFLAGS_C_Default := 
+CFLAGS_C_Debug := 
 
 # Flags passed to only C++ files.
-CFLAGS_CC_Default := 
+CFLAGS_CC_Debug := 
 
-INCS_Default := -I$(srcdir)/src/libuv/include
+INCS_Debug := -I$(srcdir)/src/libuv/include
+
+DEFS_Release := '-DWIN32' \
+       '-D_CRT_SECURE_NO_DEPRECATE' \
+       '-D_CRT_NONSTDC_NO_DEPRECATE' \
+       '-DNDEBUG'
+
+# Flags passed to all source files.
+CFLAGS_Release := -O3 \
+       -fomit-frame-pointer \
+       -fdata-sections \
+       -ffunction-sections
+
+# Flags passed to only C files.
+CFLAGS_C_Release := 
+
+# Flags passed to only C++ files.
+CFLAGS_CC_Release := 
+
+INCS_Release := -I$(srcdir)/src/libuv/include
 
 OBJS := $(obj).target/$(TARGET)/src/libuv/test/blackhole-server.o \
        $(obj).target/$(TARGET)/src/libuv/test/echo-server.o \
        $(obj).target/$(TARGET)/src/libuv/test/run-tests.o \
        $(obj).target/$(TARGET)/src/libuv/test/runner.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-get-loadavg.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-util.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-async.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-error.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-callback-stack.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-connection-fail.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-cwd-and-chdir.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-delayed-accept.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-eio-overflow.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-fail-always.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-fs.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-fs-event.o \
@@ -36,12 +63,15 @@ OBJS := $(obj).target/$(TARGET)/src/libuv/test/blackhole-server.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-hrtime.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-idle.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-ipc.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-ipc-threads.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-loop-handles.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-multiple-listen.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-pass-always.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-ping-pong.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-pipe-bind-error.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-pipe-connect-error.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-platform-output.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-process-title.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-ref.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-shutdown-eof.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-spawn.o \
@@ -56,13 +86,17 @@ OBJS := $(obj).target/$(TARGET)/src/libuv/test/blackhole-server.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-tcp-write-to-half-open-connection.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-tcp-writealot.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-threadpool.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-mutexes.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-thread.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-timer-again.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-timer.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-tty.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-udp-dgram-too-big.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-udp-ipv6.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-udp-options.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-udp-send-and-recv.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-udp-multicast-join.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-counters-init.o \
        $(obj).target/$(TARGET)/src/libuv/test/runner-win.o
 
 # Add to the list of files we specially track dependencies for.
@@ -74,8 +108,8 @@ $(OBJS): | $(obj).target/src/libuv/libuv.a
 # CFLAGS et al overrides must be target-local.
 # See "Target-specific Variable Values" in the GNU Make manual.
 $(OBJS): TOOLSET := $(TOOLSET)
-$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
-$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
+$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
+$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
 
 # Suffix rules, putting all outputs into $(obj).
 
@@ -92,10 +126,14 @@ $(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.c FORCE_DO_CMD
 
 # End of this set of suffix rules
 ### Rules for final target.
-LDFLAGS_Default := 
+LDFLAGS_Debug := 
+
+LDFLAGS_Release := 
 
 LIBS := ws2_32.lib \
-       -lws2_32.lib
+       -lws2_32.lib \
+       -lpsapi.lib \
+       -liphlpapi.lib
 
 $(builddir)/run-tests: GYP_LDFLAGS := $(LDFLAGS_$(BUILDTYPE))
 $(builddir)/run-tests: LIBS := $(LIBS)
index 86ed7071555c7b121cef6ef21faeb3305b0c02f3..53576a0f93570eec5f0ad4cbe4d217315332edd9 100644 (file)
@@ -2,21 +2,53 @@
 
 TOOLSET := target
 TARGET := uv
-DEFS_Default := '-DHAVE_CONFIG_H' \
-       '-D_WIN32_WINNT=0x0502' \
+DEFS_Debug := '-DWIN32' \
+       '-D_CRT_SECURE_NO_DEPRECATE' \
+       '-D_CRT_NONSTDC_NO_DEPRECATE' \
+       '-DHAVE_CONFIG_H' \
+       '-D_WIN32_WINNT=0x0600' \
        '-DEIO_STACKSIZE=262144' \
-       '-D_GNU_SOURCE'
+       '-D_GNU_SOURCE' \
+       '-DDEBUG' \
+       '-D_DEBUG'
 
 # Flags passed to all source files.
-CFLAGS_Default := 
+CFLAGS_Debug := -g \
+       -O0
 
 # Flags passed to only C files.
-CFLAGS_C_Default := 
+CFLAGS_C_Debug := 
 
 # Flags passed to only C++ files.
-CFLAGS_CC_Default := 
+CFLAGS_CC_Debug := 
 
-INCS_Default := -I$(srcdir)/src/libuv/include \
+INCS_Debug := -I$(srcdir)/src/libuv/include \
+       -I$(srcdir)/src/libuv/include/uv-private \
+       -I$(srcdir)/src/libuv/src \
+       -I$(srcdir)/src/libuv/src/ares/config_win32
+
+DEFS_Release := '-DWIN32' \
+       '-D_CRT_SECURE_NO_DEPRECATE' \
+       '-D_CRT_NONSTDC_NO_DEPRECATE' \
+       '-DHAVE_CONFIG_H' \
+       '-D_WIN32_WINNT=0x0600' \
+       '-DEIO_STACKSIZE=262144' \
+       '-D_GNU_SOURCE' \
+       '-DNDEBUG'
+
+# Flags passed to all source files.
+CFLAGS_Release := -O3 \
+       -fomit-frame-pointer \
+       -fdata-sections \
+       -ffunction-sections
+
+# Flags passed to only C files.
+CFLAGS_C_Release := 
+
+# Flags passed to only C++ files.
+CFLAGS_CC_Release := 
+
+INCS_Release := -I$(srcdir)/src/libuv/include \
        -I$(srcdir)/src/libuv/include/uv-private \
        -I$(srcdir)/src/libuv/src \
        -I$(srcdir)/src/libuv/src/ares/config_win32
@@ -79,13 +111,13 @@ OBJS := $(obj).target/$(TARGET)/src/libuv/src/uv-common.o \
        $(obj).target/$(TARGET)/src/libuv/src/win/handle.o \
        $(obj).target/$(TARGET)/src/libuv/src/win/loop-watcher.o \
        $(obj).target/$(TARGET)/src/libuv/src/win/pipe.o \
+       $(obj).target/$(TARGET)/src/libuv/src/win/thread.o \
        $(obj).target/$(TARGET)/src/libuv/src/win/process.o \
        $(obj).target/$(TARGET)/src/libuv/src/win/req.o \
        $(obj).target/$(TARGET)/src/libuv/src/win/stream.o \
        $(obj).target/$(TARGET)/src/libuv/src/win/tcp.o \
        $(obj).target/$(TARGET)/src/libuv/src/win/tty.o \
        $(obj).target/$(TARGET)/src/libuv/src/win/threadpool.o \
-       $(obj).target/$(TARGET)/src/libuv/src/win/threads.o \
        $(obj).target/$(TARGET)/src/libuv/src/win/timer.o \
        $(obj).target/$(TARGET)/src/libuv/src/win/udp.o \
        $(obj).target/$(TARGET)/src/libuv/src/win/util.o \
@@ -98,8 +130,8 @@ all_deps += $(OBJS)
 # CFLAGS et al overrides must be target-local.
 # See "Target-specific Variable Values" in the GNU Make manual.
 $(OBJS): TOOLSET := $(TOOLSET)
-$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
-$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
+$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
+$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
 
 # Suffix rules, putting all outputs into $(obj).
 
@@ -116,7 +148,9 @@ $(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.c FORCE_DO_CMD
 
 # End of this set of suffix rules
 ### Rules for final target.
-LDFLAGS_Default := 
+LDFLAGS_Debug := 
+
+LDFLAGS_Release := 
 
 LIBS := 
 
diff --git a/mk/libuv/ia32/win/src/libuv/uv.target.mk.bak b/mk/libuv/ia32/win/src/libuv/uv.target.mk.bak
new file mode 100644 (file)
index 0000000..00b34e4
--- /dev/null
@@ -0,0 +1,167 @@
+# This file is generated by gyp; do not edit.
+
+TOOLSET := target
+TARGET := uv
+DEFS_Debug := '-DWIN32' \
+       '-D_CRT_SECURE_NO_DEPRECATE' \
+       '-D_CRT_NONSTDC_NO_DEPRECATE' \
+       '-DHAVE_CONFIG_H' \
+       '-D_WIN32_WINNT=0x0600' \
+       '-DEIO_STACKSIZE=262144' \
+       '-D_GNU_SOURCE' \
+       '-DDEBUG' \
+       '-D_DEBUG'
+
+# Flags passed to all source files.
+CFLAGS_Debug := -g \
+       -O0
+
+# Flags passed to only C files.
+CFLAGS_C_Debug := 
+
+# Flags passed to only C++ files.
+CFLAGS_CC_Debug := 
+
+INCS_Debug := -I$(srcdir)\src\libuv\include \
+       -I$(srcdir)\src\libuv\include\uv-private \
+       -I$(srcdir)\src\libuv\src \
+       -I$(srcdir)\src\libuv\src\ares\config_win32
+
+DEFS_Release := '-DWIN32' \
+       '-D_CRT_SECURE_NO_DEPRECATE' \
+       '-D_CRT_NONSTDC_NO_DEPRECATE' \
+       '-DHAVE_CONFIG_H' \
+       '-D_WIN32_WINNT=0x0600' \
+       '-DEIO_STACKSIZE=262144' \
+       '-D_GNU_SOURCE' \
+       '-DNDEBUG'
+
+# Flags passed to all source files.
+CFLAGS_Release := -O3 \
+       -fomit-frame-pointer \
+       -fdata-sections \
+       -ffunction-sections
+
+# Flags passed to only C files.
+CFLAGS_C_Release := 
+
+# Flags passed to only C++ files.
+CFLAGS_CC_Release := 
+
+INCS_Release := -I$(srcdir)\src\libuv\include \
+       -I$(srcdir)\src\libuv\include\uv-private \
+       -I$(srcdir)\src\libuv\src \
+       -I$(srcdir)\src\libuv\src\ares\config_win32
+
+OBJS := $(obj).target\$(TARGET)\src\libuv\src\uv-common.o \
+       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_cancel.o \
+       $(obj).target\$(TARGET)\src\libuv\src\ares\ares__close_sockets.o \
+       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_data.o \
+       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_destroy.o \
+       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_expand_name.o \
+       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_expand_string.o \
+       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_fds.o \
+       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_free_hostent.o \
+       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_free_string.o \
+       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_gethostbyaddr.o \
+       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_gethostbyname.o \
+       $(obj).target\$(TARGET)\src\libuv\src\ares\ares__get_hostent.o \
+       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_getnameinfo.o \
+       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_getopt.o \
+       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_getsock.o \
+       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_init.o \
+       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_library_init.o \
+       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_llist.o \
+       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_mkquery.o \
+       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_nowarn.o \
+       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_options.o \
+       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_parse_aaaa_reply.o \
+       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_parse_a_reply.o \
+       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_parse_mx_reply.o \
+       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_parse_ns_reply.o \
+       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_parse_ptr_reply.o \
+       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_parse_srv_reply.o \
+       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_parse_txt_reply.o \
+       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_process.o \
+       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_query.o \
+       $(obj).target\$(TARGET)\src\libuv\src\ares\ares__read_line.o \
+       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_search.o \
+       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_send.o \
+       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_strcasecmp.o \
+       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_strdup.o \
+       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_strerror.o \
+       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_timeout.o \
+       $(obj).target\$(TARGET)\src\libuv\src\ares\ares__timeval.o \
+       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_version.o \
+       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_writev.o \
+       $(obj).target\$(TARGET)\src\libuv\src\ares\bitncmp.o \
+       $(obj).target\$(TARGET)\src\libuv\src\ares\inet_net_pton.o \
+       $(obj).target\$(TARGET)\src\libuv\src\ares\inet_ntop.o \
+       $(obj).target\$(TARGET)\src\libuv\src\ares\windows_port.o \
+       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_getenv.o \
+       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_platform.o \
+       $(obj).target\$(TARGET)\src\libuv\src\win\async.o \
+       $(obj).target\$(TARGET)\src\libuv\src\win\cares.o \
+       $(obj).target\$(TARGET)\src\libuv\src\win\core.o \
+       $(obj).target\$(TARGET)\src\libuv\src\win\dl.o \
+       $(obj).target\$(TARGET)\src\libuv\src\win\error.o \
+       $(obj).target\$(TARGET)\src\libuv\src\win\fs.o \
+       $(obj).target\$(TARGET)\src\libuv\src\win\fs-event.o \
+       $(obj).target\$(TARGET)\src\libuv\src\win\getaddrinfo.o \
+       $(obj).target\$(TARGET)\src\libuv\src\win\handle.o \
+       $(obj).target\$(TARGET)\src\libuv\src\win\loop-watcher.o \
+       $(obj).target\$(TARGET)\src\libuv\src\win\pipe.o \
+       $(obj).target\$(TARGET)\src\libuv\src\win\thread.o \
+       $(obj).target\$(TARGET)\src\libuv\src\win\process.o \
+       $(obj).target\$(TARGET)\src\libuv\src\win\req.o \
+       $(obj).target\$(TARGET)\src\libuv\src\win\stream.o \
+       $(obj).target\$(TARGET)\src\libuv\src\win\tcp.o \
+       $(obj).target\$(TARGET)\src\libuv\src\win\tty.o \
+       $(obj).target\$(TARGET)\src\libuv\src\win\threadpool.o \
+       $(obj).target\$(TARGET)\src\libuv\src\win\timer.o \
+       $(obj).target\$(TARGET)\src\libuv\src\win\udp.o \
+       $(obj).target\$(TARGET)\src\libuv\src\win\util.o \
+       $(obj).target\$(TARGET)\src\libuv\src\win\winapi.o \
+       $(obj).target\$(TARGET)\src\libuv\src\win\winsock.o
+
+# Add to the list of files we specially track dependencies for.
+all_deps += $(OBJS)
+
+# CFLAGS et al overrides must be target-local.
+# See "Target-specific Variable Values" in the GNU Make manual.
+$(OBJS): TOOLSET := $(TOOLSET)
+$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
+$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
+
+# Suffix rules, putting all outputs into $(obj).
+
+$(obj).$(TOOLSET)\$(TARGET)\%.o: $(srcdir)\%.c FORCE_DO_CMD
+       @$(call do_cmd,cc,1)
+
+# Try building from generated source, too.
+
+$(obj).$(TOOLSET)\$(TARGET)\%.o: $(obj).$(TOOLSET)\%.c FORCE_DO_CMD
+       @$(call do_cmd,cc,1)
+
+$(obj).$(TOOLSET)\$(TARGET)\%.o: $(obj)\%.c FORCE_DO_CMD
+       @$(call do_cmd,cc,1)
+
+# End of this set of suffix rules
+### Rules for final target.
+LDFLAGS_Debug := 
+
+LDFLAGS_Release := 
+
+LIBS := 
+
+$(obj).target\src\libuv\libuv.a: GYP_LDFLAGS := $(LDFLAGS_$(BUILDTYPE))
+$(obj).target\src\libuv\libuv.a: LIBS := $(LIBS)
+$(obj).target\src\libuv\libuv.a: TOOLSET := $(TOOLSET)
+$(obj).target\src\libuv\libuv.a: $(OBJS) FORCE_DO_CMD
+       $(call do_cmd,alink)
+
+all_deps += $(obj).target\src\libuv\libuv.a
+# Add target alias
+.PHONY: uv
+uv: $(obj).target\src\libuv\libuv.a
+
diff --git a/mk/libuv/x86_64/freebsd/Makefile b/mk/libuv/x86_64/freebsd/Makefile
deleted file mode 100644 (file)
index 98a175d..0000000
+++ /dev/null
@@ -1,353 +0,0 @@
-# We borrow heavily from the kernel build setup, though we are simpler since
-# we don't have Kconfig tweaking settings on us.
-
-# The implicit make rules have it looking for RCS files, among other things.
-# We instead explicitly write all the rules we care about.
-# It's even quicker (saves ~200ms) to pass -r on the command line.
-MAKEFLAGS=-r
-
-# The source directory tree.
-srcdir := ../../../..
-
-# The name of the builddir.
-builddir_name ?= out
-
-# The V=1 flag on command line makes us verbosely print command lines.
-ifdef V
-  quiet=
-else
-  quiet=quiet_
-endif
-
-# Specify BUILDTYPE=Release on the command line for a release build.
-BUILDTYPE ?= Default
-
-# Directory all our build output goes into.
-# Note that this must be two directories beneath src/ for unit tests to pass,
-# as they reach into the src/ directory for data with relative paths.
-builddir ?= $(builddir_name)/$(BUILDTYPE)
-abs_builddir := $(abspath $(builddir))
-depsdir := $(builddir)/.deps
-
-# Object output directory.
-obj := $(builddir)/obj
-abs_obj := $(abspath $(obj))
-
-# We build up a list of every single one of the targets so we can slurp in the
-# generated dependency rule Makefiles in one pass.
-all_deps :=
-
-
-
-# C++ apps need to be linked with g++.
-#
-# Note: flock is used to seralize linking. Linking is a memory-intensive
-# process so running parallel links can often lead to thrashing.  To disable
-# the serialization, override LINK via an envrionment variable as follows:
-#
-#   export LINK=g++
-#
-# This will allow make to invoke N linker processes as specified in -jN.
-LINK ?= lockf $(builddir)/linker.lock $(CXX)
-
-CC.target ?= $(CC)
-CFLAGS.target ?= $(CFLAGS)
-CXX.target ?= $(CXX)
-CXXFLAGS.target ?= $(CXXFLAGS)
-LINK.target ?= $(LINK)
-LDFLAGS.target ?= $(LDFLAGS) 
-AR.target ?= $(AR)
-ARFLAGS.target ?= crs
-
-# N.B.: the logic of which commands to run should match the computation done
-# in gyp's make.py where ARFLAGS.host etc. is computed.
-# TODO(evan): move all cross-compilation logic to gyp-time so we don't need
-# to replicate this environment fallback in make as well.
-CC.host ?= gcc
-CFLAGS.host ?=
-CXX.host ?= g++
-CXXFLAGS.host ?=
-LINK.host ?= g++
-LDFLAGS.host ?=
-AR.host ?= ar
-ARFLAGS.host := crs
-
-# Define a dir function that can handle spaces.
-# http://www.gnu.org/software/make/manual/make.html#Syntax-of-Functions
-# "leading spaces cannot appear in the text of the first argument as written.
-# These characters can be put into the argument value by variable substitution."
-empty :=
-space := $(empty) $(empty)
-
-# http://stackoverflow.com/questions/1189781/using-make-dir-or-notdir-on-a-path-with-spaces
-replace_spaces = $(subst $(space),?,$1)
-unreplace_spaces = $(subst ?,$(space),$1)
-dirx = $(call unreplace_spaces,$(dir $(call replace_spaces,$1)))
-
-# Flags to make gcc output dependency info.  Note that you need to be
-# careful here to use the flags that ccache and distcc can understand.
-# We write to a dep file on the side first and then rename at the end
-# so we can't end up with a broken dep file.
-depfile = $(depsdir)/$(call replace_spaces,$@).d
-DEPFLAGS = -MMD -MF $(depfile).raw
-
-# We have to fixup the deps output in a few ways.
-# (1) the file output should mention the proper .o file.
-# ccache or distcc lose the path to the target, so we convert a rule of
-# the form:
-#   foobar.o: DEP1 DEP2
-# into
-#   path/to/foobar.o: DEP1 DEP2
-# (2) we want missing files not to cause us to fail to build.
-# We want to rewrite
-#   foobar.o: DEP1 DEP2 \
-#               DEP3
-# to
-#   DEP1:
-#   DEP2:
-#   DEP3:
-# so if the files are missing, they're just considered phony rules.
-# We have to do some pretty insane escaping to get those backslashes
-# and dollar signs past make, the shell, and sed at the same time.
-# Doesn't work with spaces, but that's fine: .d files have spaces in
-# their names replaced with other characters.
-define fixup_dep
-# The depfile may not exist if the input file didn't have any #includes.
-touch $(depfile).raw
-# Fixup path as in (1).
-sed -e "s|^$(notdir $@)|$@|" $(depfile).raw >> $(depfile)
-# Add extra rules as in (2).
-# We remove slashes and replace spaces with new lines;
-# remove blank lines;
-# delete the first line and append a colon to the remaining lines.
-sed -e 's|\\||' -e 'y| |\n|' $(depfile).raw |\
-  grep -v '^$$'                             |\
-  sed -e 1d -e 's|$$|:|'                     \
-    >> $(depfile)
-rm $(depfile).raw
-endef
-
-# Command definitions:
-# - cmd_foo is the actual command to run;
-# - quiet_cmd_foo is the brief-output summary of the command.
-
-quiet_cmd_cc = CC($(TOOLSET)) $@
-cmd_cc = $(CC.$(TOOLSET)) $(GYP_CFLAGS) $(DEPFLAGS) $(CFLAGS.$(TOOLSET)) -c -o $@ $<
-
-quiet_cmd_cxx = CXX($(TOOLSET)) $@
-cmd_cxx = $(CXX.$(TOOLSET)) $(GYP_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $<
-
-quiet_cmd_touch = TOUCH $@
-cmd_touch = touch $@
-
-quiet_cmd_copy = COPY $@
-# send stderr to /dev/null to ignore messages when linking directories.
-cmd_copy = ln -f "$<" "$@" 2>/dev/null || (rm -rf "$@" && cp -af "$<" "$@")
-
-quiet_cmd_alink = AR($(TOOLSET)) $@
-cmd_alink = rm -f $@ && $(AR.$(TOOLSET)) $(ARFLAGS.$(TOOLSET)) $@ $(filter %.o,$^)
-
-# Due to circular dependencies between libraries :(, we wrap the
-# special "figure out circular dependencies" flags around the entire
-# input list during linking.
-quiet_cmd_link = LINK($(TOOLSET)) $@
-cmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ -Wl,--start-group $(LD_INPUTS) -Wl,--end-group $(LIBS)
-
-# We support two kinds of shared objects (.so):
-# 1) shared_library, which is just bundling together many dependent libraries
-# into a link line.
-# 2) loadable_module, which is generating a module intended for dlopen().
-#
-# They differ only slightly:
-# In the former case, we want to package all dependent code into the .so.
-# In the latter case, we want to package just the API exposed by the
-# outermost module.
-# This means shared_library uses --whole-archive, while loadable_module doesn't.
-# (Note that --whole-archive is incompatible with the --start-group used in
-# normal linking.)
-
-# Other shared-object link notes:
-# - Set SONAME to the library filename so our binaries don't reference
-# the local, absolute paths used on the link command-line.
-quiet_cmd_solink = SOLINK($(TOOLSET)) $@
-cmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--whole-archive $(LD_INPUTS) -Wl,--no-whole-archive $(LIBS)
-
-quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@
-cmd_solink_module = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--start-group $(filter-out FORCE_DO_CMD, $^) -Wl,--end-group $(LIBS)
-
-
-# Define an escape_quotes function to escape single quotes.
-# This allows us to handle quotes properly as long as we always use
-# use single quotes and escape_quotes.
-escape_quotes = $(subst ','\'',$(1))
-# This comment is here just to include a ' to unconfuse syntax highlighting.
-# Define an escape_vars function to escape '$' variable syntax.
-# This allows us to read/write command lines with shell variables (e.g.
-# $LD_LIBRARY_PATH), without triggering make substitution.
-escape_vars = $(subst $$,$$$$,$(1))
-# Helper that expands to a shell command to echo a string exactly as it is in
-# make. This uses printf instead of echo because printf's behaviour with respect
-# to escape sequences is more portable than echo's across different shells
-# (e.g., dash, bash).
-exact_echo = printf '%s\n' '$(call escape_quotes,$(1))'
-
-# Helper to compare the command we're about to run against the command
-# we logged the last time we ran the command.  Produces an empty
-# string (false) when the commands match.
-# Tricky point: Make has no string-equality test function.
-# The kernel uses the following, but it seems like it would have false
-# positives, where one string reordered its arguments.
-#   arg_check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \
-#                       $(filter-out $(cmd_$@), $(cmd_$(1))))
-# We instead substitute each for the empty string into the other, and
-# say they're equal if both substitutions produce the empty string.
-# .d files contain ? instead of spaces, take that into account.
-command_changed = $(or $(subst $(cmd_$(1)),,$(cmd_$(call replace_spaces,$@))),\
-                       $(subst $(cmd_$(call replace_spaces,$@)),,$(cmd_$(1))))
-
-# Helper that is non-empty when a prerequisite changes.
-# Normally make does this implicitly, but we force rules to always run
-# so we can check their command lines.
-#   $? -- new prerequisites
-#   $| -- order-only dependencies
-prereq_changed = $(filter-out FORCE_DO_CMD,$(filter-out $|,$?))
-
-# Helper that executes all postbuilds, and deletes the output file when done
-# if any of the postbuilds failed.
-define do_postbuilds
-  @E=0;\
-  for p in $(POSTBUILDS); do\
-    eval $$p;\
-    F=$$?;\
-    if [ $$F -ne 0 ]; then\
-      E=$$F;\
-    fi;\
-  done;\
-  if [ $$E -ne 0 ]; then\
-    rm -rf "$@";\
-    exit $$E;\
-  fi
-endef
-
-# do_cmd: run a command via the above cmd_foo names, if necessary.
-# Should always run for a given target to handle command-line changes.
-# Second argument, if non-zero, makes it do asm/C/C++ dependency munging.
-# Third argument, if non-zero, makes it do POSTBUILDS processing.
-# Note: We intentionally do NOT call dirx for depfile, since it contains ? for
-# spaces already and dirx strips the ? characters.
-define do_cmd
-$(if $(or $(command_changed),$(prereq_changed)),
-  @$(call exact_echo,  $($(quiet)cmd_$(1)))
-  @mkdir -p "$(call dirx,$@)" "$(dir $(depfile))"
-  $(if $(findstring flock,$(word 1,$(cmd_$1))),
-    @$(cmd_$(1))
-    @echo "  $(quiet_cmd_$(1)): Finished",
-    @$(cmd_$(1))
-  )
-  @$(call exact_echo,$(call escape_vars,cmd_$(call replace_spaces,$@) := $(cmd_$(1)))) > $(depfile)
-  @$(if $(2),$(fixup_dep))
-  $(if $(and $(3), $(POSTBUILDS)),
-    $(call do_postbuilds)
-  )
-)
-endef
-
-# Declare the "all" target first so it is the default,
-# even though we don't have the deps yet.
-.PHONY: all
-all:
-
-# Use FORCE_DO_CMD to force a target to run.  Should be coupled with
-# do_cmd.
-.PHONY: FORCE_DO_CMD
-FORCE_DO_CMD:
-
-TOOLSET := target
-# Suffix rules, putting all outputs into $(obj).
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.c FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cc FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cpp FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cxx FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.S FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.s FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-
-# Try building from generated source, too.
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.c FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cc FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cpp FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cxx FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.S FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.s FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-
-$(obj).$(TOOLSET)/%.o: $(obj)/%.c FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.cc FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.cpp FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.cxx FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.S FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.s FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-
-
-ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
-    $(findstring $(join ^,$(prefix)),\
-                 $(join ^,src/libuv/run-benchmarks.target.mk)))),)
-  include src/libuv/run-benchmarks.target.mk
-endif
-ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
-    $(findstring $(join ^,$(prefix)),\
-                 $(join ^,src/libuv/run-tests.target.mk)))),)
-  include src/libuv/run-tests.target.mk
-endif
-ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
-    $(findstring $(join ^,$(prefix)),\
-                 $(join ^,src/libuv/uv.target.mk)))),)
-  include src/libuv/uv.target.mk
-endif
-
-quiet_cmd_regen_makefile = ACTION Regenerating $@
-cmd_regen_makefile = ./src/libuv/build/gyp/gyp -fmake --ignore-environment "--toplevel-dir=." "--depth=." "--generator-output=mk/libuv/x86_64/unix" "-Dlibrary=static_library" "-Dtarget_arch=x86_64" "-DOS=freebsd" src/libuv/uv.gyp
-Makefile: $(srcdir)/src/libuv/uv.gyp
-#      $(call do_cmd,regen_makefile)
-
-# "all" is a concatenation of the "all" targets from all the included
-# sub-makefiles. This is just here to clarify.
-all:
-
-# Add in dependency-tracking rules.  $(all_deps) is the list of every single
-# target in our tree. Only consider the ones with .d (dependency) info:
-d_files := $(wildcard $(foreach f,$(all_deps),$(depsdir)/$(f).d))
-ifneq ($(d_files),)
-  # Rather than include each individual .d file, concatenate them into a
-  # single file which make is able to load faster.  We split this into
-  # commands that take 1000 files at a time to avoid overflowing the
-  # command line.
-  $(shell cat $(wordlist 1,1000,$(d_files)) > $(depsdir)/all.deps)
-
-  ifneq ($(word 1001,$(d_files)),)
-    $(error Found unprocessed dependency files (gyp didn't generate enough rules!))
-  endif
-
-  # make looks for ways to re-generate included makefiles, but in our case, we
-  # don't have a direct way. Explicitly telling make that it has nothing to do
-  # for them makes it go faster.
-  $(depsdir)/all.deps: ;
-
-  include $(depsdir)/all.deps
-endif
diff --git a/mk/libuv/x86_64/freebsd/src/libuv/run-benchmarks.target.mk b/mk/libuv/x86_64/freebsd/src/libuv/run-benchmarks.target.mk
deleted file mode 100644 (file)
index 333d5e0..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-TOOLSET := target
-TARGET := run-benchmarks
-DEFS_Default := '-D_LARGEFILE_SOURCE' \
-       '-D_FILE_OFFSET_BITS=64' \
-       '-D_GNU_SOURCE' \
-       '-DEIO_STACKSIZE=262144'
-
-# Flags passed to all source files.
-CFLAGS_Default := -pthread
-
-# Flags passed to only C files.
-CFLAGS_C_Default := 
-
-# Flags passed to only C++ files.
-CFLAGS_CC_Default := 
-
-INCS_Default := -I$(srcdir)/src/libuv/include
-
-OBJS := $(obj).target/$(TARGET)/src/libuv/test/benchmark-ares.o \
-       $(obj).target/$(TARGET)/src/libuv/test/benchmark-getaddrinfo.o \
-       $(obj).target/$(TARGET)/src/libuv/test/benchmark-ping-pongs.o \
-       $(obj).target/$(TARGET)/src/libuv/test/benchmark-pound.o \
-       $(obj).target/$(TARGET)/src/libuv/test/benchmark-pump.o \
-       $(obj).target/$(TARGET)/src/libuv/test/benchmark-sizes.o \
-       $(obj).target/$(TARGET)/src/libuv/test/benchmark-spawn.o \
-       $(obj).target/$(TARGET)/src/libuv/test/benchmark-tcp-write-batch.o \
-       $(obj).target/$(TARGET)/src/libuv/test/benchmark-udp-packet-storm.o \
-       $(obj).target/$(TARGET)/src/libuv/test/dns-server.o \
-       $(obj).target/$(TARGET)/src/libuv/test/echo-server.o \
-       $(obj).target/$(TARGET)/src/libuv/test/blackhole-server.o \
-       $(obj).target/$(TARGET)/src/libuv/test/run-benchmarks.o \
-       $(obj).target/$(TARGET)/src/libuv/test/runner.o \
-       $(obj).target/$(TARGET)/src/libuv/test/runner-unix.o
-
-# Add to the list of files we specially track dependencies for.
-all_deps += $(OBJS)
-
-# Make sure our dependencies are built before any of us.
-$(OBJS): | $(obj).target/src/libuv/libuv.a
-
-# CFLAGS et al overrides must be target-local.
-# See "Target-specific Variable Values" in the GNU Make manual.
-$(OBJS): TOOLSET := $(TOOLSET)
-$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
-$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
-
-# Suffix rules, putting all outputs into $(obj).
-
-$(obj).$(TOOLSET)/$(TARGET)/%.o: $(srcdir)/%.c FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-
-# Try building from generated source, too.
-
-$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj).$(TOOLSET)/%.c FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-
-$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.c FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-
-# End of this set of suffix rules
-### Rules for final target.
-LDFLAGS_Default := 
-
-LIBS := 
-
-$(builddir)/run-benchmarks: GYP_LDFLAGS := $(LDFLAGS_$(BUILDTYPE))
-$(builddir)/run-benchmarks: LIBS := $(LIBS)
-$(builddir)/run-benchmarks: LD_INPUTS := $(OBJS) $(obj).target/src/libuv/libuv.a
-$(builddir)/run-benchmarks: TOOLSET := $(TOOLSET)
-$(builddir)/run-benchmarks: $(OBJS) $(obj).target/src/libuv/libuv.a FORCE_DO_CMD
-       $(call do_cmd,link)
-
-all_deps += $(builddir)/run-benchmarks
-# Add target alias
-.PHONY: run-benchmarks
-run-benchmarks: $(builddir)/run-benchmarks
-
-# Add executable to "all" target.
-.PHONY: all
-all: $(builddir)/run-benchmarks
-
diff --git a/mk/libuv/x86_64/freebsd/src/libuv/run-tests.target.mk b/mk/libuv/x86_64/freebsd/src/libuv/run-tests.target.mk
deleted file mode 100644 (file)
index 7eb08d1..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-TOOLSET := target
-TARGET := run-tests
-DEFS_Default := '-D_LARGEFILE_SOURCE' \
-       '-D_FILE_OFFSET_BITS=64' \
-       '-D_GNU_SOURCE' \
-       '-DEIO_STACKSIZE=262144'
-
-# Flags passed to all source files.
-CFLAGS_Default := -pthread
-
-# Flags passed to only C files.
-CFLAGS_C_Default := 
-
-# Flags passed to only C++ files.
-CFLAGS_CC_Default := 
-
-INCS_Default := -I$(srcdir)/src/libuv/include
-
-OBJS := $(obj).target/$(TARGET)/src/libuv/test/blackhole-server.o \
-       $(obj).target/$(TARGET)/src/libuv/test/echo-server.o \
-       $(obj).target/$(TARGET)/src/libuv/test/run-tests.o \
-       $(obj).target/$(TARGET)/src/libuv/test/runner.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-get-loadavg.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-async.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-error.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-callback-stack.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-connection-fail.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-delayed-accept.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-fail-always.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-fs.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-fs-event.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-get-currentexe.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-get-memory.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-getaddrinfo.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-gethostbyname.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-getsockname.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-hrtime.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-idle.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-ipc.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-loop-handles.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-multiple-listen.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-pass-always.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-ping-pong.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-pipe-bind-error.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-pipe-connect-error.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-ref.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-shutdown-eof.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-spawn.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-stdio-over-pipes.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-tcp-bind-error.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-tcp-bind6-error.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-tcp-close.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-tcp-flags.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-tcp-connect-error.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-tcp-connect6-error.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-tcp-write-error.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-tcp-write-to-half-open-connection.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-tcp-writealot.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-threadpool.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-timer-again.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-timer.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-tty.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-udp-dgram-too-big.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-udp-ipv6.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-udp-send-and-recv.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-udp-multicast-join.o \
-       $(obj).target/$(TARGET)/src/libuv/test/runner-unix.o
-
-# Add to the list of files we specially track dependencies for.
-all_deps += $(OBJS)
-
-# Make sure our dependencies are built before any of us.
-$(OBJS): | $(obj).target/src/libuv/libuv.a
-
-# CFLAGS et al overrides must be target-local.
-# See "Target-specific Variable Values" in the GNU Make manual.
-$(OBJS): TOOLSET := $(TOOLSET)
-$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
-$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
-
-# Suffix rules, putting all outputs into $(obj).
-
-$(obj).$(TOOLSET)/$(TARGET)/%.o: $(srcdir)/%.c FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-
-# Try building from generated source, too.
-
-$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj).$(TOOLSET)/%.c FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-
-$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.c FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-
-# End of this set of suffix rules
-### Rules for final target.
-LDFLAGS_Default := 
-
-LIBS := 
-
-$(builddir)/run-tests: GYP_LDFLAGS := $(LDFLAGS_$(BUILDTYPE))
-$(builddir)/run-tests: LIBS := $(LIBS)
-$(builddir)/run-tests: LD_INPUTS := $(OBJS) $(obj).target/src/libuv/libuv.a
-$(builddir)/run-tests: TOOLSET := $(TOOLSET)
-$(builddir)/run-tests: $(OBJS) $(obj).target/src/libuv/libuv.a FORCE_DO_CMD
-       $(call do_cmd,link)
-
-all_deps += $(builddir)/run-tests
-# Add target alias
-.PHONY: run-tests
-run-tests: $(builddir)/run-tests
-
-# Add executable to "all" target.
-.PHONY: all
-all: $(builddir)/run-tests
-
diff --git a/mk/libuv/x86_64/freebsd/src/libuv/uv.Makefile b/mk/libuv/x86_64/freebsd/src/libuv/uv.Makefile
deleted file mode 100644 (file)
index 3842bae..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-export builddir_name ?= mk/libuv/x86_64/unix/./src/libuv/out
-.PHONY: all
-all:
-       $(MAKE) -C ../.. uv run-benchmarks run-tests
diff --git a/mk/libuv/x86_64/freebsd/src/libuv/uv.target.mk b/mk/libuv/x86_64/freebsd/src/libuv/uv.target.mk
deleted file mode 100644 (file)
index f1b0225..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-TOOLSET := target
-TARGET := uv
-DEFS_Default := '-D_LARGEFILE_SOURCE' \
-       '-D_FILE_OFFSET_BITS=64' \
-       '-D_GNU_SOURCE' \
-       '-DEIO_STACKSIZE=262144' \
-       '-DHAVE_CONFIG_H' \
-       '-DEV_CONFIG_H="config_freebsd.h"' \
-       '-DEIO_CONFIG_H="config_freebsd.h"'
-
-# Flags passed to all source files.
-CFLAGS_Default := -pthread \
-       -g \
-       --std=gnu89 \
-       -pedantic \
-       -Wall \
-       -Wextra \
-       -Wno-unused-parameter
-
-# Flags passed to only C files.
-CFLAGS_C_Default := 
-
-# Flags passed to only C++ files.
-CFLAGS_CC_Default := 
-
-INCS_Default := -I$(srcdir)/src/libuv/include \
-       -I$(srcdir)/src/libuv/include/uv-private \
-       -I$(srcdir)/src/libuv/src \
-       -I$(srcdir)/src/libuv/src/unix/ev \
-       -I$(srcdir)/src/libuv/src/ares/config_freebsd
-
-OBJS := $(obj).target/$(TARGET)/src/libuv/src/uv-common.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_cancel.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares__close_sockets.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_data.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_destroy.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_expand_name.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_expand_string.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_fds.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_free_hostent.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_free_string.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_gethostbyaddr.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_gethostbyname.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares__get_hostent.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_getnameinfo.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_getopt.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_getsock.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_init.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_library_init.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_llist.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_mkquery.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_nowarn.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_options.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_parse_aaaa_reply.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_parse_a_reply.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_parse_mx_reply.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_parse_ns_reply.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_parse_ptr_reply.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_parse_srv_reply.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_parse_txt_reply.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_process.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_query.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares__read_line.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_search.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_send.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_strcasecmp.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_strdup.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_strerror.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_timeout.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares__timeval.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_version.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_writev.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/bitncmp.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/inet_net_pton.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/inet_ntop.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/windows_port.o \
-       $(obj).target/$(TARGET)/src/libuv/src/unix/core.o \
-       $(obj).target/$(TARGET)/src/libuv/src/unix/uv-eio.o \
-       $(obj).target/$(TARGET)/src/libuv/src/unix/fs.o \
-       $(obj).target/$(TARGET)/src/libuv/src/unix/udp.o \
-       $(obj).target/$(TARGET)/src/libuv/src/unix/tcp.o \
-       $(obj).target/$(TARGET)/src/libuv/src/unix/pipe.o \
-       $(obj).target/$(TARGET)/src/libuv/src/unix/tty.o \
-       $(obj).target/$(TARGET)/src/libuv/src/unix/stream.o \
-       $(obj).target/$(TARGET)/src/libuv/src/unix/cares.o \
-       $(obj).target/$(TARGET)/src/libuv/src/unix/dl.o \
-       $(obj).target/$(TARGET)/src/libuv/src/unix/error.o \
-       $(obj).target/$(TARGET)/src/libuv/src/unix/process.o \
-       $(obj).target/$(TARGET)/src/libuv/src/unix/eio/eio.o \
-       $(obj).target/$(TARGET)/src/libuv/src/unix/ev/ev.o \
-       $(obj).target/$(TARGET)/src/libuv/src/unix/freebsd.o \
-       $(obj).target/$(TARGET)/src/libuv/src/unix/kqueue.o
-
-# Add to the list of files we specially track dependencies for.
-all_deps += $(OBJS)
-
-# CFLAGS et al overrides must be target-local.
-# See "Target-specific Variable Values" in the GNU Make manual.
-$(OBJS): TOOLSET := $(TOOLSET)
-$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
-$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
-
-# Suffix rules, putting all outputs into $(obj).
-
-$(obj).$(TOOLSET)/$(TARGET)/%.o: $(srcdir)/%.c FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-
-# Try building from generated source, too.
-
-$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj).$(TOOLSET)/%.c FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-
-$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.c FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-
-# End of this set of suffix rules
-### Rules for final target.
-LDFLAGS_Default := 
-
-LIBS := -lm
-
-$(obj).target/src/libuv/libuv.a: GYP_LDFLAGS := $(LDFLAGS_$(BUILDTYPE))
-$(obj).target/src/libuv/libuv.a: LIBS := $(LIBS)
-$(obj).target/src/libuv/libuv.a: TOOLSET := $(TOOLSET)
-$(obj).target/src/libuv/libuv.a: $(OBJS) FORCE_DO_CMD
-       $(call do_cmd,alink)
-
-all_deps += $(obj).target/src/libuv/libuv.a
-# Add target alias
-.PHONY: uv
-uv: $(obj).target/src/libuv/libuv.a
-
-# Add target alias to "all" target.
-.PHONY: all
-all: uv
-
index 781fa41bea9249798c6a57e34117f1b4655b9460..bae2ca0016bfdf2a39fe09977163c0590959e9af 100644 (file)
@@ -8,6 +8,7 @@ MAKEFLAGS=-r
 
 # The source directory tree.
 srcdir := ../../../..
+abs_srcdir := $(abspath $(srcdir))
 
 # The name of the builddir.
 builddir_name ?= out
@@ -20,7 +21,7 @@ else
 endif
 
 # Specify BUILDTYPE=Release on the command line for a release build.
-BUILDTYPE ?= Default
+BUILDTYPE ?= Debug
 
 # Directory all our build output goes into.
 # Note that this must be two directories beneath src/ for unit tests to pass,
@@ -147,7 +148,7 @@ cmd_objcxx = $(CXX.$(TOOLSET)) $(GYP_OBJCXXFLAGS) $(DEPFLAGS) -c -o $@ $<
 quiet_cmd_pch_c = CXX($(TOOLSET)) $@
 cmd_pch_c = $(CC.$(TOOLSET)) $(GYP_PCH_CFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $<
 quiet_cmd_pch_cc = CXX($(TOOLSET)) $@
-cmd_pch_cc = $(CC.$(TOOLSET)) $(GYP_PCH_CCFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $<
+cmd_pch_cc = $(CC.$(TOOLSET)) $(GYP_PCH_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $<
 quiet_cmd_pch_m = CXX($(TOOLSET)) $@
 cmd_pch_m = $(CC.$(TOOLSET)) $(GYP_PCH_OBJCFLAGS) $(DEPFLAGS) -c -o $@ $<
 quiet_cmd_pch_mm = CXX($(TOOLSET)) $@
@@ -162,6 +163,9 @@ cmd_mac_tool = ./gyp-mac-tool $(4) $< "$@"
 quiet_cmd_mac_package_framework = PACKAGE FRAMEWORK $@
 cmd_mac_package_framework = ./gyp-mac-tool package-framework "$@" $(4)
 
+quiet_cmd_infoplist = INFOPLIST $@
+cmd_infoplist = $(CC.$(TOOLSET)) -E -P -Wno-trigraphs -x c $(INFOPLIST_DEFINES) "$<" -o "$@"
+
 quiet_cmd_touch = TOUCH $@
 cmd_touch = touch $@
 
@@ -262,8 +266,8 @@ $(if $(or $(command_changed),$(prereq_changed)),
 )
 endef
 
-# Declare "all" target first so it is the default, even though we don't have the
-# deps yet.
+# Declare the "all" target first so it is the default,
+# even though we don't have the deps yet.
 .PHONY: all
 all:
 
@@ -343,9 +347,9 @@ ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
   include src/libuv/uv.target.mk
 endif
 
-quiet_cmd_regen_makefile = ACTION Regenerating $@
-cmd_regen_makefile = ./src/libuv/build/gyp/gyp -fmake --ignore-environment "--toplevel-dir=." "--depth=." "--generator-output=mk/libuv/x86_64/mac" "-Dlibrary=static_library" "-Dtarget_arch=x86_64" "-DOS=mac" src/libuv/uv.gyp
-Makefile: $(srcdir)/src/libuv/uv.gyp
+#quiet_cmd_regen_makefile = ACTION Regenerating $@
+#cmd_regen_makefile = ./src/libuv/build/gyp/gyp -fmake --ignore-environment "--toplevel-dir=." -Isrc/libuv/common.gypi "--depth=." "--generator-output=mk/libuv/x86_64/mac" "-Ddefault_configuration=Default" "-Dcomponent=static_library" "-Dlibrary=static_library" "-Dtarget_arch=x86_64" "-DOS=mac" src/libuv/uv.gyp
+#Makefile: $(srcdir)/src/libuv/uv.gyp $(srcdir)/src/libuv/common.gypi
 #      $(call do_cmd,regen_makefile)
 
 # "all" is a concatenation of the "all" targets from all the included
diff --git a/mk/libuv/x86_64/mac/Makefile-e b/mk/libuv/x86_64/mac/Makefile-e
deleted file mode 100644 (file)
index 44d99ba..0000000
+++ /dev/null
@@ -1,375 +0,0 @@
-# We borrow heavily from the kernel build setup, though we are simpler since
-# we don't have Kconfig tweaking settings on us.
-
-# The implicit make rules have it looking for RCS files, among other things.
-# We instead explicitly write all the rules we care about.
-# It's even quicker (saves ~200ms) to pass -r on the command line.
-MAKEFLAGS=-r
-
-# The source directory tree.
-srcdir := ../../../..
-
-# The name of the builddir.
-builddir_name ?= out
-
-# The V=1 flag on command line makes us verbosely print command lines.
-ifdef V
-  quiet=
-else
-  quiet=quiet_
-endif
-
-# Specify BUILDTYPE=Release on the command line for a release build.
-BUILDTYPE ?= Default
-
-# Directory all our build output goes into.
-# Note that this must be two directories beneath src/ for unit tests to pass,
-# as they reach into the src/ directory for data with relative paths.
-builddir ?= $(builddir_name)/$(BUILDTYPE)
-abs_builddir := $(abspath $(builddir))
-depsdir := $(builddir)/.deps
-
-# Object output directory.
-obj := $(builddir)/obj
-abs_obj := $(abspath $(obj))
-
-# We build up a list of every single one of the targets so we can slurp in the
-# generated dependency rule Makefiles in one pass.
-all_deps :=
-
-
-
-# C++ apps need to be linked with g++.
-#
-# Note: flock is used to seralize linking. Linking is a memory-intensive
-# process so running parallel links can often lead to thrashing.  To disable
-# the serialization, override LINK via an envrionment variable as follows:
-#
-#   export LINK=g++
-#
-# This will allow make to invoke N linker processes as specified in -jN.
-LINK ?= ./gyp-mac-tool flock $(builddir)/linker.lock $(CXX)
-
-CC.target ?= $(CC)
-CFLAGS.target ?= $(CFLAGS)
-CXX.target ?= $(CXX)
-CXXFLAGS.target ?= $(CXXFLAGS)
-LINK.target ?= $(LINK)
-LDFLAGS.target ?= $(LDFLAGS) 
-AR.target ?= $(AR)
-ARFLAGS.target ?= crs
-
-# N.B.: the logic of which commands to run should match the computation done
-# in gyp's make.py where ARFLAGS.host etc. is computed.
-# TODO(evan): move all cross-compilation logic to gyp-time so we don't need
-# to replicate this environment fallback in make as well.
-CC.host ?= gcc
-CFLAGS.host ?=
-CXX.host ?= g++
-CXXFLAGS.host ?=
-LINK.host ?= g++
-LDFLAGS.host ?=
-AR.host ?= ar
-ARFLAGS.host := crs
-
-# Define a dir function that can handle spaces.
-# http://www.gnu.org/software/make/manual/make.html#Syntax-of-Functions
-# "leading spaces cannot appear in the text of the first argument as written.
-# These characters can be put into the argument value by variable substitution."
-empty :=
-space := $(empty) $(empty)
-
-# http://stackoverflow.com/questions/1189781/using-make-dir-or-notdir-on-a-path-with-spaces
-replace_spaces = $(subst $(space),?,$1)
-unreplace_spaces = $(subst ?,$(space),$1)
-dirx = $(call unreplace_spaces,$(dir $(call replace_spaces,$1)))
-
-# Flags to make gcc output dependency info.  Note that you need to be
-# careful here to use the flags that ccache and distcc can understand.
-# We write to a dep file on the side first and then rename at the end
-# so we can't end up with a broken dep file.
-depfile = $(depsdir)/$(call replace_spaces,$@).d
-DEPFLAGS = -MMD -MF $(depfile).raw
-
-# We have to fixup the deps output in a few ways.
-# (1) the file output should mention the proper .o file.
-# ccache or distcc lose the path to the target, so we convert a rule of
-# the form:
-#   foobar.o: DEP1 DEP2
-# into
-#   path/to/foobar.o: DEP1 DEP2
-# (2) we want missing files not to cause us to fail to build.
-# We want to rewrite
-#   foobar.o: DEP1 DEP2 \
-#               DEP3
-# to
-#   DEP1:
-#   DEP2:
-#   DEP3:
-# so if the files are missing, they're just considered phony rules.
-# We have to do some pretty insane escaping to get those backslashes
-# and dollar signs past make, the shell, and sed at the same time.
-# Doesn't work with spaces, but that's fine: .d files have spaces in
-# their names replaced with other characters.
-define fixup_dep
-# The depfile may not exist if the input file didn't have any #includes.
-touch $(depfile).raw
-# Fixup path as in (1).
-sed -e "s|^$(notdir $@)|$@|" $(depfile).raw >> $(depfile)
-# Add extra rules as in (2).
-# We remove slashes and replace spaces with new lines;
-# remove blank lines;
-# delete the first line and append a colon to the remaining lines.
-sed -e 's|\\||' -e 'y| |\n|' $(depfile).raw |\
-  grep -v '^$$'                             |\
-  sed -e 1d -e 's|$$|:|'                     \
-    >> $(depfile)
-rm $(depfile).raw
-endef
-
-# Command definitions:
-# - cmd_foo is the actual command to run;
-# - quiet_cmd_foo is the brief-output summary of the command.
-
-quiet_cmd_cc = CC($(TOOLSET)) $@
-cmd_cc = $(CC.$(TOOLSET)) $(GYP_CFLAGS) $(DEPFLAGS) $(CFLAGS.$(TOOLSET)) -c -o $@ $<
-
-quiet_cmd_cxx = CXX($(TOOLSET)) $@
-cmd_cxx = $(CXX.$(TOOLSET)) $(GYP_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $<
-
-quiet_cmd_objc = CXX($(TOOLSET)) $@
-cmd_objc = $(CC.$(TOOLSET)) $(GYP_OBJCFLAGS) $(DEPFLAGS) -c -o $@ $<
-
-quiet_cmd_objcxx = CXX($(TOOLSET)) $@
-cmd_objcxx = $(CXX.$(TOOLSET)) $(GYP_OBJCXXFLAGS) $(DEPFLAGS) -c -o $@ $<
-
-# Commands for precompiled header files.
-quiet_cmd_pch_c = CXX($(TOOLSET)) $@
-cmd_pch_c = $(CC.$(TOOLSET)) $(GYP_PCH_CFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $<
-quiet_cmd_pch_cc = CXX($(TOOLSET)) $@
-cmd_pch_cc = $(CC.$(TOOLSET)) $(GYP_PCH_CCFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $<
-quiet_cmd_pch_m = CXX($(TOOLSET)) $@
-cmd_pch_m = $(CC.$(TOOLSET)) $(GYP_PCH_OBJCFLAGS) $(DEPFLAGS) -c -o $@ $<
-quiet_cmd_pch_mm = CXX($(TOOLSET)) $@
-cmd_pch_mm = $(CC.$(TOOLSET)) $(GYP_PCH_OBJCXXFLAGS) $(DEPFLAGS) -c -o $@ $<
-
-# gyp-mac-tool is written next to the root Makefile by gyp.
-# Use $(4) for the command, since $(2) and $(3) are used as flag by do_cmd
-# already.
-quiet_cmd_mac_tool = MACTOOL $(4) $<
-cmd_mac_tool = ./gyp-mac-tool $(4) $< "$@"
-
-quiet_cmd_mac_package_framework = PACKAGE FRAMEWORK $@
-cmd_mac_package_framework = ./gyp-mac-tool package-framework "$@" $(4)
-
-quiet_cmd_touch = TOUCH $@
-cmd_touch = touch $@
-
-quiet_cmd_copy = COPY $@
-# send stderr to /dev/null to ignore messages when linking directories.
-cmd_copy = ln -f "$<" "$@" 2>/dev/null || (rm -rf "$@" && cp -af "$<" "$@")
-
-quiet_cmd_alink = LIBTOOL-STATIC $@
-cmd_alink = rm -f $@ && libtool -static -o $@ $(filter %.o,$^)
-
-quiet_cmd_link = LINK($(TOOLSET)) $@
-cmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o "$@" $(LD_INPUTS) $(LIBS)
-
-# TODO(thakis): Find out and document the difference between shared_library and
-# loadable_module on mac.
-quiet_cmd_solink = SOLINK($(TOOLSET)) $@
-cmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o "$@" $(LD_INPUTS) $(LIBS)
-
-# TODO(thakis): The solink_module rule is likely wrong. Xcode seems to pass
-# -bundle -single_module here (for osmesa.so).
-quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@
-cmd_solink_module = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ $(filter-out FORCE_DO_CMD, $^) $(LIBS)
-
-
-# Define an escape_quotes function to escape single quotes.
-# This allows us to handle quotes properly as long as we always use
-# use single quotes and escape_quotes.
-escape_quotes = $(subst ','\'',$(1))
-# This comment is here just to include a ' to unconfuse syntax highlighting.
-# Define an escape_vars function to escape '$' variable syntax.
-# This allows us to read/write command lines with shell variables (e.g.
-# $LD_LIBRARY_PATH), without triggering make substitution.
-escape_vars = $(subst $$,$$$$,$(1))
-# Helper that expands to a shell command to echo a string exactly as it is in
-# make. This uses printf instead of echo because printf's behaviour with respect
-# to escape sequences is more portable than echo's across different shells
-# (e.g., dash, bash).
-exact_echo = printf '%s\n' '$(call escape_quotes,$(1))'
-
-# Helper to compare the command we're about to run against the command
-# we logged the last time we ran the command.  Produces an empty
-# string (false) when the commands match.
-# Tricky point: Make has no string-equality test function.
-# The kernel uses the following, but it seems like it would have false
-# positives, where one string reordered its arguments.
-#   arg_check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \
-#                       $(filter-out $(cmd_$@), $(cmd_$(1))))
-# We instead substitute each for the empty string into the other, and
-# say they're equal if both substitutions produce the empty string.
-# .d files contain ? instead of spaces, take that into account.
-command_changed = $(or $(subst $(cmd_$(1)),,$(cmd_$(call replace_spaces,$@))),\
-                       $(subst $(cmd_$(call replace_spaces,$@)),,$(cmd_$(1))))
-
-# Helper that is non-empty when a prerequisite changes.
-# Normally make does this implicitly, but we force rules to always run
-# so we can check their command lines.
-#   $? -- new prerequisites
-#   $| -- order-only dependencies
-prereq_changed = $(filter-out FORCE_DO_CMD,$(filter-out $|,$?))
-
-# Helper that executes all postbuilds, and deletes the output file when done
-# if any of the postbuilds failed.
-define do_postbuilds
-  @E=0;\
-  for p in $(POSTBUILDS); do\
-    eval $$p;\
-    F=$$?;\
-    if [ $$F -ne 0 ]; then\
-      E=$$F;\
-    fi;\
-  done;\
-  if [ $$E -ne 0 ]; then\
-    rm -rf "$@";\
-    exit $$E;\
-  fi
-endef
-
-# do_cmd: run a command via the above cmd_foo names, if necessary.
-# Should always run for a given target to handle command-line changes.
-# Second argument, if non-zero, makes it do asm/C/C++ dependency munging.
-# Third argument, if non-zero, makes it do POSTBUILDS processing.
-# Note: We intentionally do NOT call dirx for depfile, since it contains ? for
-# spaces already and dirx strips the ? characters.
-define do_cmd
-$(if $(or $(command_changed),$(prereq_changed)),
-  @$(call exact_echo,  $($(quiet)cmd_$(1)))
-  @mkdir -p "$(call dirx,$@)" "$(dir $(depfile))"
-  $(if $(findstring flock,$(word 2,$(cmd_$1))),
-    @$(cmd_$(1))
-    @echo "  $(quiet_cmd_$(1)): Finished",
-    @$(cmd_$(1))
-  )
-  @$(call exact_echo,$(call escape_vars,cmd_$(call replace_spaces,$@) := $(cmd_$(1)))) > $(depfile)
-  @$(if $(2),$(fixup_dep))
-  $(if $(and $(3), $(POSTBUILDS)),
-    $(call do_postbuilds)
-  )
-)
-endef
-
-# Declare "all" target first so it is the default, even though we don't have the
-# deps yet.
-.PHONY: all
-all:
-
-# Use FORCE_DO_CMD to force a target to run.  Should be coupled with
-# do_cmd.
-.PHONY: FORCE_DO_CMD
-FORCE_DO_CMD:
-
-TOOLSET := target
-# Suffix rules, putting all outputs into $(obj).
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.c FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cc FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cpp FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cxx FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.m FORCE_DO_CMD
-       @$(call do_cmd,objc,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.mm FORCE_DO_CMD
-       @$(call do_cmd,objcxx,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.S FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.s FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-
-# Try building from generated source, too.
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.c FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cc FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cpp FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cxx FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.m FORCE_DO_CMD
-       @$(call do_cmd,objc,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.mm FORCE_DO_CMD
-       @$(call do_cmd,objcxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.S FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.s FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-
-$(obj).$(TOOLSET)/%.o: $(obj)/%.c FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.cc FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.cpp FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.cxx FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.m FORCE_DO_CMD
-       @$(call do_cmd,objc,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.mm FORCE_DO_CMD
-       @$(call do_cmd,objcxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.S FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.s FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-
-
-ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
-    $(findstring $(join ^,$(prefix)),\
-                 $(join ^,src/libuv/run-benchmarks.target.mk)))),)
-  include src/libuv/run-benchmarks.target.mk
-endif
-ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
-    $(findstring $(join ^,$(prefix)),\
-                 $(join ^,src/libuv/run-tests.target.mk)))),)
-  include src/libuv/run-tests.target.mk
-endif
-ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
-    $(findstring $(join ^,$(prefix)),\
-                 $(join ^,src/libuv/uv.target.mk)))),)
-  include src/libuv/uv.target.mk
-endif
-
-quiet_cmd_regen_makefile = ACTION Regenerating $@
-cmd_regen_makefile = ./src/libuv/build/gyp/gyp -fmake --ignore-environment "--toplevel-dir=." "--depth=." "--generator-output=mk/libuv/x86_64/mac" "-Dlibrary=static_library" "-Dtarget_arch=x86_64" "-DOS=mac" src/libuv/uv.gyp
-Makefile: $(srcdir)/src/libuv/uv.gyp
-       $(call do_cmd,regen_makefile)
-
-# "all" is a concatenation of the "all" targets from all the included
-# sub-makefiles. This is just here to clarify.
-all:
-
-# Add in dependency-tracking rules.  $(all_deps) is the list of every single
-# target in our tree. Only consider the ones with .d (dependency) info:
-d_files := $(wildcard $(foreach f,$(all_deps),$(depsdir)/$(f).d))
-ifneq ($(d_files),)
-  # Rather than include each individual .d file, concatenate them into a
-  # single file which make is able to load faster.  We split this into
-  # commands that take 1000 files at a time to avoid overflowing the
-  # command line.
-  $(shell cat $(wordlist 1,1000,$(d_files)) > $(depsdir)/all.deps)
-
-  ifneq ($(word 1001,$(d_files)),)
-    $(error Found unprocessed dependency files (gyp didn't generate enough rules!))
-  endif
-
-  # make looks for ways to re-generate included makefiles, but in our case, we
-  # don't have a direct way. Explicitly telling make that it has nothing to do
-  # for them makes it go faster.
-  $(depsdir)/all.deps: ;
-
-  include $(depsdir)/all.deps
-endif
index 7eb894b23ef66b97de39288e0fa4d5794b5e2a97..bd4059840ea8a6efa2825d0f5ea849e60f15b16b 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python
 # Generated by gyp. Do not edit.
 # Copyright (c) 2011 Google Inc. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
@@ -17,10 +17,12 @@ import string
 import subprocess
 import sys
 
+
 def main(args):
   executor = MacTool()
   executor.Dispatch(args)
 
+
 class MacTool(object):
   """This class performs all the Mac tooling steps. The methods can either be
   executed directly, or dispatched from an argument list."""
@@ -74,12 +76,14 @@ class MacTool(object):
     if not plist:
       return
 
+    # Only create PkgInfo for executable types.
+    package_type = plist['CFBundlePackageType']
+    if package_type != 'APPL':
+      return
+
     # The format of PkgInfo is eight characters, representing the bundle type
-    # and bundle signature, each four characters. If either is missing, four
+    # and bundle signature, each four characters. If that is missing, four
     # '?' characters are used instead.
-    package_type = plist['CFBundlePackageType']
-    if len(package_type) != 4:
-      package_type = '?' * 4
     signature_code = plist['CFBundleSignature']
     if len(signature_code) != 4:
       signature_code = '?' * 4
@@ -184,5 +188,6 @@ class MacTool(object):
     else:
       return None
 
+
 if __name__ == '__main__':
   sys.exit(main(sys.argv[1:]))
index 1dfb1515524343b9feeb9fb05d91598ad58b4fe1..f5930c9dc564d3d53dedece6866cadf828f6aeb9 100644 (file)
@@ -2,31 +2,77 @@
 
 TOOLSET := target
 TARGET := run-benchmarks
-DEFS_Default := '-D_LARGEFILE_SOURCE' \
+DEFS_Debug := '-D_LARGEFILE_SOURCE' \
        '-D_FILE_OFFSET_BITS=64' \
        '-D_GNU_SOURCE' \
-       '-DEIO_STACKSIZE=262144'
+       '-DEIO_STACKSIZE=262144' \
+       '-DDEBUG' \
+       '-D_DEBUG' \
+       '-DEV_VERIFY=2'
 
 # Flags passed to all source files.
-CFLAGS_Default := -fasm-blocks \
-       -mpascal-strings \
-       -Os \
+CFLAGS_Debug := -Os \
        -gdwarf-2 \
-       -arch x86_64
+       -fvisibility=hidden \
+       -Wnewline-eof \
+       -arch x86_64 \
+       -fno-strict-aliasing \
+       -Wall \
+       -Wendif-labels \
+       -W \
+       -Wno-unused-parameter
 
 # Flags passed to only C files.
-CFLAGS_C_Default := 
+CFLAGS_C_Debug := 
 
 # Flags passed to only C++ files.
-CFLAGS_CC_Default := 
+CFLAGS_CC_Debug := -fno-rtti \
+       -fno-exceptions \
+       -fvisibility-inlines-hidden \
+       -fno-threadsafe-statics
 
 # Flags passed to only ObjC files.
-CFLAGS_OBJC_Default := 
+CFLAGS_OBJC_Debug := 
 
 # Flags passed to only ObjC++ files.
-CFLAGS_OBJCC_Default := 
+CFLAGS_OBJCC_Debug := 
 
-INCS_Default := -I$(srcdir)/src/libuv/include
+INCS_Debug := -I$(srcdir)/src/libuv/include
+
+DEFS_Release := '-D_LARGEFILE_SOURCE' \
+       '-D_FILE_OFFSET_BITS=64' \
+       '-D_GNU_SOURCE' \
+       '-DEIO_STACKSIZE=262144' \
+       '-DNDEBUG'
+
+# Flags passed to all source files.
+CFLAGS_Release := -Os \
+       -gdwarf-2 \
+       -fvisibility=hidden \
+       -Wnewline-eof \
+       -arch x86_64 \
+       -fno-strict-aliasing \
+       -Wall \
+       -Wendif-labels \
+       -W \
+       -Wno-unused-parameter
+
+# Flags passed to only C files.
+CFLAGS_C_Release := 
+
+# Flags passed to only C++ files.
+CFLAGS_CC_Release := -fno-rtti \
+       -fno-exceptions \
+       -fvisibility-inlines-hidden \
+       -fno-threadsafe-statics
+
+# Flags passed to only ObjC files.
+CFLAGS_OBJC_Release := 
+
+# Flags passed to only ObjC++ files.
+CFLAGS_OBJCC_Release := 
+
+INCS_Release := -I$(srcdir)/src/libuv/include
 
 OBJS := $(obj).target/$(TARGET)/src/libuv/test/benchmark-ares.o \
        $(obj).target/$(TARGET)/src/libuv/test/benchmark-getaddrinfo.o \
@@ -35,6 +81,7 @@ OBJS := $(obj).target/$(TARGET)/src/libuv/test/benchmark-ares.o \
        $(obj).target/$(TARGET)/src/libuv/test/benchmark-pump.o \
        $(obj).target/$(TARGET)/src/libuv/test/benchmark-sizes.o \
        $(obj).target/$(TARGET)/src/libuv/test/benchmark-spawn.o \
+       $(obj).target/$(TARGET)/src/libuv/test/benchmark-thread.o \
        $(obj).target/$(TARGET)/src/libuv/test/benchmark-tcp-write-batch.o \
        $(obj).target/$(TARGET)/src/libuv/test/benchmark-udp-packet-storm.o \
        $(obj).target/$(TARGET)/src/libuv/test/dns-server.o \
@@ -53,10 +100,10 @@ $(OBJS): | $(builddir)/libuv.a
 # CFLAGS et al overrides must be target-local.
 # See "Target-specific Variable Values" in the GNU Make manual.
 $(OBJS): TOOLSET := $(TOOLSET)
-$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
-$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
-$(OBJS): GYP_OBJCFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE)) $(CFLAGS_OBJC_$(BUILDTYPE))
-$(OBJS): GYP_OBJCXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE)) $(CFLAGS_OBJCC_$(BUILDTYPE))
+$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
+$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
+$(OBJS): GYP_OBJCFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE)) $(CFLAGS_OBJC_$(BUILDTYPE))
+$(OBJS): GYP_OBJCXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE)) $(CFLAGS_OBJCC_$(BUILDTYPE))
 
 # Suffix rules, putting all outputs into $(obj).
 
@@ -73,7 +120,12 @@ $(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.c FORCE_DO_CMD
 
 # End of this set of suffix rules
 ### Rules for final target.
-LDFLAGS_Default := -arch x86_64 \
+LDFLAGS_Debug := -Wl,-search_paths_first \
+       -arch x86_64 \
+       -L$(builddir)
+
+LDFLAGS_Release := -Wl,-search_paths_first \
+       -arch x86_64 \
        -L$(builddir)
 
 LIBS := -framework Carbon \
diff --git a/mk/libuv/x86_64/mac/src/libuv/run-benchmarks.target.mk-e b/mk/libuv/x86_64/mac/src/libuv/run-benchmarks.target.mk-e
deleted file mode 100644 (file)
index 64d150f..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-TOOLSET := target
-TARGET := run-benchmarks
-DEFS_Default := '-D_LARGEFILE_SOURCE' \
-       '-D_FILE_OFFSET_BITS=64' \
-       '-D_GNU_SOURCE' \
-       '-DEIO_STACKSIZE=262144'
-
-# Flags passed to all source files.
-CFLAGS_Default := -fasm-blocks \
-       -mpascal-strings \
-       -Os \
-       -gdwarf-2 \
-       -arch i386
-
-# Flags passed to only C files.
-CFLAGS_C_Default := 
-
-# Flags passed to only C++ files.
-CFLAGS_CC_Default := 
-
-# Flags passed to only ObjC files.
-CFLAGS_OBJC_Default := 
-
-# Flags passed to only ObjC++ files.
-CFLAGS_OBJCC_Default := 
-
-INCS_Default := -I$(srcdir)/src/libuv/include
-
-OBJS := $(obj).target/$(TARGET)/src/libuv/test/benchmark-ares.o \
-       $(obj).target/$(TARGET)/src/libuv/test/benchmark-getaddrinfo.o \
-       $(obj).target/$(TARGET)/src/libuv/test/benchmark-ping-pongs.o \
-       $(obj).target/$(TARGET)/src/libuv/test/benchmark-pound.o \
-       $(obj).target/$(TARGET)/src/libuv/test/benchmark-pump.o \
-       $(obj).target/$(TARGET)/src/libuv/test/benchmark-sizes.o \
-       $(obj).target/$(TARGET)/src/libuv/test/benchmark-spawn.o \
-       $(obj).target/$(TARGET)/src/libuv/test/benchmark-tcp-write-batch.o \
-       $(obj).target/$(TARGET)/src/libuv/test/benchmark-udp-packet-storm.o \
-       $(obj).target/$(TARGET)/src/libuv/test/dns-server.o \
-       $(obj).target/$(TARGET)/src/libuv/test/echo-server.o \
-       $(obj).target/$(TARGET)/src/libuv/test/blackhole-server.o \
-       $(obj).target/$(TARGET)/src/libuv/test/run-benchmarks.o \
-       $(obj).target/$(TARGET)/src/libuv/test/runner.o \
-       $(obj).target/$(TARGET)/src/libuv/test/runner-unix.o
-
-# Add to the list of files we specially track dependencies for.
-all_deps += $(OBJS)
-
-# Make sure our dependencies are built before any of us.
-$(OBJS): | $(builddir)/libuv.a
-
-# CFLAGS et al overrides must be target-local.
-# See "Target-specific Variable Values" in the GNU Make manual.
-$(OBJS): TOOLSET := $(TOOLSET)
-$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
-$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
-$(OBJS): GYP_OBJCFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE)) $(CFLAGS_OBJC_$(BUILDTYPE))
-$(OBJS): GYP_OBJCXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE)) $(CFLAGS_OBJCC_$(BUILDTYPE))
-
-# Suffix rules, putting all outputs into $(obj).
-
-$(obj).$(TOOLSET)/$(TARGET)/%.o: $(srcdir)/%.c FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-
-# Try building from generated source, too.
-
-$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj).$(TOOLSET)/%.c FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-
-$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.c FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-
-# End of this set of suffix rules
-### Rules for final target.
-LDFLAGS_Default := -arch i386 \
-       -L$(builddir)
-
-LIBS := -framework Carbon \
-       -framework CoreServices
-
-$(builddir)/run-benchmarks: GYP_LDFLAGS := $(LDFLAGS_$(BUILDTYPE))
-$(builddir)/run-benchmarks: LIBS := $(LIBS)
-$(builddir)/run-benchmarks: LD_INPUTS := $(OBJS) $(builddir)/libuv.a
-$(builddir)/run-benchmarks: TOOLSET := $(TOOLSET)
-$(builddir)/run-benchmarks: $(OBJS) $(builddir)/libuv.a FORCE_DO_CMD
-       $(call do_cmd,link)
-
-all_deps += $(builddir)/run-benchmarks
-# Add target alias
-.PHONY: run-benchmarks
-run-benchmarks: $(builddir)/run-benchmarks
-
-# Add executable to "all" target.
-.PHONY: all
-all: $(builddir)/run-benchmarks
-
index 498e3b562e7a4d32b0e92e2feee3eb9ef176141f..4694c7cfd4d6ad45c7dfeb6a8a059bb241257cc0 100644 (file)
@@ -2,42 +2,91 @@
 
 TOOLSET := target
 TARGET := run-tests
-DEFS_Default := '-D_LARGEFILE_SOURCE' \
+DEFS_Debug := '-D_LARGEFILE_SOURCE' \
        '-D_FILE_OFFSET_BITS=64' \
        '-D_GNU_SOURCE' \
-       '-DEIO_STACKSIZE=262144'
+       '-DEIO_STACKSIZE=262144' \
+       '-DDEBUG' \
+       '-D_DEBUG' \
+       '-DEV_VERIFY=2'
 
 # Flags passed to all source files.
-CFLAGS_Default := -fasm-blocks \
-       -mpascal-strings \
-       -Os \
+CFLAGS_Debug := -Os \
        -gdwarf-2 \
-       -arch x86_64
+       -fvisibility=hidden \
+       -Wnewline-eof \
+       -arch x86_64 \
+       -fno-strict-aliasing \
+       -Wall \
+       -Wendif-labels \
+       -W \
+       -Wno-unused-parameter
 
 # Flags passed to only C files.
-CFLAGS_C_Default := 
+CFLAGS_C_Debug := 
 
 # Flags passed to only C++ files.
-CFLAGS_CC_Default := 
+CFLAGS_CC_Debug := -fno-rtti \
+       -fno-exceptions \
+       -fvisibility-inlines-hidden \
+       -fno-threadsafe-statics
 
 # Flags passed to only ObjC files.
-CFLAGS_OBJC_Default := 
+CFLAGS_OBJC_Debug := 
 
 # Flags passed to only ObjC++ files.
-CFLAGS_OBJCC_Default := 
+CFLAGS_OBJCC_Debug := 
 
-INCS_Default := -I$(srcdir)/src/libuv/include
+INCS_Debug := -I$(srcdir)/src/libuv/include
+
+DEFS_Release := '-D_LARGEFILE_SOURCE' \
+       '-D_FILE_OFFSET_BITS=64' \
+       '-D_GNU_SOURCE' \
+       '-DEIO_STACKSIZE=262144' \
+       '-DNDEBUG'
+
+# Flags passed to all source files.
+CFLAGS_Release := -Os \
+       -gdwarf-2 \
+       -fvisibility=hidden \
+       -Wnewline-eof \
+       -arch x86_64 \
+       -fno-strict-aliasing \
+       -Wall \
+       -Wendif-labels \
+       -W \
+       -Wno-unused-parameter
+
+# Flags passed to only C files.
+CFLAGS_C_Release := 
+
+# Flags passed to only C++ files.
+CFLAGS_CC_Release := -fno-rtti \
+       -fno-exceptions \
+       -fvisibility-inlines-hidden \
+       -fno-threadsafe-statics
+
+# Flags passed to only ObjC files.
+CFLAGS_OBJC_Release := 
+
+# Flags passed to only ObjC++ files.
+CFLAGS_OBJCC_Release := 
+
+INCS_Release := -I$(srcdir)/src/libuv/include
 
 OBJS := $(obj).target/$(TARGET)/src/libuv/test/blackhole-server.o \
        $(obj).target/$(TARGET)/src/libuv/test/echo-server.o \
        $(obj).target/$(TARGET)/src/libuv/test/run-tests.o \
        $(obj).target/$(TARGET)/src/libuv/test/runner.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-get-loadavg.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-util.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-async.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-error.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-callback-stack.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-connection-fail.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-cwd-and-chdir.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-delayed-accept.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-eio-overflow.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-fail-always.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-fs.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-fs-event.o \
@@ -49,12 +98,15 @@ OBJS := $(obj).target/$(TARGET)/src/libuv/test/blackhole-server.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-hrtime.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-idle.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-ipc.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-ipc-threads.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-loop-handles.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-multiple-listen.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-pass-always.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-ping-pong.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-pipe-bind-error.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-pipe-connect-error.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-platform-output.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-process-title.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-ref.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-shutdown-eof.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-spawn.o \
@@ -69,13 +121,17 @@ OBJS := $(obj).target/$(TARGET)/src/libuv/test/blackhole-server.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-tcp-write-to-half-open-connection.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-tcp-writealot.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-threadpool.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-mutexes.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-thread.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-timer-again.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-timer.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-tty.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-udp-dgram-too-big.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-udp-ipv6.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-udp-options.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-udp-send-and-recv.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-udp-multicast-join.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-counters-init.o \
        $(obj).target/$(TARGET)/src/libuv/test/runner-unix.o
 
 # Add to the list of files we specially track dependencies for.
@@ -87,10 +143,10 @@ $(OBJS): | $(builddir)/libuv.a
 # CFLAGS et al overrides must be target-local.
 # See "Target-specific Variable Values" in the GNU Make manual.
 $(OBJS): TOOLSET := $(TOOLSET)
-$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
-$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
-$(OBJS): GYP_OBJCFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE)) $(CFLAGS_OBJC_$(BUILDTYPE))
-$(OBJS): GYP_OBJCXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE)) $(CFLAGS_OBJCC_$(BUILDTYPE))
+$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
+$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
+$(OBJS): GYP_OBJCFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE)) $(CFLAGS_OBJC_$(BUILDTYPE))
+$(OBJS): GYP_OBJCXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE)) $(CFLAGS_OBJCC_$(BUILDTYPE))
 
 # Suffix rules, putting all outputs into $(obj).
 
@@ -107,7 +163,12 @@ $(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.c FORCE_DO_CMD
 
 # End of this set of suffix rules
 ### Rules for final target.
-LDFLAGS_Default := -arch x86_64 \
+LDFLAGS_Debug := -Wl,-search_paths_first \
+       -arch x86_64 \
+       -L$(builddir)
+
+LDFLAGS_Release := -Wl,-search_paths_first \
+       -arch x86_64 \
        -L$(builddir)
 
 LIBS := -framework Carbon \
diff --git a/mk/libuv/x86_64/mac/src/libuv/run-tests.target.mk-e b/mk/libuv/x86_64/mac/src/libuv/run-tests.target.mk-e
deleted file mode 100644 (file)
index 5a5730b..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-TOOLSET := target
-TARGET := run-tests
-DEFS_Default := '-D_LARGEFILE_SOURCE' \
-       '-D_FILE_OFFSET_BITS=64' \
-       '-D_GNU_SOURCE' \
-       '-DEIO_STACKSIZE=262144'
-
-# Flags passed to all source files.
-CFLAGS_Default := -fasm-blocks \
-       -mpascal-strings \
-       -Os \
-       -gdwarf-2 \
-       -arch i386
-
-# Flags passed to only C files.
-CFLAGS_C_Default := 
-
-# Flags passed to only C++ files.
-CFLAGS_CC_Default := 
-
-# Flags passed to only ObjC files.
-CFLAGS_OBJC_Default := 
-
-# Flags passed to only ObjC++ files.
-CFLAGS_OBJCC_Default := 
-
-INCS_Default := -I$(srcdir)/src/libuv/include
-
-OBJS := $(obj).target/$(TARGET)/src/libuv/test/blackhole-server.o \
-       $(obj).target/$(TARGET)/src/libuv/test/echo-server.o \
-       $(obj).target/$(TARGET)/src/libuv/test/run-tests.o \
-       $(obj).target/$(TARGET)/src/libuv/test/runner.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-get-loadavg.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-async.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-error.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-callback-stack.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-connection-fail.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-delayed-accept.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-fail-always.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-fs.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-fs-event.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-get-currentexe.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-get-memory.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-getaddrinfo.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-gethostbyname.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-getsockname.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-hrtime.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-idle.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-ipc.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-loop-handles.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-multiple-listen.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-pass-always.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-ping-pong.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-pipe-bind-error.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-pipe-connect-error.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-ref.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-shutdown-eof.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-spawn.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-stdio-over-pipes.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-tcp-bind-error.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-tcp-bind6-error.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-tcp-close.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-tcp-flags.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-tcp-connect-error.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-tcp-connect6-error.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-tcp-write-error.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-tcp-write-to-half-open-connection.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-tcp-writealot.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-threadpool.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-timer-again.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-timer.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-tty.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-udp-dgram-too-big.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-udp-ipv6.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-udp-send-and-recv.o \
-       $(obj).target/$(TARGET)/src/libuv/test/test-udp-multicast-join.o \
-       $(obj).target/$(TARGET)/src/libuv/test/runner-unix.o
-
-# Add to the list of files we specially track dependencies for.
-all_deps += $(OBJS)
-
-# Make sure our dependencies are built before any of us.
-$(OBJS): | $(builddir)/libuv.a
-
-# CFLAGS et al overrides must be target-local.
-# See "Target-specific Variable Values" in the GNU Make manual.
-$(OBJS): TOOLSET := $(TOOLSET)
-$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
-$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
-$(OBJS): GYP_OBJCFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE)) $(CFLAGS_OBJC_$(BUILDTYPE))
-$(OBJS): GYP_OBJCXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE)) $(CFLAGS_OBJCC_$(BUILDTYPE))
-
-# Suffix rules, putting all outputs into $(obj).
-
-$(obj).$(TOOLSET)/$(TARGET)/%.o: $(srcdir)/%.c FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-
-# Try building from generated source, too.
-
-$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj).$(TOOLSET)/%.c FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-
-$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.c FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-
-# End of this set of suffix rules
-### Rules for final target.
-LDFLAGS_Default := -arch i386 \
-       -L$(builddir)
-
-LIBS := -framework Carbon \
-       -framework CoreServices
-
-$(builddir)/run-tests: GYP_LDFLAGS := $(LDFLAGS_$(BUILDTYPE))
-$(builddir)/run-tests: LIBS := $(LIBS)
-$(builddir)/run-tests: LD_INPUTS := $(OBJS) $(builddir)/libuv.a
-$(builddir)/run-tests: TOOLSET := $(TOOLSET)
-$(builddir)/run-tests: $(OBJS) $(builddir)/libuv.a FORCE_DO_CMD
-       $(call do_cmd,link)
-
-all_deps += $(builddir)/run-tests
-# Add target alias
-.PHONY: run-tests
-run-tests: $(builddir)/run-tests
-
-# Add executable to "all" target.
-.PHONY: all
-all: $(builddir)/run-tests
-
index 8761d16342accf5c0c1b1f582abb23cefaaa40ef..385a64c9f538b732f45b8efa955c9272875f80e1 100644 (file)
@@ -2,34 +2,87 @@
 
 TOOLSET := target
 TARGET := uv
-DEFS_Default := '-D_LARGEFILE_SOURCE' \
+DEFS_Debug := '-D_LARGEFILE_SOURCE' \
        '-D_FILE_OFFSET_BITS=64' \
        '-D_GNU_SOURCE' \
        '-DEIO_STACKSIZE=262144' \
        '-DHAVE_CONFIG_H' \
        '-DEV_CONFIG_H="config_darwin.h"' \
-       '-DEIO_CONFIG_H="config_darwin.h"'
+       '-DEIO_CONFIG_H="config_darwin.h"' \
+       '-DDEBUG' \
+       '-D_DEBUG' \
+       '-DEV_VERIFY=2'
 
 # Flags passed to all source files.
-CFLAGS_Default := -fasm-blocks \
-       -mpascal-strings \
-       -Os \
+CFLAGS_Debug := -Os \
        -gdwarf-2 \
-       -arch x86_64
+       -fvisibility=hidden \
+       -Wnewline-eof \
+       -arch x86_64 \
+       -fno-strict-aliasing \
+       -Wall \
+       -Wendif-labels \
+       -W \
+       -Wno-unused-parameter
 
 # Flags passed to only C files.
-CFLAGS_C_Default := 
+CFLAGS_C_Debug := 
 
 # Flags passed to only C++ files.
-CFLAGS_CC_Default := 
+CFLAGS_CC_Debug := -fno-rtti \
+       -fno-exceptions \
+       -fvisibility-inlines-hidden \
+       -fno-threadsafe-statics
 
 # Flags passed to only ObjC files.
-CFLAGS_OBJC_Default := 
+CFLAGS_OBJC_Debug := 
 
 # Flags passed to only ObjC++ files.
-CFLAGS_OBJCC_Default := 
+CFLAGS_OBJCC_Debug := 
 
-INCS_Default := -I$(srcdir)/src/libuv/include \
+INCS_Debug := -I$(srcdir)/src/libuv/include \
+       -I$(srcdir)/src/libuv/include/uv-private \
+       -I$(srcdir)/src/libuv/src \
+       -I$(srcdir)/src/libuv/src/unix/ev \
+       -I$(srcdir)/src/libuv/src/ares/config_darwin
+
+DEFS_Release := '-D_LARGEFILE_SOURCE' \
+       '-D_FILE_OFFSET_BITS=64' \
+       '-D_GNU_SOURCE' \
+       '-DEIO_STACKSIZE=262144' \
+       '-DHAVE_CONFIG_H' \
+       '-DEV_CONFIG_H="config_darwin.h"' \
+       '-DEIO_CONFIG_H="config_darwin.h"' \
+       '-DNDEBUG'
+
+# Flags passed to all source files.
+CFLAGS_Release := -Os \
+       -gdwarf-2 \
+       -fvisibility=hidden \
+       -Wnewline-eof \
+       -arch x86_64 \
+       -fno-strict-aliasing \
+       -Wall \
+       -Wendif-labels \
+       -W \
+       -Wno-unused-parameter
+
+# Flags passed to only C files.
+CFLAGS_C_Release := 
+
+# Flags passed to only C++ files.
+CFLAGS_CC_Release := -fno-rtti \
+       -fno-exceptions \
+       -fvisibility-inlines-hidden \
+       -fno-threadsafe-statics
+
+# Flags passed to only ObjC files.
+CFLAGS_OBJC_Release := 
+
+# Flags passed to only ObjC++ files.
+CFLAGS_OBJCC_Release := 
+
+INCS_Release := -I$(srcdir)/src/libuv/include \
        -I$(srcdir)/src/libuv/include/uv-private \
        -I$(srcdir)/src/libuv/src \
        -I$(srcdir)/src/libuv/src/unix/ev \
@@ -91,6 +144,7 @@ OBJS := $(obj).target/$(TARGET)/src/libuv/src/uv-common.o \
        $(obj).target/$(TARGET)/src/libuv/src/unix/cares.o \
        $(obj).target/$(TARGET)/src/libuv/src/unix/dl.o \
        $(obj).target/$(TARGET)/src/libuv/src/unix/error.o \
+       $(obj).target/$(TARGET)/src/libuv/src/unix/thread.o \
        $(obj).target/$(TARGET)/src/libuv/src/unix/process.o \
        $(obj).target/$(TARGET)/src/libuv/src/unix/eio/eio.o \
        $(obj).target/$(TARGET)/src/libuv/src/unix/ev/ev.o \
@@ -103,10 +157,10 @@ all_deps += $(OBJS)
 # CFLAGS et al overrides must be target-local.
 # See "Target-specific Variable Values" in the GNU Make manual.
 $(OBJS): TOOLSET := $(TOOLSET)
-$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
-$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
-$(OBJS): GYP_OBJCFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE)) $(CFLAGS_OBJC_$(BUILDTYPE))
-$(OBJS): GYP_OBJCXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE)) $(CFLAGS_OBJCC_$(BUILDTYPE))
+$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
+$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
+$(OBJS): GYP_OBJCFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE)) $(CFLAGS_OBJC_$(BUILDTYPE))
+$(OBJS): GYP_OBJCXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE)) $(CFLAGS_OBJCC_$(BUILDTYPE))
 
 # Suffix rules, putting all outputs into $(obj).
 
@@ -123,7 +177,10 @@ $(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.c FORCE_DO_CMD
 
 # End of this set of suffix rules
 ### Rules for final target.
-LDFLAGS_Default := -arch x86_64 \
+LDFLAGS_Debug := -arch x86_64 \
+       -L$(builddir)
+
+LDFLAGS_Release := -arch x86_64 \
        -L$(builddir)
 
 LIBS := -lm
diff --git a/mk/libuv/x86_64/mac/src/libuv/uv.target.mk-e b/mk/libuv/x86_64/mac/src/libuv/uv.target.mk-e
deleted file mode 100644 (file)
index 28f911f..0000000
+++ /dev/null
@@ -1,145 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-TOOLSET := target
-TARGET := uv
-DEFS_Default := '-D_LARGEFILE_SOURCE' \
-       '-D_FILE_OFFSET_BITS=64' \
-       '-D_GNU_SOURCE' \
-       '-DEIO_STACKSIZE=262144' \
-       '-DHAVE_CONFIG_H' \
-       '-DEV_CONFIG_H="config_darwin.h"' \
-       '-DEIO_CONFIG_H="config_darwin.h"'
-
-# Flags passed to all source files.
-CFLAGS_Default := -fasm-blocks \
-       -mpascal-strings \
-       -Os \
-       -gdwarf-2 \
-       -arch i386
-
-# Flags passed to only C files.
-CFLAGS_C_Default := 
-
-# Flags passed to only C++ files.
-CFLAGS_CC_Default := 
-
-# Flags passed to only ObjC files.
-CFLAGS_OBJC_Default := 
-
-# Flags passed to only ObjC++ files.
-CFLAGS_OBJCC_Default := 
-
-INCS_Default := -I$(srcdir)/src/libuv/include \
-       -I$(srcdir)/src/libuv/include/uv-private \
-       -I$(srcdir)/src/libuv/src \
-       -I$(srcdir)/src/libuv/src/unix/ev \
-       -I$(srcdir)/src/libuv/src/ares/config_darwin
-
-OBJS := $(obj).target/$(TARGET)/src/libuv/src/uv-common.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_cancel.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares__close_sockets.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_data.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_destroy.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_expand_name.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_expand_string.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_fds.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_free_hostent.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_free_string.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_gethostbyaddr.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_gethostbyname.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares__get_hostent.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_getnameinfo.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_getopt.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_getsock.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_init.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_library_init.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_llist.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_mkquery.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_nowarn.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_options.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_parse_aaaa_reply.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_parse_a_reply.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_parse_mx_reply.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_parse_ns_reply.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_parse_ptr_reply.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_parse_srv_reply.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_parse_txt_reply.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_process.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_query.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares__read_line.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_search.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_send.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_strcasecmp.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_strdup.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_strerror.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_timeout.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares__timeval.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_version.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/ares_writev.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/bitncmp.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/inet_net_pton.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/inet_ntop.o \
-       $(obj).target/$(TARGET)/src/libuv/src/ares/windows_port.o \
-       $(obj).target/$(TARGET)/src/libuv/src/unix/core.o \
-       $(obj).target/$(TARGET)/src/libuv/src/unix/uv-eio.o \
-       $(obj).target/$(TARGET)/src/libuv/src/unix/fs.o \
-       $(obj).target/$(TARGET)/src/libuv/src/unix/udp.o \
-       $(obj).target/$(TARGET)/src/libuv/src/unix/tcp.o \
-       $(obj).target/$(TARGET)/src/libuv/src/unix/pipe.o \
-       $(obj).target/$(TARGET)/src/libuv/src/unix/tty.o \
-       $(obj).target/$(TARGET)/src/libuv/src/unix/stream.o \
-       $(obj).target/$(TARGET)/src/libuv/src/unix/cares.o \
-       $(obj).target/$(TARGET)/src/libuv/src/unix/dl.o \
-       $(obj).target/$(TARGET)/src/libuv/src/unix/error.o \
-       $(obj).target/$(TARGET)/src/libuv/src/unix/process.o \
-       $(obj).target/$(TARGET)/src/libuv/src/unix/eio/eio.o \
-       $(obj).target/$(TARGET)/src/libuv/src/unix/ev/ev.o \
-       $(obj).target/$(TARGET)/src/libuv/src/unix/darwin.o \
-       $(obj).target/$(TARGET)/src/libuv/src/unix/kqueue.o
-
-# Add to the list of files we specially track dependencies for.
-all_deps += $(OBJS)
-
-# CFLAGS et al overrides must be target-local.
-# See "Target-specific Variable Values" in the GNU Make manual.
-$(OBJS): TOOLSET := $(TOOLSET)
-$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
-$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
-$(OBJS): GYP_OBJCFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE)) $(CFLAGS_OBJC_$(BUILDTYPE))
-$(OBJS): GYP_OBJCXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE)) $(CFLAGS_OBJCC_$(BUILDTYPE))
-
-# Suffix rules, putting all outputs into $(obj).
-
-$(obj).$(TOOLSET)/$(TARGET)/%.o: $(srcdir)/%.c FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-
-# Try building from generated source, too.
-
-$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj).$(TOOLSET)/%.c FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-
-$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.c FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-
-# End of this set of suffix rules
-### Rules for final target.
-LDFLAGS_Default := -arch i386 \
-       -L$(builddir)
-
-LIBS := -lm
-
-$(builddir)/libuv.a: GYP_LDFLAGS := $(LDFLAGS_$(BUILDTYPE))
-$(builddir)/libuv.a: LIBS := $(LIBS)
-$(builddir)/libuv.a: TOOLSET := $(TOOLSET)
-$(builddir)/libuv.a: $(OBJS) FORCE_DO_CMD
-       $(call do_cmd,alink)
-
-all_deps += $(builddir)/libuv.a
-# Add target alias
-.PHONY: uv
-uv: $(builddir)/libuv.a
-
-# Add target alias to "all" target.
-.PHONY: all
-all: uv
-
index e7b86e6cfc6673f0497afefcedb0b9c9c8d1652f..d71b06661c8da6be1b12e3b55c6e4f5bc6cb5c56 100644 (file)
@@ -8,6 +8,7 @@ MAKEFLAGS=-r
 
 # The source directory tree.
 srcdir := ../../../..
+abs_srcdir := $(abspath $(srcdir))
 
 # The name of the builddir.
 builddir_name ?= out
@@ -20,7 +21,7 @@ else
 endif
 
 # Specify BUILDTYPE=Release on the command line for a release build.
-BUILDTYPE ?= Default
+BUILDTYPE ?= Debug
 
 # Directory all our build output goes into.
 # Note that this must be two directories beneath src/ for unit tests to pass,
@@ -252,8 +253,8 @@ $(if $(or $(command_changed),$(prereq_changed)),
 )
 endef
 
-# Declare "all" target first so it is the default, even though we don't have the
-# deps yet.
+# Declare the "all" target first so it is the default,
+# even though we don't have the deps yet.
 .PHONY: all
 all:
 
@@ -321,9 +322,9 @@ ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
   include src/libuv/uv.target.mk
 endif
 
-quiet_cmd_regen_makefile = ACTION Regenerating $@
-cmd_regen_makefile = ./src/libuv/build/gyp/gyp -fmake --ignore-environment "--toplevel-dir=." "--depth=." "--generator-output=mk/libuv/x86_64/unix" "-Dlibrary=static_library" "-Dtarget_arch=x86_64" "-DOS=linux" src/libuv/uv.gyp
-Makefile: $(srcdir)/src/libuv/uv.gyp
+#quiet_cmd_regen_makefile = ACTION Regenerating $@
+#cmd_regen_makefile = ./src/libuv/build/gyp/gyp -fmake --ignore-environment "--toplevel-dir=." -Isrc/libuv/common.gypi "--depth=." "--generator-output=mk/libuv/x86_64/unix" "-Ddefault_configuration=Default" "-Dcomponent=static_library" "-Dlibrary=static_library" "-Dtarget_arch=x86_64" "-DOS=linux" src/libuv/uv.gyp
+#Makefile: $(srcdir)/src/libuv/uv.gyp $(srcdir)/src/libuv/common.gypi
 #      $(call do_cmd,regen_makefile)
 
 # "all" is a concatenation of the "all" targets from all the included
diff --git a/mk/libuv/x86_64/unix/Makefile-e b/mk/libuv/x86_64/unix/Makefile-e
deleted file mode 100644 (file)
index 8197dff..0000000
+++ /dev/null
@@ -1,353 +0,0 @@
-# We borrow heavily from the kernel build setup, though we are simpler since
-# we don't have Kconfig tweaking settings on us.
-
-# The implicit make rules have it looking for RCS files, among other things.
-# We instead explicitly write all the rules we care about.
-# It's even quicker (saves ~200ms) to pass -r on the command line.
-MAKEFLAGS=-r
-
-# The source directory tree.
-srcdir := ../../../..
-
-# The name of the builddir.
-builddir_name ?= out
-
-# The V=1 flag on command line makes us verbosely print command lines.
-ifdef V
-  quiet=
-else
-  quiet=quiet_
-endif
-
-# Specify BUILDTYPE=Release on the command line for a release build.
-BUILDTYPE ?= Default
-
-# Directory all our build output goes into.
-# Note that this must be two directories beneath src/ for unit tests to pass,
-# as they reach into the src/ directory for data with relative paths.
-builddir ?= $(builddir_name)/$(BUILDTYPE)
-abs_builddir := $(abspath $(builddir))
-depsdir := $(builddir)/.deps
-
-# Object output directory.
-obj := $(builddir)/obj
-abs_obj := $(abspath $(obj))
-
-# We build up a list of every single one of the targets so we can slurp in the
-# generated dependency rule Makefiles in one pass.
-all_deps :=
-
-
-
-# C++ apps need to be linked with g++.
-#
-# Note: flock is used to seralize linking. Linking is a memory-intensive
-# process so running parallel links can often lead to thrashing.  To disable
-# the serialization, override LINK via an envrionment variable as follows:
-#
-#   export LINK=g++
-#
-# This will allow make to invoke N linker processes as specified in -jN.
-LINK ?= flock $(builddir)/linker.lock $(CXX)
-
-CC.target ?= $(CC)
-CFLAGS.target ?= $(CFLAGS)
-CXX.target ?= $(CXX)
-CXXFLAGS.target ?= $(CXXFLAGS)
-LINK.target ?= $(LINK)
-LDFLAGS.target ?= $(LDFLAGS) 
-AR.target ?= $(AR)
-ARFLAGS.target ?= crsT
-
-# N.B.: the logic of which commands to run should match the computation done
-# in gyp's make.py where ARFLAGS.host etc. is computed.
-# TODO(evan): move all cross-compilation logic to gyp-time so we don't need
-# to replicate this environment fallback in make as well.
-CC.host ?= gcc
-CFLAGS.host ?=
-CXX.host ?= g++
-CXXFLAGS.host ?=
-LINK.host ?= g++
-LDFLAGS.host ?=
-AR.host ?= ar
-ARFLAGS.host := crsT
-
-# Define a dir function that can handle spaces.
-# http://www.gnu.org/software/make/manual/make.html#Syntax-of-Functions
-# "leading spaces cannot appear in the text of the first argument as written.
-# These characters can be put into the argument value by variable substitution."
-empty :=
-space := $(empty) $(empty)
-
-# http://stackoverflow.com/questions/1189781/using-make-dir-or-notdir-on-a-path-with-spaces
-replace_spaces = $(subst $(space),?,$1)
-unreplace_spaces = $(subst ?,$(space),$1)
-dirx = $(call unreplace_spaces,$(dir $(call replace_spaces,$1)))
-
-# Flags to make gcc output dependency info.  Note that you need to be
-# careful here to use the flags that ccache and distcc can understand.
-# We write to a dep file on the side first and then rename at the end
-# so we can't end up with a broken dep file.
-depfile = $(depsdir)/$(call replace_spaces,$@).d
-DEPFLAGS = -MMD -MF $(depfile).raw
-
-# We have to fixup the deps output in a few ways.
-# (1) the file output should mention the proper .o file.
-# ccache or distcc lose the path to the target, so we convert a rule of
-# the form:
-#   foobar.o: DEP1 DEP2
-# into
-#   path/to/foobar.o: DEP1 DEP2
-# (2) we want missing files not to cause us to fail to build.
-# We want to rewrite
-#   foobar.o: DEP1 DEP2 \
-#               DEP3
-# to
-#   DEP1:
-#   DEP2:
-#   DEP3:
-# so if the files are missing, they're just considered phony rules.
-# We have to do some pretty insane escaping to get those backslashes
-# and dollar signs past make, the shell, and sed at the same time.
-# Doesn't work with spaces, but that's fine: .d files have spaces in
-# their names replaced with other characters.
-define fixup_dep
-# The depfile may not exist if the input file didn't have any #includes.
-touch $(depfile).raw
-# Fixup path as in (1).
-sed -e "s|^$(notdir $@)|$@|" $(depfile).raw >> $(depfile)
-# Add extra rules as in (2).
-# We remove slashes and replace spaces with new lines;
-# remove blank lines;
-# delete the first line and append a colon to the remaining lines.
-sed -e 's|\\||' -e 'y| |\n|' $(depfile).raw |\
-  grep -v '^$$'                             |\
-  sed -e 1d -e 's|$$|:|'                     \
-    >> $(depfile)
-rm $(depfile).raw
-endef
-
-# Command definitions:
-# - cmd_foo is the actual command to run;
-# - quiet_cmd_foo is the brief-output summary of the command.
-
-quiet_cmd_cc = CC($(TOOLSET)) $@
-cmd_cc = $(CC.$(TOOLSET)) $(GYP_CFLAGS) $(DEPFLAGS) $(CFLAGS.$(TOOLSET)) -c -o $@ $<
-
-quiet_cmd_cxx = CXX($(TOOLSET)) $@
-cmd_cxx = $(CXX.$(TOOLSET)) $(GYP_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $<
-
-quiet_cmd_touch = TOUCH $@
-cmd_touch = touch $@
-
-quiet_cmd_copy = COPY $@
-# send stderr to /dev/null to ignore messages when linking directories.
-cmd_copy = ln -f "$<" "$@" 2>/dev/null || (rm -rf "$@" && cp -af "$<" "$@")
-
-quiet_cmd_alink = AR($(TOOLSET)) $@
-cmd_alink = rm -f $@ && $(AR.$(TOOLSET)) $(ARFLAGS.$(TOOLSET)) $@ $(filter %.o,$^)
-
-# Due to circular dependencies between libraries :(, we wrap the
-# special "figure out circular dependencies" flags around the entire
-# input list during linking.
-quiet_cmd_link = LINK($(TOOLSET)) $@
-cmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ -Wl,--start-group $(LD_INPUTS) -Wl,--end-group $(LIBS)
-
-# We support two kinds of shared objects (.so):
-# 1) shared_library, which is just bundling together many dependent libraries
-# into a link line.
-# 2) loadable_module, which is generating a module intended for dlopen().
-#
-# They differ only slightly:
-# In the former case, we want to package all dependent code into the .so.
-# In the latter case, we want to package just the API exposed by the
-# outermost module.
-# This means shared_library uses --whole-archive, while loadable_module doesn't.
-# (Note that --whole-archive is incompatible with the --start-group used in
-# normal linking.)
-
-# Other shared-object link notes:
-# - Set SONAME to the library filename so our binaries don't reference
-# the local, absolute paths used on the link command-line.
-quiet_cmd_solink = SOLINK($(TOOLSET)) $@
-cmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--whole-archive $(LD_INPUTS) -Wl,--no-whole-archive $(LIBS)
-
-quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@
-cmd_solink_module = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--start-group $(filter-out FORCE_DO_CMD, $^) -Wl,--end-group $(LIBS)
-
-
-# Define an escape_quotes function to escape single quotes.
-# This allows us to handle quotes properly as long as we always use
-# use single quotes and escape_quotes.
-escape_quotes = $(subst ','\'',$(1))
-# This comment is here just to include a ' to unconfuse syntax highlighting.
-# Define an escape_vars function to escape '$' variable syntax.
-# This allows us to read/write command lines with shell variables (e.g.
-# $LD_LIBRARY_PATH), without triggering make substitution.
-escape_vars = $(subst $$,$$$$,$(1))
-# Helper that expands to a shell command to echo a string exactly as it is in
-# make. This uses printf instead of echo because printf's behaviour with respect
-# to escape sequences is more portable than echo's across different shells
-# (e.g., dash, bash).
-exact_echo = printf '%s\n' '$(call escape_quotes,$(1))'
-
-# Helper to compare the command we're about to run against the command
-# we logged the last time we ran the command.  Produces an empty
-# string (false) when the commands match.
-# Tricky point: Make has no string-equality test function.
-# The kernel uses the following, but it seems like it would have false
-# positives, where one string reordered its arguments.
-#   arg_check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \
-#                       $(filter-out $(cmd_$@), $(cmd_$(1))))
-# We instead substitute each for the empty string into the other, and
-# say they're equal if both substitutions produce the empty string.
-# .d files contain ? instead of spaces, take that into account.
-command_changed = $(or $(subst $(cmd_$(1)),,$(cmd_$(call replace_spaces,$@))),\
-                       $(subst $(cmd_$(call replace_spaces,$@)),,$(cmd_$(1))))
-
-# Helper that is non-empty when a prerequisite changes.
-# Normally make does this implicitly, but we force rules to always run
-# so we can check their command lines.
-#   $? -- new prerequisites
-#   $| -- order-only dependencies
-prereq_changed = $(filter-out FORCE_DO_CMD,$(filter-out $|,$?))
-
-# Helper that executes all postbuilds, and deletes the output file when done
-# if any of the postbuilds failed.
-define do_postbuilds
-  @E=0;\
-  for p in $(POSTBUILDS); do\
-    eval $$p;\
-    F=$$?;\
-    if [ $$F -ne 0 ]; then\
-      E=$$F;\
-    fi;\
-  done;\
-  if [ $$E -ne 0 ]; then\
-    rm -rf "$@";\
-    exit $$E;\
-  fi
-endef
-
-# do_cmd: run a command via the above cmd_foo names, if necessary.
-# Should always run for a given target to handle command-line changes.
-# Second argument, if non-zero, makes it do asm/C/C++ dependency munging.
-# Third argument, if non-zero, makes it do POSTBUILDS processing.
-# Note: We intentionally do NOT call dirx for depfile, since it contains ? for
-# spaces already and dirx strips the ? characters.
-define do_cmd
-$(if $(or $(command_changed),$(prereq_changed)),
-  @$(call exact_echo,  $($(quiet)cmd_$(1)))
-  @mkdir -p "$(call dirx,$@)" "$(dir $(depfile))"
-  $(if $(findstring flock,$(word 1,$(cmd_$1))),
-    @$(cmd_$(1))
-    @echo "  $(quiet_cmd_$(1)): Finished",
-    @$(cmd_$(1))
-  )
-  @$(call exact_echo,$(call escape_vars,cmd_$(call replace_spaces,$@) := $(cmd_$(1)))) > $(depfile)
-  @$(if $(2),$(fixup_dep))
-  $(if $(and $(3), $(POSTBUILDS)),
-    $(call do_postbuilds)
-  )
-)
-endef
-
-# Declare "all" target first so it is the default, even though we don't have the
-# deps yet.
-.PHONY: all
-all:
-
-# Use FORCE_DO_CMD to force a target to run.  Should be coupled with
-# do_cmd.
-.PHONY: FORCE_DO_CMD
-FORCE_DO_CMD:
-
-TOOLSET := target
-# Suffix rules, putting all outputs into $(obj).
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.c FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cc FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cpp FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cxx FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.S FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.s FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-
-# Try building from generated source, too.
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.c FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cc FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cpp FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cxx FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.S FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.s FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-
-$(obj).$(TOOLSET)/%.o: $(obj)/%.c FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.cc FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.cpp FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.cxx FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.S FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.s FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-
-
-ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
-    $(findstring $(join ^,$(prefix)),\
-                 $(join ^,src/libuv/run-benchmarks.target.mk)))),)
-  include src/libuv/run-benchmarks.target.mk
-endif
-ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
-    $(findstring $(join ^,$(prefix)),\
-                 $(join ^,src/libuv/run-tests.target.mk)))),)
-  include src/libuv/run-tests.target.mk
-endif
-ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
-    $(findstring $(join ^,$(prefix)),\
-                 $(join ^,src/libuv/uv.target.mk)))),)
-  include src/libuv/uv.target.mk
-endif
-
-quiet_cmd_regen_makefile = ACTION Regenerating $@
-cmd_regen_makefile = ./src/libuv/build/gyp/gyp -fmake --ignore-environment "--toplevel-dir=." "--depth=." "--generator-output=mk/libuv/x86_64/unix" "-Dlibrary=static_library" "-Dtarget_arch=x86_64" "-DOS=linux" src/libuv/uv.gyp
-Makefile: $(srcdir)/src/libuv/uv.gyp
-       $(call do_cmd,regen_makefile)
-
-# "all" is a concatenation of the "all" targets from all the included
-# sub-makefiles. This is just here to clarify.
-all:
-
-# Add in dependency-tracking rules.  $(all_deps) is the list of every single
-# target in our tree. Only consider the ones with .d (dependency) info:
-d_files := $(wildcard $(foreach f,$(all_deps),$(depsdir)/$(f).d))
-ifneq ($(d_files),)
-  # Rather than include each individual .d file, concatenate them into a
-  # single file which make is able to load faster.  We split this into
-  # commands that take 1000 files at a time to avoid overflowing the
-  # command line.
-  $(shell cat $(wordlist 1,1000,$(d_files)) > $(depsdir)/all.deps)
-
-  ifneq ($(word 1001,$(d_files)),)
-    $(error Found unprocessed dependency files (gyp didn't generate enough rules!))
-  endif
-
-  # make looks for ways to re-generate included makefiles, but in our case, we
-  # don't have a direct way. Explicitly telling make that it has nothing to do
-  # for them makes it go faster.
-  $(depsdir)/all.deps: ;
-
-  include $(depsdir)/all.deps
-endif
index b5680d2c557c7ffc7ea924bb22fc0ea05d30fba4..25b01014e79d4d77388813a41830e8d1ad32d84a 100644 (file)
@@ -2,21 +2,57 @@
 
 TOOLSET := target
 TARGET := run-benchmarks
-DEFS_Default := '-D_LARGEFILE_SOURCE' \
+DEFS_Debug := '-D_LARGEFILE_SOURCE' \
        '-D_FILE_OFFSET_BITS=64' \
        '-D_GNU_SOURCE' \
-       '-DEIO_STACKSIZE=262144'
+       '-DEIO_STACKSIZE=262144' \
+       '-DDEBUG' \
+       '-D_DEBUG' \
+       '-DEV_VERIFY=2'
 
 # Flags passed to all source files.
-CFLAGS_Default := -pthread
+CFLAGS_Debug := -pthread \
+       -Wall \
+       -ansi \
+       -pthread \
+       -fvisibility=hidden \
+       -g \
+       -O0
 
 # Flags passed to only C files.
-CFLAGS_C_Default := 
+CFLAGS_C_Debug := 
 
 # Flags passed to only C++ files.
-CFLAGS_CC_Default := 
+CFLAGS_CC_Debug := -fno-rtti \
+       -fno-exceptions
 
-INCS_Default := -I$(srcdir)/src/libuv/include
+INCS_Debug := -I$(srcdir)/src/libuv/include
+
+DEFS_Release := '-D_LARGEFILE_SOURCE' \
+       '-D_FILE_OFFSET_BITS=64' \
+       '-D_GNU_SOURCE' \
+       '-DEIO_STACKSIZE=262144' \
+       '-DNDEBUG'
+
+# Flags passed to all source files.
+CFLAGS_Release := -pthread \
+       -Wall \
+       -ansi \
+       -pthread \
+       -fvisibility=hidden \
+       -O3 \
+       -fomit-frame-pointer \
+       -fdata-sections \
+       -ffunction-sections
+
+# Flags passed to only C files.
+CFLAGS_C_Release := 
+
+# Flags passed to only C++ files.
+CFLAGS_CC_Release := -fno-rtti \
+       -fno-exceptions
+
+INCS_Release := -I$(srcdir)/src/libuv/include
 
 OBJS := $(obj).target/$(TARGET)/src/libuv/test/benchmark-ares.o \
        $(obj).target/$(TARGET)/src/libuv/test/benchmark-getaddrinfo.o \
@@ -25,6 +61,7 @@ OBJS := $(obj).target/$(TARGET)/src/libuv/test/benchmark-ares.o \
        $(obj).target/$(TARGET)/src/libuv/test/benchmark-pump.o \
        $(obj).target/$(TARGET)/src/libuv/test/benchmark-sizes.o \
        $(obj).target/$(TARGET)/src/libuv/test/benchmark-spawn.o \
+       $(obj).target/$(TARGET)/src/libuv/test/benchmark-thread.o \
        $(obj).target/$(TARGET)/src/libuv/test/benchmark-tcp-write-batch.o \
        $(obj).target/$(TARGET)/src/libuv/test/benchmark-udp-packet-storm.o \
        $(obj).target/$(TARGET)/src/libuv/test/dns-server.o \
@@ -43,8 +80,8 @@ $(OBJS): | $(obj).target/src/libuv/libuv.a
 # CFLAGS et al overrides must be target-local.
 # See "Target-specific Variable Values" in the GNU Make manual.
 $(OBJS): TOOLSET := $(TOOLSET)
-$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
-$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
+$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
+$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
 
 # Suffix rules, putting all outputs into $(obj).
 
@@ -61,7 +98,9 @@ $(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.c FORCE_DO_CMD
 
 # End of this set of suffix rules
 ### Rules for final target.
-LDFLAGS_Default := 
+LDFLAGS_Debug := -pthread
+
+LDFLAGS_Release := -pthread
 
 LIBS := -lrt
 
index 34bc8551b44da5d28326438c2f3e677563f6e3a0..a2fe0d2065e230c637dd3c17a8cb946dfad41850 100644 (file)
@@ -2,32 +2,71 @@
 
 TOOLSET := target
 TARGET := run-tests
-DEFS_Default := '-D_LARGEFILE_SOURCE' \
+DEFS_Debug := '-D_LARGEFILE_SOURCE' \
        '-D_FILE_OFFSET_BITS=64' \
        '-D_GNU_SOURCE' \
-       '-DEIO_STACKSIZE=262144'
+       '-DEIO_STACKSIZE=262144' \
+       '-DDEBUG' \
+       '-D_DEBUG' \
+       '-DEV_VERIFY=2'
 
 # Flags passed to all source files.
-CFLAGS_Default := -pthread
+CFLAGS_Debug := -pthread \
+       -Wall \
+       -ansi \
+       -pthread \
+       -fvisibility=hidden \
+       -g \
+       -O0
 
 # Flags passed to only C files.
-CFLAGS_C_Default := 
+CFLAGS_C_Debug := 
 
 # Flags passed to only C++ files.
-CFLAGS_CC_Default := 
+CFLAGS_CC_Debug := -fno-rtti \
+       -fno-exceptions
 
-INCS_Default := -I$(srcdir)/src/libuv/include
+INCS_Debug := -I$(srcdir)/src/libuv/include
+
+DEFS_Release := '-D_LARGEFILE_SOURCE' \
+       '-D_FILE_OFFSET_BITS=64' \
+       '-D_GNU_SOURCE' \
+       '-DEIO_STACKSIZE=262144' \
+       '-DNDEBUG'
+
+# Flags passed to all source files.
+CFLAGS_Release := -pthread \
+       -Wall \
+       -ansi \
+       -pthread \
+       -fvisibility=hidden \
+       -O3 \
+       -fomit-frame-pointer \
+       -fdata-sections \
+       -ffunction-sections
+
+# Flags passed to only C files.
+CFLAGS_C_Release := 
+
+# Flags passed to only C++ files.
+CFLAGS_CC_Release := -fno-rtti \
+       -fno-exceptions
+
+INCS_Release := -I$(srcdir)/src/libuv/include
 
 OBJS := $(obj).target/$(TARGET)/src/libuv/test/blackhole-server.o \
        $(obj).target/$(TARGET)/src/libuv/test/echo-server.o \
        $(obj).target/$(TARGET)/src/libuv/test/run-tests.o \
        $(obj).target/$(TARGET)/src/libuv/test/runner.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-get-loadavg.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-util.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-async.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-error.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-callback-stack.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-connection-fail.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-cwd-and-chdir.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-delayed-accept.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-eio-overflow.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-fail-always.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-fs.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-fs-event.o \
@@ -39,12 +78,15 @@ OBJS := $(obj).target/$(TARGET)/src/libuv/test/blackhole-server.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-hrtime.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-idle.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-ipc.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-ipc-threads.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-loop-handles.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-multiple-listen.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-pass-always.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-ping-pong.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-pipe-bind-error.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-pipe-connect-error.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-platform-output.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-process-title.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-ref.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-shutdown-eof.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-spawn.o \
@@ -59,13 +101,17 @@ OBJS := $(obj).target/$(TARGET)/src/libuv/test/blackhole-server.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-tcp-write-to-half-open-connection.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-tcp-writealot.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-threadpool.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-mutexes.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-thread.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-timer-again.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-timer.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-tty.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-udp-dgram-too-big.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-udp-ipv6.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-udp-options.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-udp-send-and-recv.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-udp-multicast-join.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-counters-init.o \
        $(obj).target/$(TARGET)/src/libuv/test/runner-unix.o
 
 # Add to the list of files we specially track dependencies for.
@@ -77,8 +123,8 @@ $(OBJS): | $(obj).target/src/libuv/libuv.a
 # CFLAGS et al overrides must be target-local.
 # See "Target-specific Variable Values" in the GNU Make manual.
 $(OBJS): TOOLSET := $(TOOLSET)
-$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
-$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
+$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
+$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
 
 # Suffix rules, putting all outputs into $(obj).
 
@@ -95,7 +141,9 @@ $(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.c FORCE_DO_CMD
 
 # End of this set of suffix rules
 ### Rules for final target.
-LDFLAGS_Default := 
+LDFLAGS_Debug := -pthread
+
+LDFLAGS_Release := -pthread
 
 LIBS := -lrt
 
index 65c2cf17b839d0747c4347fdce19b8fc3b5eb4c5..60e0e8fd2def64a48356d5b48390bab1906ae4a5 100644 (file)
@@ -2,30 +2,79 @@
 
 TOOLSET := target
 TARGET := uv
-DEFS_Default := '-D_LARGEFILE_SOURCE' \
+DEFS_Debug := '-D_LARGEFILE_SOURCE' \
        '-D_FILE_OFFSET_BITS=64' \
        '-D_GNU_SOURCE' \
        '-DEIO_STACKSIZE=262144' \
        '-DHAVE_CONFIG_H' \
        '-DEV_CONFIG_H="config_linux.h"' \
-       '-DEIO_CONFIG_H="config_linux.h"'
+       '-DEIO_CONFIG_H="config_linux.h"' \
+       '-DDEBUG' \
+       '-D_DEBUG' \
+       '-DEV_VERIFY=2'
 
 # Flags passed to all source files.
-CFLAGS_Default := -pthread \
+CFLAGS_Debug := -pthread \
+       -Wall \
+       -ansi \
+       -pthread \
+       -fvisibility=hidden \
+       -g \
+       --std=gnu89 \
+       -pedantic \
+       -Wall \
+       -Wextra \
+       -Wno-unused-parameter \
+       -g \
+       -O0
+
+# Flags passed to only C files.
+CFLAGS_C_Debug := 
+
+# Flags passed to only C++ files.
+CFLAGS_CC_Debug := -fno-rtti \
+       -fno-exceptions
+
+INCS_Debug := -I$(srcdir)/src/libuv/include \
+       -I$(srcdir)/src/libuv/include/uv-private \
+       -I$(srcdir)/src/libuv/src \
+       -I$(srcdir)/src/libuv/src/unix/ev \
+       -I$(srcdir)/src/libuv/src/ares/config_linux
+
+DEFS_Release := '-D_LARGEFILE_SOURCE' \
+       '-D_FILE_OFFSET_BITS=64' \
+       '-D_GNU_SOURCE' \
+       '-DEIO_STACKSIZE=262144' \
+       '-DHAVE_CONFIG_H' \
+       '-DEV_CONFIG_H="config_linux.h"' \
+       '-DEIO_CONFIG_H="config_linux.h"' \
+       '-DNDEBUG'
+
+# Flags passed to all source files.
+CFLAGS_Release := -pthread \
+       -Wall \
+       -ansi \
+       -pthread \
+       -fvisibility=hidden \
        -g \
        --std=gnu89 \
        -pedantic \
        -Wall \
        -Wextra \
-       -Wno-unused-parameter
+       -Wno-unused-parameter \
+       -O3 \
+       -fomit-frame-pointer \
+       -fdata-sections \
+       -ffunction-sections
 
 # Flags passed to only C files.
-CFLAGS_C_Default := 
+CFLAGS_C_Release := 
 
 # Flags passed to only C++ files.
-CFLAGS_CC_Default := 
+CFLAGS_CC_Release := -fno-rtti \
+       -fno-exceptions
 
-INCS_Default := -I$(srcdir)/src/libuv/include \
+INCS_Release := -I$(srcdir)/src/libuv/include \
        -I$(srcdir)/src/libuv/include/uv-private \
        -I$(srcdir)/src/libuv/src \
        -I$(srcdir)/src/libuv/src/unix/ev \
@@ -87,6 +136,7 @@ OBJS := $(obj).target/$(TARGET)/src/libuv/src/uv-common.o \
        $(obj).target/$(TARGET)/src/libuv/src/unix/cares.o \
        $(obj).target/$(TARGET)/src/libuv/src/unix/dl.o \
        $(obj).target/$(TARGET)/src/libuv/src/unix/error.o \
+       $(obj).target/$(TARGET)/src/libuv/src/unix/thread.o \
        $(obj).target/$(TARGET)/src/libuv/src/unix/process.o \
        $(obj).target/$(TARGET)/src/libuv/src/unix/eio/eio.o \
        $(obj).target/$(TARGET)/src/libuv/src/unix/ev/ev.o \
@@ -98,8 +148,8 @@ all_deps += $(OBJS)
 # CFLAGS et al overrides must be target-local.
 # See "Target-specific Variable Values" in the GNU Make manual.
 $(OBJS): TOOLSET := $(TOOLSET)
-$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
-$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
+$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
+$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
 
 # Suffix rules, putting all outputs into $(obj).
 
@@ -116,7 +166,9 @@ $(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.c FORCE_DO_CMD
 
 # End of this set of suffix rules
 ### Rules for final target.
-LDFLAGS_Default := 
+LDFLAGS_Debug := -pthread
+
+LDFLAGS_Release := -pthread
 
 LIBS := -lm
 
index 9597ce768ca358c12c3e2c102ed1e8e35dba7a5e..d40391e0f8988659a5558bd22cf560c4745dbf90 100644 (file)
@@ -8,6 +8,7 @@ MAKEFLAGS=-r
 
 # The source directory tree.
 srcdir := ../../../..
+abs_srcdir := $(abspath $(srcdir))
 
 # The name of the builddir.
 builddir_name ?= out
@@ -20,7 +21,7 @@ else
 endif
 
 # Specify BUILDTYPE=Release on the command line for a release build.
-BUILDTYPE ?= Default
+BUILDTYPE ?= Debug
 
 # Directory all our build output goes into.
 # Note that this must be two directories beneath src/ for unit tests to pass,
@@ -252,8 +253,8 @@ $(if $(or $(command_changed),$(prereq_changed)),
 )
 endef
 
-# Declare "all" target first so it is the default, even though we don't have the
-# deps yet.
+# Declare the "all" target first so it is the default,
+# even though we don't have the deps yet.
 .PHONY: all
 all:
 
@@ -321,9 +322,9 @@ ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
   include src/libuv/uv.target.mk
 endif
 
-quiet_cmd_regen_makefile = ACTION Regenerating $@
-cmd_regen_makefile = ./src/libuv/build/gyp/gyp -fmake --ignore-environment "--toplevel-dir=." "--depth=." "--generator-output=mk/libuv/x86_64/win" "-Dlibrary=static_library" "-Dtarget_arch=x86_64" "-DOS=win" src/libuv/uv.gyp
-Makefile: $(srcdir)/src/libuv/uv.gyp
+#quiet_cmd_regen_makefile = ACTION Regenerating $@
+#cmd_regen_makefile = ./src/libuv/build/gyp/gyp -fmake --ignore-environment "--toplevel-dir=." -Isrc/libuv/common.gypi "--depth=." "--generator-output=mk/libuv/x86_64/win" "-Ddefault_configuration=Default" "-Dcomponent=static_library" "-Dlibrary=static_library" "-Dtarget_arch=x86_64" "-DOS=win" src/libuv/uv.gyp
+#Makefile: $(srcdir)/src/libuv/uv.gyp $(srcdir)/src/libuv/common.gypi
 #      $(call do_cmd,regen_makefile)
 
 # "all" is a concatenation of the "all" targets from all the included
diff --git a/mk/libuv/x86_64/win/Makefile-e b/mk/libuv/x86_64/win/Makefile-e
deleted file mode 100644 (file)
index d7c2077..0000000
+++ /dev/null
@@ -1,353 +0,0 @@
-# We borrow heavily from the kernel build setup, though we are simpler since
-# we don't have Kconfig tweaking settings on us.
-
-# The implicit make rules have it looking for RCS files, among other things.
-# We instead explicitly write all the rules we care about.
-# It's even quicker (saves ~200ms) to pass -r on the command line.
-MAKEFLAGS=-r
-
-# The source directory tree.
-srcdir := ../../../..
-
-# The name of the builddir.
-builddir_name ?= out
-
-# The V=1 flag on command line makes us verbosely print command lines.
-ifdef V
-  quiet=
-else
-  quiet=quiet_
-endif
-
-# Specify BUILDTYPE=Release on the command line for a release build.
-BUILDTYPE ?= Default
-
-# Directory all our build output goes into.
-# Note that this must be two directories beneath src/ for unit tests to pass,
-# as they reach into the src/ directory for data with relative paths.
-builddir ?= $(builddir_name)/$(BUILDTYPE)
-abs_builddir := $(abspath $(builddir))
-depsdir := $(builddir)/.deps
-
-# Object output directory.
-obj := $(builddir)/obj
-abs_obj := $(abspath $(obj))
-
-# We build up a list of every single one of the targets so we can slurp in the
-# generated dependency rule Makefiles in one pass.
-all_deps :=
-
-
-
-# C++ apps need to be linked with g++.
-#
-# Note: flock is used to seralize linking. Linking is a memory-intensive
-# process so running parallel links can often lead to thrashing.  To disable
-# the serialization, override LINK via an envrionment variable as follows:
-#
-#   export LINK=g++
-#
-# This will allow make to invoke N linker processes as specified in -jN.
-LINK ?= flock $(builddir)/linker.lock $(CXX)
-
-CC.target ?= $(CC)
-CFLAGS.target ?= $(CFLAGS)
-CXX.target ?= $(CXX)
-CXXFLAGS.target ?= $(CXXFLAGS)
-LINK.target ?= $(LINK)
-LDFLAGS.target ?= $(LDFLAGS) 
-AR.target ?= $(AR)
-ARFLAGS.target ?= crsT
-
-# N.B.: the logic of which commands to run should match the computation done
-# in gyp's make.py where ARFLAGS.host etc. is computed.
-# TODO(evan): move all cross-compilation logic to gyp-time so we don't need
-# to replicate this environment fallback in make as well.
-CC.host ?= gcc
-CFLAGS.host ?=
-CXX.host ?= g++
-CXXFLAGS.host ?=
-LINK.host ?= g++
-LDFLAGS.host ?=
-AR.host ?= ar
-ARFLAGS.host := crsT
-
-# Define a dir function that can handle spaces.
-# http://www.gnu.org/software/make/manual/make.html#Syntax-of-Functions
-# "leading spaces cannot appear in the text of the first argument as written.
-# These characters can be put into the argument value by variable substitution."
-empty :=
-space := $(empty) $(empty)
-
-# http://stackoverflow.com/questions/1189781/using-make-dir-or-notdir-on-a-path-with-spaces
-replace_spaces = $(subst $(space),?,$1)
-unreplace_spaces = $(subst ?,$(space),$1)
-dirx = $(call unreplace_spaces,$(dir $(call replace_spaces,$1)))
-
-# Flags to make gcc output dependency info.  Note that you need to be
-# careful here to use the flags that ccache and distcc can understand.
-# We write to a dep file on the side first and then rename at the end
-# so we can't end up with a broken dep file.
-depfile = $(depsdir)/$(call replace_spaces,$@).d
-DEPFLAGS = -MMD -MF $(depfile).raw
-
-# We have to fixup the deps output in a few ways.
-# (1) the file output should mention the proper .o file.
-# ccache or distcc lose the path to the target, so we convert a rule of
-# the form:
-#   foobar.o: DEP1 DEP2
-# into
-#   path/to/foobar.o: DEP1 DEP2
-# (2) we want missing files not to cause us to fail to build.
-# We want to rewrite
-#   foobar.o: DEP1 DEP2 \
-#               DEP3
-# to
-#   DEP1:
-#   DEP2:
-#   DEP3:
-# so if the files are missing, they're just considered phony rules.
-# We have to do some pretty insane escaping to get those backslashes
-# and dollar signs past make, the shell, and sed at the same time.
-# Doesn't work with spaces, but that's fine: .d files have spaces in
-# their names replaced with other characters.
-define fixup_dep
-# The depfile may not exist if the input file didn't have any #includes.
-touch $(depfile).raw
-# Fixup path as in (1).
-sed -e "s|^$(notdir $@)|$@|" $(depfile).raw >> $(depfile)
-# Add extra rules as in (2).
-# We remove slashes and replace spaces with new lines;
-# remove blank lines;
-# delete the first line and append a colon to the remaining lines.
-sed -e 's|\\||' -e 'y| |\n|' $(depfile).raw |\
-  grep -v '^$$'                             |\
-  sed -e 1d -e 's|$$|:|'                     \
-    >> $(depfile)
-rm $(depfile).raw
-endef
-
-# Command definitions:
-# - cmd_foo is the actual command to run;
-# - quiet_cmd_foo is the brief-output summary of the command.
-
-quiet_cmd_cc = CC($(TOOLSET)) $@
-cmd_cc = $(CC.$(TOOLSET)) $(GYP_CFLAGS) $(DEPFLAGS) $(CFLAGS.$(TOOLSET)) -c -o $@ $<
-
-quiet_cmd_cxx = CXX($(TOOLSET)) $@
-cmd_cxx = $(CXX.$(TOOLSET)) $(GYP_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $<
-
-quiet_cmd_touch = TOUCH $@
-cmd_touch = touch $@
-
-quiet_cmd_copy = COPY $@
-# send stderr to /dev/null to ignore messages when linking directories.
-cmd_copy = ln -f "$<" "$@" 2>/dev/null || (rm -rf "$@" && cp -af "$<" "$@")
-
-quiet_cmd_alink = AR($(TOOLSET)) $@
-cmd_alink = rm -f $@ && $(AR.$(TOOLSET)) $(ARFLAGS.$(TOOLSET)) $@ $(filter %.o,$^)
-
-# Due to circular dependencies between libraries :(, we wrap the
-# special "figure out circular dependencies" flags around the entire
-# input list during linking.
-quiet_cmd_link = LINK($(TOOLSET)) $@
-cmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ -Wl,--start-group $(LD_INPUTS) -Wl,--end-group $(LIBS)
-
-# We support two kinds of shared objects (.so):
-# 1) shared_library, which is just bundling together many dependent libraries
-# into a link line.
-# 2) loadable_module, which is generating a module intended for dlopen().
-#
-# They differ only slightly:
-# In the former case, we want to package all dependent code into the .so.
-# In the latter case, we want to package just the API exposed by the
-# outermost module.
-# This means shared_library uses --whole-archive, while loadable_module doesn't.
-# (Note that --whole-archive is incompatible with the --start-group used in
-# normal linking.)
-
-# Other shared-object link notes:
-# - Set SONAME to the library filename so our binaries don't reference
-# the local, absolute paths used on the link command-line.
-quiet_cmd_solink = SOLINK($(TOOLSET)) $@
-cmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--whole-archive $(LD_INPUTS) -Wl,--no-whole-archive $(LIBS)
-
-quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@
-cmd_solink_module = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--start-group $(filter-out FORCE_DO_CMD, $^) -Wl,--end-group $(LIBS)
-
-
-# Define an escape_quotes function to escape single quotes.
-# This allows us to handle quotes properly as long as we always use
-# use single quotes and escape_quotes.
-escape_quotes = $(subst ','\'',$(1))
-# This comment is here just to include a ' to unconfuse syntax highlighting.
-# Define an escape_vars function to escape '$' variable syntax.
-# This allows us to read/write command lines with shell variables (e.g.
-# $LD_LIBRARY_PATH), without triggering make substitution.
-escape_vars = $(subst $$,$$$$,$(1))
-# Helper that expands to a shell command to echo a string exactly as it is in
-# make. This uses printf instead of echo because printf's behaviour with respect
-# to escape sequences is more portable than echo's across different shells
-# (e.g., dash, bash).
-exact_echo = printf '%s\n' '$(call escape_quotes,$(1))'
-
-# Helper to compare the command we're about to run against the command
-# we logged the last time we ran the command.  Produces an empty
-# string (false) when the commands match.
-# Tricky point: Make has no string-equality test function.
-# The kernel uses the following, but it seems like it would have false
-# positives, where one string reordered its arguments.
-#   arg_check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \
-#                       $(filter-out $(cmd_$@), $(cmd_$(1))))
-# We instead substitute each for the empty string into the other, and
-# say they're equal if both substitutions produce the empty string.
-# .d files contain ? instead of spaces, take that into account.
-command_changed = $(or $(subst $(cmd_$(1)),,$(cmd_$(call replace_spaces,$@))),\
-                       $(subst $(cmd_$(call replace_spaces,$@)),,$(cmd_$(1))))
-
-# Helper that is non-empty when a prerequisite changes.
-# Normally make does this implicitly, but we force rules to always run
-# so we can check their command lines.
-#   $? -- new prerequisites
-#   $| -- order-only dependencies
-prereq_changed = $(filter-out FORCE_DO_CMD,$(filter-out $|,$?))
-
-# Helper that executes all postbuilds, and deletes the output file when done
-# if any of the postbuilds failed.
-define do_postbuilds
-  @E=0;\
-  for p in $(POSTBUILDS); do\
-    eval $$p;\
-    F=$$?;\
-    if [ $$F -ne 0 ]; then\
-      E=$$F;\
-    fi;\
-  done;\
-  if [ $$E -ne 0 ]; then\
-    rm -rf "$@";\
-    exit $$E;\
-  fi
-endef
-
-# do_cmd: run a command via the above cmd_foo names, if necessary.
-# Should always run for a given target to handle command-line changes.
-# Second argument, if non-zero, makes it do asm/C/C++ dependency munging.
-# Third argument, if non-zero, makes it do POSTBUILDS processing.
-# Note: We intentionally do NOT call dirx for depfile, since it contains ? for
-# spaces already and dirx strips the ? characters.
-define do_cmd
-$(if $(or $(command_changed),$(prereq_changed)),
-  @$(call exact_echo,  $($(quiet)cmd_$(1)))
-  @mkdir -p "$(call dirx,$@)" "$(dir $(depfile))"
-  $(if $(findstring flock,$(word 1,$(cmd_$1))),
-    @$(cmd_$(1))
-    @echo "  $(quiet_cmd_$(1)): Finished",
-    @$(cmd_$(1))
-  )
-  @$(call exact_echo,$(call escape_vars,cmd_$(call replace_spaces,$@) := $(cmd_$(1)))) > $(depfile)
-  @$(if $(2),$(fixup_dep))
-  $(if $(and $(3), $(POSTBUILDS)),
-    $(call do_postbuilds)
-  )
-)
-endef
-
-# Declare "all" target first so it is the default, even though we don't have the
-# deps yet.
-.PHONY: all
-all:
-
-# Use FORCE_DO_CMD to force a target to run.  Should be coupled with
-# do_cmd.
-.PHONY: FORCE_DO_CMD
-FORCE_DO_CMD:
-
-TOOLSET := target
-# Suffix rules, putting all outputs into $(obj).
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.c FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cc FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cpp FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cxx FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.S FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.s FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-
-# Try building from generated source, too.
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.c FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cc FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cpp FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cxx FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.S FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.s FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-
-$(obj).$(TOOLSET)/%.o: $(obj)/%.c FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.cc FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.cpp FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.cxx FORCE_DO_CMD
-       @$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.S FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.s FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-
-
-ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
-    $(findstring $(join ^,$(prefix)),\
-                 $(join ^,src/libuv/run-benchmarks.target.mk)))),)
-  include src/libuv/run-benchmarks.target.mk
-endif
-ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
-    $(findstring $(join ^,$(prefix)),\
-                 $(join ^,src/libuv/run-tests.target.mk)))),)
-  include src/libuv/run-tests.target.mk
-endif
-ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
-    $(findstring $(join ^,$(prefix)),\
-                 $(join ^,src/libuv/uv.target.mk)))),)
-  include src/libuv/uv.target.mk
-endif
-
-quiet_cmd_regen_makefile = ACTION Regenerating $@
-cmd_regen_makefile = ./src/libuv/build/gyp/gyp -fmake --ignore-environment "--toplevel-dir=." "--depth=." "--generator-output=mk/libuv/x86_64/win" "-Dlibrary=static_library" "-Dtarget_arch=x86_64" "-DOS=win" src/libuv/uv.gyp
-Makefile: $(srcdir)/src/libuv/uv.gyp
-       $(call do_cmd,regen_makefile)
-
-# "all" is a concatenation of the "all" targets from all the included
-# sub-makefiles. This is just here to clarify.
-all:
-
-# Add in dependency-tracking rules.  $(all_deps) is the list of every single
-# target in our tree. Only consider the ones with .d (dependency) info:
-d_files := $(wildcard $(foreach f,$(all_deps),$(depsdir)/$(f).d))
-ifneq ($(d_files),)
-  # Rather than include each individual .d file, concatenate them into a
-  # single file which make is able to load faster.  We split this into
-  # commands that take 1000 files at a time to avoid overflowing the
-  # command line.
-  $(shell cat $(wordlist 1,1000,$(d_files)) > $(depsdir)/all.deps)
-
-  ifneq ($(word 1001,$(d_files)),)
-    $(error Found unprocessed dependency files (gyp didn't generate enough rules!))
-  endif
-
-  # make looks for ways to re-generate included makefiles, but in our case, we
-  # don't have a direct way. Explicitly telling make that it has nothing to do
-  # for them makes it go faster.
-  $(depsdir)/all.deps: ;
-
-  include $(depsdir)/all.deps
-endif
index 68dc04f210593f7d201169aa0c53cda362827df8..25bf58f854886b60bb13d8e58485cddd463f426e 100644 (file)
@@ -2,18 +2,42 @@
 
 TOOLSET := target
 TARGET := run-benchmarks
-DEFS_Default := 
+DEFS_Debug := '-DWIN32' \
+       '-D_CRT_SECURE_NO_DEPRECATE' \
+       '-D_CRT_NONSTDC_NO_DEPRECATE' \
+       '-DDEBUG' \
+       '-D_DEBUG'
 
 # Flags passed to all source files.
-CFLAGS_Default := 
+CFLAGS_Debug := -g \
+       -O0
 
 # Flags passed to only C files.
-CFLAGS_C_Default := 
+CFLAGS_C_Debug := 
 
 # Flags passed to only C++ files.
-CFLAGS_CC_Default := 
+CFLAGS_CC_Debug := 
 
-INCS_Default := -I$(srcdir)/src/libuv/include
+INCS_Debug := -I$(srcdir)/src/libuv/include
+
+DEFS_Release := '-DWIN32' \
+       '-D_CRT_SECURE_NO_DEPRECATE' \
+       '-D_CRT_NONSTDC_NO_DEPRECATE' \
+       '-DNDEBUG'
+
+# Flags passed to all source files.
+CFLAGS_Release := -O3 \
+       -fomit-frame-pointer \
+       -fdata-sections \
+       -ffunction-sections
+
+# Flags passed to only C files.
+CFLAGS_C_Release := 
+
+# Flags passed to only C++ files.
+CFLAGS_CC_Release := 
+
+INCS_Release := -I$(srcdir)/src/libuv/include
 
 OBJS := $(obj).target/$(TARGET)/src/libuv/test/benchmark-ares.o \
        $(obj).target/$(TARGET)/src/libuv/test/benchmark-getaddrinfo.o \
@@ -22,6 +46,7 @@ OBJS := $(obj).target/$(TARGET)/src/libuv/test/benchmark-ares.o \
        $(obj).target/$(TARGET)/src/libuv/test/benchmark-pump.o \
        $(obj).target/$(TARGET)/src/libuv/test/benchmark-sizes.o \
        $(obj).target/$(TARGET)/src/libuv/test/benchmark-spawn.o \
+       $(obj).target/$(TARGET)/src/libuv/test/benchmark-thread.o \
        $(obj).target/$(TARGET)/src/libuv/test/benchmark-tcp-write-batch.o \
        $(obj).target/$(TARGET)/src/libuv/test/benchmark-udp-packet-storm.o \
        $(obj).target/$(TARGET)/src/libuv/test/dns-server.o \
@@ -40,8 +65,8 @@ $(OBJS): | $(obj).target/src/libuv/libuv.a
 # CFLAGS et al overrides must be target-local.
 # See "Target-specific Variable Values" in the GNU Make manual.
 $(OBJS): TOOLSET := $(TOOLSET)
-$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
-$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
+$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
+$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
 
 # Suffix rules, putting all outputs into $(obj).
 
@@ -58,10 +83,14 @@ $(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.c FORCE_DO_CMD
 
 # End of this set of suffix rules
 ### Rules for final target.
-LDFLAGS_Default := 
+LDFLAGS_Debug := 
+
+LDFLAGS_Release := 
 
 LIBS := ws2_32.lib \
-       -lws2_32.lib
+       -lws2_32.lib \
+       -lpsapi.lib \
+       -liphlpapi.lib
 
 $(builddir)/run-benchmarks: GYP_LDFLAGS := $(LDFLAGS_$(BUILDTYPE))
 $(builddir)/run-benchmarks: LIBS := $(LIBS)
index 9b09db73373df4434cfb0e2454f7ec7ce3fbaf6d..51b62f7a3e2d58f64a4e3c2f9b1e33b874894567 100644 (file)
@@ -2,29 +2,56 @@
 
 TOOLSET := target
 TARGET := run-tests
-DEFS_Default := 
+DEFS_Debug := '-DWIN32' \
+       '-D_CRT_SECURE_NO_DEPRECATE' \
+       '-D_CRT_NONSTDC_NO_DEPRECATE' \
+       '-DDEBUG' \
+       '-D_DEBUG'
 
 # Flags passed to all source files.
-CFLAGS_Default := 
+CFLAGS_Debug := -g \
+       -O0
 
 # Flags passed to only C files.
-CFLAGS_C_Default := 
+CFLAGS_C_Debug := 
 
 # Flags passed to only C++ files.
-CFLAGS_CC_Default := 
+CFLAGS_CC_Debug := 
 
-INCS_Default := -I$(srcdir)/src/libuv/include
+INCS_Debug := -I$(srcdir)/src/libuv/include
+
+DEFS_Release := '-DWIN32' \
+       '-D_CRT_SECURE_NO_DEPRECATE' \
+       '-D_CRT_NONSTDC_NO_DEPRECATE' \
+       '-DNDEBUG'
+
+# Flags passed to all source files.
+CFLAGS_Release := -O3 \
+       -fomit-frame-pointer \
+       -fdata-sections \
+       -ffunction-sections
+
+# Flags passed to only C files.
+CFLAGS_C_Release := 
+
+# Flags passed to only C++ files.
+CFLAGS_CC_Release := 
+
+INCS_Release := -I$(srcdir)/src/libuv/include
 
 OBJS := $(obj).target/$(TARGET)/src/libuv/test/blackhole-server.o \
        $(obj).target/$(TARGET)/src/libuv/test/echo-server.o \
        $(obj).target/$(TARGET)/src/libuv/test/run-tests.o \
        $(obj).target/$(TARGET)/src/libuv/test/runner.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-get-loadavg.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-util.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-async.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-error.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-callback-stack.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-connection-fail.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-cwd-and-chdir.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-delayed-accept.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-eio-overflow.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-fail-always.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-fs.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-fs-event.o \
@@ -36,12 +63,15 @@ OBJS := $(obj).target/$(TARGET)/src/libuv/test/blackhole-server.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-hrtime.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-idle.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-ipc.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-ipc-threads.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-loop-handles.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-multiple-listen.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-pass-always.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-ping-pong.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-pipe-bind-error.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-pipe-connect-error.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-platform-output.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-process-title.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-ref.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-shutdown-eof.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-spawn.o \
@@ -56,13 +86,17 @@ OBJS := $(obj).target/$(TARGET)/src/libuv/test/blackhole-server.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-tcp-write-to-half-open-connection.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-tcp-writealot.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-threadpool.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-mutexes.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-thread.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-timer-again.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-timer.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-tty.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-udp-dgram-too-big.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-udp-ipv6.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-udp-options.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-udp-send-and-recv.o \
        $(obj).target/$(TARGET)/src/libuv/test/test-udp-multicast-join.o \
+       $(obj).target/$(TARGET)/src/libuv/test/test-counters-init.o \
        $(obj).target/$(TARGET)/src/libuv/test/runner-win.o
 
 # Add to the list of files we specially track dependencies for.
@@ -74,8 +108,8 @@ $(OBJS): | $(obj).target/src/libuv/libuv.a
 # CFLAGS et al overrides must be target-local.
 # See "Target-specific Variable Values" in the GNU Make manual.
 $(OBJS): TOOLSET := $(TOOLSET)
-$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
-$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
+$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
+$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
 
 # Suffix rules, putting all outputs into $(obj).
 
@@ -92,10 +126,14 @@ $(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.c FORCE_DO_CMD
 
 # End of this set of suffix rules
 ### Rules for final target.
-LDFLAGS_Default := 
+LDFLAGS_Debug := 
+
+LDFLAGS_Release := 
 
 LIBS := ws2_32.lib \
-       -lws2_32.lib
+       -lws2_32.lib \
+       -lpsapi.lib \
+       -liphlpapi.lib
 
 $(builddir)/run-tests: GYP_LDFLAGS := $(LDFLAGS_$(BUILDTYPE))
 $(builddir)/run-tests: LIBS := $(LIBS)
index 86ed7071555c7b121cef6ef21faeb3305b0c02f3..53576a0f93570eec5f0ad4cbe4d217315332edd9 100644 (file)
@@ -2,21 +2,53 @@
 
 TOOLSET := target
 TARGET := uv
-DEFS_Default := '-DHAVE_CONFIG_H' \
-       '-D_WIN32_WINNT=0x0502' \
+DEFS_Debug := '-DWIN32' \
+       '-D_CRT_SECURE_NO_DEPRECATE' \
+       '-D_CRT_NONSTDC_NO_DEPRECATE' \
+       '-DHAVE_CONFIG_H' \
+       '-D_WIN32_WINNT=0x0600' \
        '-DEIO_STACKSIZE=262144' \
-       '-D_GNU_SOURCE'
+       '-D_GNU_SOURCE' \
+       '-DDEBUG' \
+       '-D_DEBUG'
 
 # Flags passed to all source files.
-CFLAGS_Default := 
+CFLAGS_Debug := -g \
+       -O0
 
 # Flags passed to only C files.
-CFLAGS_C_Default := 
+CFLAGS_C_Debug := 
 
 # Flags passed to only C++ files.
-CFLAGS_CC_Default := 
+CFLAGS_CC_Debug := 
 
-INCS_Default := -I$(srcdir)/src/libuv/include \
+INCS_Debug := -I$(srcdir)/src/libuv/include \
+       -I$(srcdir)/src/libuv/include/uv-private \
+       -I$(srcdir)/src/libuv/src \
+       -I$(srcdir)/src/libuv/src/ares/config_win32
+
+DEFS_Release := '-DWIN32' \
+       '-D_CRT_SECURE_NO_DEPRECATE' \
+       '-D_CRT_NONSTDC_NO_DEPRECATE' \
+       '-DHAVE_CONFIG_H' \
+       '-D_WIN32_WINNT=0x0600' \
+       '-DEIO_STACKSIZE=262144' \
+       '-D_GNU_SOURCE' \
+       '-DNDEBUG'
+
+# Flags passed to all source files.
+CFLAGS_Release := -O3 \
+       -fomit-frame-pointer \
+       -fdata-sections \
+       -ffunction-sections
+
+# Flags passed to only C files.
+CFLAGS_C_Release := 
+
+# Flags passed to only C++ files.
+CFLAGS_CC_Release := 
+
+INCS_Release := -I$(srcdir)/src/libuv/include \
        -I$(srcdir)/src/libuv/include/uv-private \
        -I$(srcdir)/src/libuv/src \
        -I$(srcdir)/src/libuv/src/ares/config_win32
@@ -79,13 +111,13 @@ OBJS := $(obj).target/$(TARGET)/src/libuv/src/uv-common.o \
        $(obj).target/$(TARGET)/src/libuv/src/win/handle.o \
        $(obj).target/$(TARGET)/src/libuv/src/win/loop-watcher.o \
        $(obj).target/$(TARGET)/src/libuv/src/win/pipe.o \
+       $(obj).target/$(TARGET)/src/libuv/src/win/thread.o \
        $(obj).target/$(TARGET)/src/libuv/src/win/process.o \
        $(obj).target/$(TARGET)/src/libuv/src/win/req.o \
        $(obj).target/$(TARGET)/src/libuv/src/win/stream.o \
        $(obj).target/$(TARGET)/src/libuv/src/win/tcp.o \
        $(obj).target/$(TARGET)/src/libuv/src/win/tty.o \
        $(obj).target/$(TARGET)/src/libuv/src/win/threadpool.o \
-       $(obj).target/$(TARGET)/src/libuv/src/win/threads.o \
        $(obj).target/$(TARGET)/src/libuv/src/win/timer.o \
        $(obj).target/$(TARGET)/src/libuv/src/win/udp.o \
        $(obj).target/$(TARGET)/src/libuv/src/win/util.o \
@@ -98,8 +130,8 @@ all_deps += $(OBJS)
 # CFLAGS et al overrides must be target-local.
 # See "Target-specific Variable Values" in the GNU Make manual.
 $(OBJS): TOOLSET := $(TOOLSET)
-$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
-$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
+$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
+$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
 
 # Suffix rules, putting all outputs into $(obj).
 
@@ -116,7 +148,9 @@ $(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.c FORCE_DO_CMD
 
 # End of this set of suffix rules
 ### Rules for final target.
-LDFLAGS_Default := 
+LDFLAGS_Debug := 
+
+LDFLAGS_Release := 
 
 LIBS := 
 
index 10cef47e6f02d8efa204b4915f4a2b8695f6bcd4..45c1d3ab751e862b47a241e68b1ba187bbe88e4e 100644 (file)
@@ -99,6 +99,10 @@ ifneq ($(findstring darwin,$(CFG_OSTYPE)),)
   CFG_INSTALL_NAME = -Wl,-install_name,@rpath/$(1)
 endif
 
+# Hack: not sure how to test if a file exists in make other than this
+OS_SUPP = $(patsubst %,--suppressions=%,\
+           $(wildcard $(CFG_SRC_DIR)src/etc/$(CFG_OSTYPE).supp*))
+
 ifneq ($(findstring mingw,$(CFG_OSTYPE)),)
   CFG_WINDOWSY := 1
 endif
@@ -154,7 +158,9 @@ ifdef CFG_UNIXY
   ifdef CFG_VALGRIND
     CFG_VALGRIND += --leak-check=full \
                     --error-exitcode=100 \
-                    --quiet --suppressions=$(CFG_SRC_DIR)src/etc/x86.supp
+                    --quiet \
+                    --suppressions=$(CFG_SRC_DIR)src/etc/x86.supp \
+                    $(OS_SUPP)
   endif
 endif
 
index a161f298a6397467777e1cf6a0c81137ed59c3d0..06ecc6c5d7cd02be219577baf28cd5fc54471d5b 100644 (file)
--- a/mk/rt.mk
+++ b/mk/rt.mk
@@ -42,6 +42,7 @@ RUNTIME_CS_$(1) := \
               rt/rust_run_program.cpp \
               rt/rust_crate_cache.cpp \
               rt/rust_env.cpp \
+              rt/rust_task_thread.cpp \
               rt/rust_scheduler.cpp \
               rt/rust_task.cpp \
               rt/rust_task_list.cpp \
@@ -50,21 +51,17 @@ RUNTIME_CS_$(1) := \
               rt/rust_uv.cpp \
               rt/rust_uvtmp.cpp \
               rt/rust_log.cpp \
-              rt/rust_timer.cpp \
               rt/circular_buffer.cpp \
               rt/isaac/randport.cpp \
               rt/rust_srv.cpp \
               rt/rust_kernel.cpp \
               rt/rust_shape.cpp \
               rt/rust_obstack.cpp \
-              rt/rust_gc.cpp \
               rt/rust_abi.cpp \
               rt/rust_cc.cpp \
               rt/rust_debug.cpp \
               rt/memory_region.cpp \
-              rt/test/rust_test_harness.cpp \
-              rt/test/rust_test_runtime.cpp \
-              rt/test/rust_test_util.cpp \
+              rt/boxed_region.cpp \
               rt/arch/$$(HOST_$(1))/context.cpp
 
 RUNTIME_S_$(1) := rt/arch/$$(HOST_$(1))/_context.S \
@@ -76,7 +73,6 @@ RUNTIME_HDR_$(1) := rt/globals.h \
                rt/rust_abi.h \
                rt/rust_cc.h \
                rt/rust_debug.h \
-               rt/rust_gc.h \
                rt/rust_internal.h \
                rt/rust_util.h \
                rt/rust_env.h \
@@ -84,6 +80,7 @@ RUNTIME_HDR_$(1) := rt/globals.h \
                rt/rust_unwind.h \
                rt/rust_upcall.h \
                rt/rust_port.h \
+               rt/rust_task_thread.h \
                rt/rust_scheduler.h \
                rt/rust_shape.h \
                rt/rust_task.h \
@@ -102,9 +99,6 @@ RUNTIME_HDR_$(1) := rt/globals.h \
                rt/rust_kernel.h \
                rt/memory_region.h \
                rt/memory.h \
-               rt/test/rust_test_harness.h \
-               rt/test/rust_test_runtime.h \
-               rt/test/rust_test_util.h \
                rt/arch/$$(HOST_$(1))/context.h \
                rt/arch/$$(HOST_$(1))/regs.h
 
@@ -116,16 +110,16 @@ endif
 
 ifeq ($$(CFG_WINDOWSY), 1)
   LIBUV_OSTYPE_$(1) := win
-  LIBUV_LIB_$(1) := rt/$(1)/libuv/Default/obj.target/src/libuv/libuv.a
+  LIBUV_LIB_$(1) := rt/$(1)/libuv/Release/obj.target/src/libuv/libuv.a
 else ifeq ($(CFG_OSTYPE), apple-darwin)
   LIBUV_OSTYPE_$(1) := mac
-  LIBUV_LIB_$(1) := rt/$(1)/libuv/Default/libuv.a
+  LIBUV_LIB_$(1) := rt/$(1)/libuv/Release/libuv.a
 else ifeq ($(CFG_OSTYPE), unknown-freebsd)
   LIBUV_OSTYPE_$(1) := freebsd
-  LIBUV_LIB_$(1) := rt/$(1)/libuv/Default/obj.target/src/libuv/libuv.a
+  LIBUV_LIB_$(1) := rt/$(1)/libuv/Release/obj.target/src/libuv/libuv.a
 else
   LIBUV_OSTYPE_$(1) := unix
-  LIBUV_LIB_$(1) := rt/$(1)/libuv/Default/obj.target/src/libuv/libuv.a
+  LIBUV_LIB_$(1) := rt/$(1)/libuv/Release/obj.target/src/libuv/libuv.a
 endif
 
 RUNTIME_DEF_$(1) := rt/rustrt$$(CFG_DEF_SUFFIX)
@@ -172,6 +166,7 @@ $$(LIBUV_LIB_$(1)): $$(wildcard \
                CC="$$(CFG_GCCISH_CROSS)$$(CC)" \
                CXX="$$(CFG_GCCISH_CROSS)$$(CXX)" \
                AR="$$(CFG_GCCISH_CROSS)$$(AR)" \
+               BUILDTYPE=Release \
                builddir_name="$$(CFG_BUILD_DIR)/rt/$(1)/libuv" \
                V=$$(VERBOSE) FLOCK= uv
 
index 69546118c49b33c80a118f5dc25b87645d3bb2f9..0acd3e4f1c8e57eceb861efd5feed22747b9e3e4 100644 (file)
@@ -32,16 +32,16 @@ enum _src {
     url: str,
     method: str,
     description: str,
-    ref: option::t<str>,
+    ref: option<str>,
     tags: [str]
 };
 
 type source = {
     name: str,
     url: str,
-    sig: option::t<str>,
-    key: option::t<str>,
-    keyfp: option::t<str>,
+    sig: option<str>,
+    key: option<str>,
+    keyfp: option<str>,
     mutable packages: [package]
 };
 
@@ -60,9 +60,9 @@ enum _src {
     name: str,
     vers: str,
     uuid: str,
-    desc: option::t<str>,
-    sigs: option::t<str>,
-    crate_type: option::t<str>
+    desc: option<str>,
+    sigs: option<str>,
+    crate_type: option<str>
 };
 
 fn info(msg: str) {
@@ -77,9 +77,9 @@ fn error(msg: str) {
     io::stdout().write_line("error: " + msg);
 }
 
-fn load_link(mis: [@ast::meta_item]) -> (option::t<str>,
-                                         option::t<str>,
-                                         option::t<str>) {
+fn load_link(mis: [@ast::meta_item]) -> (option<str>,
+                                         option<str>,
+                                         option<str>) {
     let name = none;
     let vers = none;
     let uuid = none;
@@ -93,12 +93,13 @@ fn load_link(mis: [@ast::meta_item]) -> (option::t<str>,
                     _ { }
                 }
             }
+            _ { fail "load_link: meta items must be name-values"; }
         }
     }
     (name, vers, uuid)
 }
 
-fn load_pkg(filename: str) -> option::t<pkg> {
+fn load_pkg(filename: str) -> option<pkg> {
     let cm = codemap::new_codemap();
     let handler = diagnostic::mk_handler(none);
     let sess = @{
@@ -135,6 +136,7 @@ fn load_pkg(filename: str) -> option::t<pkg> {
                     uuid = u;
                 }
             }
+            _ { fail "load_pkg: pkg attributes may not contain meta_words"; }
         }
     }
 
@@ -160,7 +162,7 @@ fn rest(s: str, start: uint) -> str {
     if (start >= str::char_len(s)) {
         ""
     } else {
-        str::char_slice(s, start, str::char_len(s))
+        str::slice(s, start, str::char_len(s))
     }
 }
 
@@ -437,7 +439,7 @@ fn install_source(c: cargo, path: str) {
     }
 }
 
-fn install_git(c: cargo, wd: str, url: str, ref: option::t<str>) {
+fn install_git(c: cargo, wd: str, url: str, ref: option<str>) {
     run::run_program("git", ["clone", url, wd]);
     if option::is_some::<str>(ref) {
         let r = option::get::<str>(ref);
@@ -571,7 +573,7 @@ fn install_named_specific(c: cargo, wd: str, src: str, name: str) {
     error("Can't find package " + src + "/" + name);
 }
 
-fn cmd_install(c: cargo, argv: [str]) {
+fn cmd_install(c: cargo, argv: [str]) unsafe {
     // cargo install <pkg>
     if vec::len(argv) < 3u {
         cmd_usage();
@@ -594,8 +596,9 @@ fn cmd_install(c: cargo, argv: [str]) {
         let uuid = rest(target, 5u);
         let idx = str::index(uuid, '/' as u8);
         if idx != -1 {
-            let source = str::slice(uuid, 0u, idx as uint);
-            uuid = str::slice(uuid, idx as uint + 1u, str::byte_len(uuid));
+            let source = str::unsafe::slice_bytes(uuid, 0u, idx as uint);
+            uuid = str::unsafe::slice_bytes(uuid, idx as uint + 1u,
+                                      str::byte_len(uuid));
             install_uuid_specific(c, wd, source, uuid);
         } else {
             install_uuid(c, wd, uuid);
@@ -604,8 +607,9 @@ fn cmd_install(c: cargo, argv: [str]) {
         let name = target;
         let idx = str::index(name, '/' as u8);
         if idx != -1 {
-            let source = str::slice(name, 0u, idx as uint);
-            name = str::slice(name, idx as uint + 1u, str::byte_len(name));
+            let source = str::unsafe::slice_bytes(name, 0u, idx as uint);
+            name = str::unsafe::slice_bytes(name, idx as uint + 1u,
+                                      str::byte_len(name));
             install_named_specific(c, wd, source, name);
         } else {
             install_named(c, wd, name);
index 9de31c2d014d4c7b65ff4bedbb6c19d227315a92..a5670a03fa9ca6899fd6d28fea00768fe3a13f3e 100644 (file)
 
 const frame_glue_fns_field_reloc: int = 2;
 
-// n.b. must be same as cbox_elt_refcnt
-const box_rc_field_refcnt: int = 0;
-const box_rc_field_body: int = 1;
+const box_field_refcnt: int = 0;
+const box_field_tydesc: int = 1;
+const box_field_prev: int = 2;
+const box_field_next: int = 3;
+const box_field_body: int = 4;
 
 const general_code_alignment: int = 16;
 
 const fn_field_code: int = 0;
 const fn_field_box: int = 1;
 
-// closure_box, see trans_closure.rs
-//
-// n.b. the refcnt must be compatible with a normal box
-const cbox_elt_refcnt: int = 0;
-const cbox_elt_tydesc: int = 1;
-const cbox_elt_ty_params: int = 2;
-const cbox_elt_bindings: int = 3;
+// closures, see trans_closure.rs
+const closure_body_ty_params: int = 0;
+const closure_body_bindings: int = 1;
 
 const vec_elt_fill: int = 0;
 
index 068c8fddb334907b417325b3c97d39d1250181a3..eee0c60599f291be74e6661562d0a5fa580cbb9a 100644 (file)
 import std::sha1::sha1;
 import syntax::ast;
 import syntax::print::pprust;
-import lib::llvm::llvm::ModuleRef;
-import lib::llvm::mk_pass_manager;
-import lib::llvm::mk_target_data;
-import lib::llvm::False;
+import lib::llvm::{ModuleRef, mk_pass_manager, mk_target_data, True, False};
 import util::filesearch;
+import middle::ast_map::{path, path_mod, path_name};
 
 enum output_type {
     output_type_none,
@@ -38,7 +36,7 @@ fn llvm_err(sess: session, msg: str) unsafe {
     } else { sess.fatal(msg + ": " + str::from_cstr(buf)); }
 }
 
-fn load_intrinsics_bc(sess: session) -> option::t<ModuleRef> {
+fn load_intrinsics_bc(sess: session) -> option<ModuleRef> {
     let path = alt filesearch::search(
         sess.filesearch,
         bind filesearch::pick_file("intrinsics.bc", _)) {
@@ -182,7 +180,7 @@ fn run_passes(sess: session, llmod: ModuleRef, output: str) {
             let MPMB = llvm::LLVMPassManagerBuilderCreate();
             llvm::LLVMPassManagerBuilderSetOptLevel(MPMB,
                                                     opts.optimize as c_uint);
-            llvm::LLVMPassManagerBuilderSetSizeLevel(MPMB, 0);
+            llvm::LLVMPassManagerBuilderSetSizeLevel(MPMB, False);
             llvm::LLVMPassManagerBuilderSetDisableUnitAtATime(MPMB, False);
             llvm::LLVMPassManagerBuilderSetDisableUnrollLoops(MPMB, False);
             llvm::LLVMPassManagerBuilderSetDisableSimplifyLibCalls(MPMB,
@@ -368,14 +366,14 @@ fn build_link_meta(sess: session, c: ast::crate, output: str,
                    sha: sha1) -> link_meta {
 
     type provided_metas =
-        {name: option::t<str>,
-         vers: option::t<str>,
+        {name: option<str>,
+         vers: option<str>,
          cmh_items: [@ast::meta_item]};
 
     fn provided_link_metas(sess: session, c: ast::crate) ->
        provided_metas {
-        let name: option::t<str> = none;
-        let vers: option::t<str> = none;
+        let name: option<str> = none;
+        let vers: option<str> = none;
         let cmh_items: [@ast::meta_item] = [];
         let linkage_metas = attr::find_linkage_metas(c.node.attrs);
         attr::require_unique_names(sess, linkage_metas);
@@ -517,25 +515,27 @@ fn get_symbol_hash(ccx: @crate_ctxt, t: ty::t) -> str {
     ret hash;
 }
 
-fn mangle(ss: [str]) -> str {
+fn mangle(ss: path) -> str {
     // Follow C++ namespace-mangling style
 
     let n = "_ZN"; // Begin name-sequence.
 
-    for s: str in ss { n += #fmt["%u%s", str::byte_len(s), s]; }
+    for s in ss {
+        alt s { path_name(s) | path_mod(s) {
+          n += #fmt["%u%s", str::byte_len(s), s];
+        } }
+    }
     n += "E"; // End name-sequence.
-
-    ret n;
+    n
 }
 
-fn exported_name(path: [str], hash: str, _vers: str) -> str {
+fn exported_name(path: path, hash: str, _vers: str) -> str {
     // FIXME: versioning isn't working yet
-
-    ret mangle(path + [hash]); //  + "@" + vers;
+    ret mangle(path + [path_name(hash)]); //  + "@" + vers;
 
 }
 
-fn mangle_exported_name(ccx: @crate_ctxt, path: [str], t: ty::t) -> str {
+fn mangle_exported_name(ccx: @crate_ctxt, path: path, t: ty::t) -> str {
     let hash = get_symbol_hash(ccx, t);
     ret exported_name(path, hash, ccx.link_meta.vers);
 }
@@ -544,15 +544,15 @@ fn mangle_internal_name_by_type_only(ccx: @crate_ctxt, t: ty::t, name: str) ->
    str {
     let s = util::ppaux::ty_to_short_str(ccx.tcx, t);
     let hash = get_symbol_hash(ccx, t);
-    ret mangle([name, s, hash]);
+    ret mangle([path_name(name), path_name(s), path_name(hash)]);
 }
 
-fn mangle_internal_name_by_path_and_seq(ccx: @crate_ctxt, path: [str],
+fn mangle_internal_name_by_path_and_seq(ccx: @crate_ctxt, path: path,
                                         flav: str) -> str {
-    ret mangle(path + [ccx.names(flav)]);
+    ret mangle(path + [path_name(ccx.names(flav))]);
 }
 
-fn mangle_internal_name_by_path(_ccx: @crate_ctxt, path: [str]) -> str {
+fn mangle_internal_name_by_path(_ccx: @crate_ctxt, path: path) -> str {
     ret mangle(path);
 }
 
@@ -567,13 +567,13 @@ fn link_binary(sess: session,
                out_filename: str,
                lm: link_meta) {
     // Converts a library file name into a gcc -l argument
-    fn unlib(config: @session::config, filename: str) -> str {
+    fn unlib(config: @session::config, filename: str) -> str unsafe {
         let rmlib = fn@(filename: str) -> str {
             if config.os == session::os_macos ||
                 (config.os == session::os_linux ||
                  config.os == session::os_freebsd) &&
                 str::find(filename, "lib") == 0 {
-                ret str::slice(filename, 3u,
+                ret str::unsafe::slice_bytes(filename, 3u,
                                str::byte_len(filename));
             } else { ret filename; }
         };
index b848ca9459092145911dc341ef4e1229fcdd99aa..a2030e10fabe2d273c6afb24fa821e7dbaa9e293 100644 (file)
 
 export get_rpath_flags;
 
+pure fn not_win32(os: session::os) -> bool {
+  alt os {
+      session::os_win32 { false }
+      _ { true }
+  }
+}
+
 fn get_rpath_flags(sess: session::session, out_filename: str) -> [str] {
     let os = sess.targ_cfg.os;
 
@@ -99,12 +106,13 @@ fn get_rpaths_relative_to_output(os: session::os,
 fn get_rpath_relative_to_output(os: session::os,
                                 cwd: fs::path,
                                 output: fs::path,
-                                &&lib: fs::path) -> str {
+                                &&lib: fs::path) : not_win32(os) -> str {
     // Mac doesn't appear to support $ORIGIN
     let prefix = alt os {
         session::os_linux { "$ORIGIN" + fs::path_sep() }
         session::os_freebsd { "$ORIGIN" + fs::path_sep() }
         session::os_macos { "@executable_path" + fs::path_sep() }
+        session::os_win32 { std::util::unreachable(); }
     };
 
     prefix + get_relative_to(
@@ -309,24 +317,31 @@ fn test_relative_to8() {
     #[test]
     #[cfg(target_os = "linux")]
     fn test_rpath_relative() {
-        let res = get_rpath_relative_to_output(session::os_linux,
+      let o = session::os_linux;
+      check not_win32(o);
+      let res = get_rpath_relative_to_output(o,
             "/usr", "bin/rustc", "lib/libstd.so");
-        assert res == "$ORIGIN/../lib";
+      assert res == "$ORIGIN/../lib";
     }
 
     #[test]
     #[cfg(target_os = "freebsd")]
     fn test_rpath_relative() {
-        let res = get_rpath_relative_to_output(session::os_freebsd,
+      let o = session::os_freebsd;
+      check not_win32(o);
+      let res = get_rpath_relative_to_output(o,
             "/usr", "bin/rustc", "lib/libstd.so");
-        assert res == "$ORIGIN/../lib";
+      assert res == "$ORIGIN/../lib";
     }
 
     #[test]
     #[cfg(target_os = "macos")]
     fn test_rpath_relative() {
-        let res = get_rpath_relative_to_output(session::os_macos,
-            "/usr", "bin/rustc", "lib/libstd.so");
+      // this is why refinements would be nice
+      let o = session::os_macos;
+      check not_win32(o);
+      let res = get_rpath_relative_to_output(o, "/usr", "bin/rustc",
+                                             "lib/libstd.so");
         assert res == "@executable_path/../lib";
     }
 
index 098ed43750ed0cdb002ce5c8f4c2cac89c5e93f2..e3a124640e48d211083b1b38b9e16bd2f8622c27 100644 (file)
@@ -5,15 +5,13 @@
                                T_int, T_nil, T_dict,
                                T_opaque_vec, T_ptr,
                                T_size_t, T_void};
-import lib::llvm::type_names;
-import lib::llvm::llvm::ModuleRef;
-import lib::llvm::llvm::ValueRef;
-import lib::llvm::llvm::TypeRef;
+import lib::llvm::{type_names, ModuleRef, ValueRef, TypeRef};
 
 type upcalls =
     {_fail: ValueRef,
      malloc: ValueRef,
      free: ValueRef,
+     validate_box: ValueRef,
      shared_malloc: ValueRef,
      shared_free: ValueRef,
      mark: ValueRef,
@@ -55,10 +53,12 @@ fn decl(llmod: ModuleRef, name: str, tys: [TypeRef], rv: TypeRef) ->
                              T_ptr(T_i8()),
                              size_t]),
           malloc:
-              d("malloc", [size_t, T_ptr(tydesc_type)],
+              d("malloc", [T_ptr(tydesc_type)],
                 T_ptr(T_i8())),
           free:
-              dv("free", [T_ptr(T_i8()), int_t]),
+              dv("free", [T_ptr(T_i8())]),
+          validate_box:
+              dv("validate_box", [T_ptr(T_i8())]),
           shared_malloc:
               d("shared_malloc", [size_t, T_ptr(tydesc_type)],
                 T_ptr(T_i8())),
index 986087bf4d0bda482e08b67ad6abff3a529eb296..5c0661fe51eb8c7e25b8fc4cc1e175ce4b609976 100644 (file)
@@ -159,16 +159,16 @@ fn diagnosticcolor(lvl: level) -> u8 {
 
 fn print_diagnostic(topic: str, lvl: level, msg: str) {
     if str::is_not_empty(topic) {
-        io::stdout().write_str(#fmt["%s ", topic]);
+        io::stderr().write_str(#fmt["%s ", topic]);
     }
     if term::color_supported() {
-        term::fg(io::stdout(), diagnosticcolor(lvl));
+        term::fg(io::stderr(), diagnosticcolor(lvl));
     }
-    io::stdout().write_str(#fmt["%s:", diagnosticstr(lvl)]);
+    io::stderr().write_str(#fmt["%s:", diagnosticstr(lvl)]);
     if term::color_supported() {
-        term::reset(io::stdout());
+        term::reset(io::stderr());
     }
-    io::stdout().write_str(#fmt[" %s\n", msg]);
+    io::stderr().write_str(#fmt[" %s\n", msg]);
 }
 
 fn emit(cmsp: option<(codemap::codemap, span)>,
@@ -189,11 +189,7 @@ fn emit(cmsp: option<(codemap::codemap, span)>,
 fn highlight_lines(cm: codemap::codemap, sp: span,
                    lines: @codemap::file_lines) {
 
-    // If we're not looking at a real file then we can't re-open it to
-    // pull out the lines
-    if lines.name == "-" { ret; }
-
-    let fm = codemap::get_filemap(cm, lines.name);
+    let fm = lines.file;
 
     // arbitrarily only print up to six lines of the error
     let max_lines = 6u;
@@ -205,10 +201,10 @@ fn highlight_lines(cm: codemap::codemap, sp: span,
     }
     // Print the offending lines
     for line: uint in display_lines {
-        io::stdout().write_str(#fmt["%s:%u ", fm.name, line + 1u]);
+        io::stderr().write_str(#fmt["%s:%u ", fm.name, line + 1u]);
         let s = codemap::get_line(fm, line as int);
         if !str::ends_with(s, "\n") { s += "\n"; }
-        io::stdout().write_str(s);
+        io::stderr().write_str(s);
     }
     if elided {
         let last_line = display_lines[vec::len(display_lines) - 1u];
@@ -217,7 +213,7 @@ fn highlight_lines(cm: codemap::codemap, sp: span,
         let out = "";
         while indent > 0u { out += " "; indent -= 1u; }
         out += "...\n";
-        io::stdout().write_str(out);
+        io::stderr().write_str(out);
     }
 
 
@@ -242,6 +238,6 @@ fn highlight_lines(cm: codemap::codemap, sp: span,
             let width = hi.col - lo.col - 1u;
             while width > 0u { str::push_char(s, '~'); width -= 1u; }
         }
-        io::stdout().write_str(s + "\n");
+        io::stderr().write_str(s + "\n");
     }
 }
index 75749722823d941c20f0bf7dd925e0ef418cb83d..f03e8d2c16c914407f53de5562b7a2332f71fc0d 100644 (file)
@@ -80,7 +80,7 @@ fn parse_input(sess: session, cfg: ast::crate_cfg, input: str)
     if !input_is_stdin(input) {
         parser::parse_crate_from_file(input, cfg, sess.parse_sess)
     } else {
-        let src = @str::unsafe_from_bytes(io::stdin().read_whole_stream());
+        let src = @str::from_bytes(io::stdin().read_whole_stream());
         parser::parse_crate_from_source_str(input, src, cfg, sess.parse_sess)
     }
 }
@@ -105,8 +105,8 @@ enum compile_upto {
 
 fn compile_upto(sess: session, cfg: ast::crate_cfg,
                 input: str, upto: compile_upto,
-                outputs: option::t<output_filenames>)
-    -> {crate: @ast::crate, tcx: option::t<ty::ctxt>} {
+                outputs: option<output_filenames>)
+    -> {crate: @ast::crate, tcx: option<ty::ctxt>} {
     let time_passes = sess.opts.time_passes;
     let crate = time(time_passes, "parsing",
                      bind parse_input(sess, cfg, input));
@@ -197,7 +197,7 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg,
 }
 
 fn compile_input(sess: session, cfg: ast::crate_cfg, input: str,
-                 outdir: option::t<str>, output: option::t<str>) {
+                 outdir: option<str>, output: option<str>) {
 
     let upto = if sess.opts.parse_only { cu_parse }
                else if sess.opts.no_trans { cu_no_trans }
@@ -333,7 +333,11 @@ fn host_triple() -> str {
     // 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_HOST_TRIPLE");
-    ret ht != "" ? ht : fail "rustc built without CFG_HOST_TRIPLE";
+    ret if ht != "" {
+            ht
+        } else {
+            fail "rustc built without CFG_HOST_TRIPLE"
+        };
 }
 
 fn build_session_options(match: getopts::match,
@@ -353,6 +357,7 @@ fn build_session_options(match: getopts::match,
     if opt_present(match, "no-lint-ctypes") {
         lint_opts += [(lint::ctypes, false)];
     }
+    let monomorphize = opt_present(match, "monomorphize");
 
     let output_type =
         if parse_only || no_trans {
@@ -408,7 +413,6 @@ fn build_session_options(match: getopts::match,
     let addl_lib_search_paths = getopts::opt_strs(match, "L");
     let cfg = parse_cfgspecs(getopts::opt_strs(match, "cfg"));
     let test = opt_present(match, "test");
-    let do_gc = opt_present(match, "gc");
     let warn_unused_imports = opt_present(match, "warn-unused-imports");
     let sopts: @session::options =
         @{crate_type: crate_type,
@@ -430,8 +434,8 @@ fn build_session_options(match: getopts::match,
           test: test,
           parse_only: parse_only,
           no_trans: no_trans,
-          do_gc: do_gc,
           no_asm_comments: no_asm_comments,
+          monomorphize: monomorphize,
           warn_unused_imports: warn_unused_imports};
     ret sopts;
 }
@@ -491,6 +495,7 @@ fn opts() -> [getopts::opt] {
          optflag("time-passes"), optflag("time-llvm-passes"),
          optflag("no-verify"),
          optflag("no-lint-ctypes"),
+         optflag("monomorphize"),
          optmulti("cfg"), optflag("test"),
          optflag("lib"), optflag("bin"), optflag("static"), optflag("gc"),
          optflag("no-asm-comments"),
@@ -500,8 +505,8 @@ fn opts() -> [getopts::opt] {
 type output_filenames = @{out_filename: str, obj_filename:str};
 
 fn build_output_filenames(ifile: str,
-                          odir: option::t<str>,
-                          ofile: option::t<str>,
+                          odir: option<str>,
+                          ofile: option<str>,
                           sess: session)
         -> output_filenames {
     let obj_path = "";
@@ -604,6 +609,8 @@ fn test_switch_implies_cfg_test() {
         let match =
             alt getopts::getopts(["--test"], opts()) {
               ok(m) { m }
+              err(f) { fail "test_switch_implies_cfg_test: " +
+                       getopts::fail_str(f); }
             };
         let sessopts = build_session_options(match, diagnostic::emit);
         let sess = build_session(sessopts, "", diagnostic::emit);
@@ -618,6 +625,8 @@ fn test_switch_implies_cfg_test_unless_cfg_test() {
         let match =
             alt getopts::getopts(["--test", "--cfg=test"], opts()) {
               ok(m) { m }
+              err(f) { fail "test_switch_implies_cfg_test_unless_cfg_test: " +
+                       getopts::fail_str(f); }
             };
         let sessopts = build_session_options(match, diagnostic::emit);
         let sess = build_session(sessopts, "", diagnostic::emit);
index 12d10e8065378dd5ed5a9bc3573ef5e7b1e3948c..f0e535d36fdb3bfe6fe46e9e12a72f547a648948 100644 (file)
@@ -21,43 +21,52 @@ fn version(argv0: str) {
 }
 
 fn usage(argv0: str) {
-    io::stdout().write_str(#fmt["usage: %s [options] <input>\n", argv0] +
+    io::stdout().write_str(#fmt["Usage: %s [options] <input>\n", argv0] +
                                "
-options:
-
-    -h --help          display this message
-    -v --version       print version info and exit
-
-    -o <filename>      write output to <filename>
-    --out-dir <dir>    write output to compiler-chosen filename in <dir>
-    --lib              compile a library crate
-    --bin              compile an executable crate (default)
-    --static           use or produce static libraries
-    --pretty [type]    pretty-print the input instead of compiling
-    --ls               list the symbols defined by a crate file
-    -L <path>          add a directory to the library search path
-    --no-verify        suppress LLVM verification step (slight speedup)
-    --parse-only       parse only; do not compile, assemble, or link
-    --no-trans         run all passes except translation; no output
-    -g                 produce debug info
-    --opt-level <lvl>  optimize with possible levels 0-3
-    -O                 equivalent to --opt-level=2
-    -S                 compile only; do not assemble or link
-    --no-asm-comments  do not add comments into the assembly source
-    -c                 compile and assemble, but do not link
-    --emit-llvm        produce an LLVM bitcode file
-    --save-temps       write intermediate files in addition to normal output
-    --stats            gather and report various compilation statistics
-    --cfg <cfgspec>    configure the compilation environment
-    --time-passes      time the individual phases of the compiler
-    --time-llvm-passes time the individual phases of the LLVM backend
-    --sysroot <path>   override the system root
-    --target <triple>  target to compile for (default: host triple)
-    --test             build test harness
-    --gc               garbage collect shared data (experimental/temporary)
+Options:
+
+    --bin              Compile an executable crate (default)
+    -c                 Compile and assemble, but do not link
+    --cfg <cfgspec>    Configure the compilation environment
+    --emit-llvm        Produce an LLVM bitcode file
+    -g                 Produce debug info
+    --gc               Garbage collect shared data (experimental/temporary)
+    -h --help          Display this message
+    -L <path>          Add a directory to the library search path
+    --lib              Compile a library crate
+    --ls               List the symbols defined by a compiled library crate
+    --no-asm-comments  Do not add comments into the assembly source
+    --no-lint-ctypes   Suppress warnings for possibly incorrect ctype usage
+    --no-trans         Run all passes except translation; no output
+    --no-verify        Suppress LLVM verification step (slight speedup)
+                       (see http://llvm.org/docs/Passes.html for detail)
+    -O                 Equivalent to --opt-level=2
+    -o <filename>      Write output to <filename>
+    --opt-level <lvl>  Optimize with possible levels 0-3
+    --out-dir <dir>    Write output to compiler-chosen filename in <dir>
+    --parse-only       Parse only; do not compile, assemble, or link
+    --pretty [type]    Pretty-print the input instead of compiling;
+                       valid types are: normal (un-annotated source), 
+                       expanded (crates expanded), typed (crates expanded,
+                       with type annotations), or identified (fully
+                       parenthesized, AST nodes and blocks with IDs)
+    -S                 Compile only; do not assemble or link
+    --save-temps       Write intermediate files (.bc, .opt.bc, .o)
+                       in addition to normal output
+    --static           Use or produce static libraries or binaries
+    --stats            Print compilation statistics
+    --sysroot <path>   Override the system root
+    --test             Build a test harness
+    --target <triple>  Target cpu-manufacturer-kernel[-os] to compile for
+                       (default: host triple)
+                       (see http://sources.redhat.com/autobook/autobook/
+                       autobook_17.html for detail)
+
+    --time-passes      Time the individual phases of the compiler
+    --time-llvm-passes Time the individual phases of the LLVM backend
+    -v --version       Print version info and exit
     --warn-unused-imports
-                       warn about unnecessary imports
-    --no-lint-ctypes   suppress lint-style ctypes usage check
+                       Warn about unnecessary imports
 
 ");
 }
index b570744a6655f224ba5336d9ec2a6c461e17f161..36991e4e108d30942af7794b0eb74f20b6e91801 100644 (file)
@@ -40,14 +40,14 @@ enum crate_type { bin_crate, lib_crate, unknown_crate, }
      time_llvm_passes: bool,
      output_type: back::link::output_type,
      addl_lib_search_paths: [str],
-     maybe_sysroot: option::t<str>,
+     maybe_sysroot: option<str>,
      target_triple: str,
      cfg: ast::crate_cfg,
      test: bool,
      parse_only: bool,
      no_trans: bool,
-     do_gc: bool,
      no_asm_comments: bool,
+     monomorphize: bool,
      warn_unused_imports: bool};
 
 type crate_metadata = {name: str, data: [u8]};
@@ -58,7 +58,7 @@ enum crate_type { bin_crate, lib_crate, unknown_crate, }
                  parse_sess: parse_sess,
                  codemap: codemap::codemap,
                  // For a library crate, this is always none
-                 mutable main_fn: option::t<node_id>,
+                 mutable main_fn: option<(node_id, codemap::span)>,
                  span_diagnostic: diagnostic::span_handler,
                  filesearch: filesearch::filesearch,
                  mutable building_library: bool,
index 54960d653603c6d827c7ee7be86db919b520736a..e90fd0ecdfb13e67a8d8707a10238306649a01e8 100644 (file)
@@ -48,7 +48,7 @@ fn find_linkage_metas(attrs: [ast::attribute]) -> [@ast::meta_item] {
 fn find_attrs_by_name(attrs: [ast::attribute], name: ast::ident) ->
    [ast::attribute] {
     let filter = (
-        fn@(a: ast::attribute) -> option::t<ast::attribute> {
+        fn@(a: ast::attribute) -> option<ast::attribute> {
             if get_attr_name(a) == name {
                 option::some(a)
             } else { option::none }
@@ -67,7 +67,7 @@ fn get_attr_name(attr: ast::attribute) -> ast::ident {
 
 fn find_meta_items_by_name(metas: [@ast::meta_item], name: ast::ident) ->
    [@ast::meta_item] {
-    let filter = fn@(&&m: @ast::meta_item) -> option::t<@ast::meta_item> {
+    let filter = fn@(&&m: @ast::meta_item) -> option<@ast::meta_item> {
         if get_meta_item_name(m) == name {
             option::some(m)
         } else { option::none }
@@ -85,7 +85,7 @@ fn get_meta_item_name(meta: @ast::meta_item) -> ast::ident {
 
 // Gets the string value if the meta_item is a meta_name_value variant
 // containing a string, otherwise none
-fn get_meta_item_value_str(meta: @ast::meta_item) -> option::t<str> {
+fn get_meta_item_value_str(meta: @ast::meta_item) -> option<str> {
     alt meta.node {
       ast::meta_name_value(_, v) {
         alt v.node { ast::lit_str(s) { option::some(s) } _ { option::none } }
@@ -95,7 +95,7 @@ fn get_meta_item_value_str(meta: @ast::meta_item) -> option::t<str> {
 }
 
 fn get_meta_item_value_str_by_name(attrs: [ast::attribute], name: ast::ident)
-    -> option::t<str> {
+    -> option<str> {
     let mattrs = find_attrs_by_name(attrs, name);
     if vec::len(mattrs) > 0u {
         ret get_meta_item_value_str(attr_meta(mattrs[0]));
@@ -103,7 +103,7 @@ fn get_meta_item_value_str_by_name(attrs: [ast::attribute], name: ast::ident)
     ret option::none;
 }
 
-fn get_meta_item_list(meta: @ast::meta_item) -> option::t<[@ast::meta_item]> {
+fn get_meta_item_list(meta: @ast::meta_item) -> option<[@ast::meta_item]> {
     alt meta.node {
       ast::meta_list(_, l) { option::some(l) }
       _ { option::none }
@@ -184,7 +184,7 @@ fn key(m: @ast::meta_item) -> ast::ident {
 fn remove_meta_items_by_name(items: [@ast::meta_item], name: str) ->
    [@ast::meta_item] {
 
-    let filter = fn@(&&item: @ast::meta_item) -> option::t<@ast::meta_item> {
+    let filter = fn@(&&item: @ast::meta_item) -> option<@ast::meta_item> {
         if get_meta_item_name(item) != name {
             option::some(item)
         } else { option::none }
index 684564052afc188545f3d4eb41e049221e8b9792..5e5723680d9cfdfc54b0a2914afd00ef85cc0e69 100644 (file)
@@ -37,7 +37,7 @@ fn strip_items(crate: @ast::crate, in_cfg: in_cfg_pred)
 }
 
 fn filter_item(cx: ctxt, &&item: @ast::item) ->
-   option::t<@ast::item> {
+   option<@ast::item> {
     if item_in_cfg(cx, item) { option::some(item) } else { option::none }
 }
 
@@ -50,7 +50,7 @@ fn fold_mod(cx: ctxt, m: ast::_mod, fld: fold::ast_fold) ->
 }
 
 fn filter_native_item(cx: ctxt, &&item: @ast::native_item) ->
-   option::t<@ast::native_item> {
+   option<@ast::native_item> {
     if native_item_in_cfg(cx, item) {
         option::some(item)
     } else { option::none }
@@ -65,7 +65,7 @@ fn fold_native_mod(cx: ctxt, nm: ast::native_mod,
 }
 
 fn filter_stmt(cx: ctxt, &&stmt: @ast::stmt) ->
-   option::t<@ast::stmt> {
+   option<@ast::stmt> {
     alt stmt.node {
       ast::stmt_decl(decl, _) {
         alt decl.node {
index 05eedf09bd712b45b5b76651d9f9d0b9d7265482..5d74165c4b6d27f18faf2244d7eb43f6eecacd8b 100644 (file)
@@ -67,7 +67,7 @@ fn fold_mod(_cx: test_ctxt, m: ast::_mod, fld: fold::ast_fold) -> ast::_mod {
     // the one we're going to add.  FIXME: This is sloppy. Instead we should
     // have some mechanism to indicate to the translation pass which function
     // we want to be main.
-    fn nomain(&&item: @ast::item) -> option::t<@ast::item> {
+    fn nomain(&&item: @ast::item) -> option<@ast::item> {
         alt item.node {
           ast::item_fn(_, _, _) {
             if item.ident == "main" {
@@ -244,7 +244,7 @@ fn mk_path(cx: test_ctxt, path: [ast::ident]) -> [ast::ident] {
           _ { false }
         }
     };
-    (is_std ? [] : ["std"]) + path
+    (if is_std { [] } else { ["std"] }) + path
 }
 
 // The ast::ty of [std::test::test_desc]
@@ -382,7 +382,7 @@ fn mk_main(cx: test_ctxt) -> @ast::item {
     let args_ty: ast::ty = nospan(ast::ty_vec(args_mt));
 
     let args_arg: ast::arg =
-        {mode: ast::by_val,
+        {mode: ast::expl(ast::by_val),
          ty: @args_ty,
          ident: "args",
          id: cx.sess.next_node_id()};
index 1ef6ccca41b79259f0d2107d8aeafd38aded3394..5515d740089997cd22a1e739db8501dc9f73bd9d 100644 (file)
 import core::{vec, str, option};
 import str::sbuf;
 
-import llvm::{TypeRef, MemoryBufferRef,
-              PassManagerRef, TargetDataRef,
-              ObjectFileRef, SectionIteratorRef};
 import ctypes::{c_int, c_uint, unsigned, longlong, ulonglong};
 
-type Long = i32;
-type Bool = int;
+type Opcode = u32;
+type Bool = unsigned;
+const True: Bool = 1u32;
+const False: Bool = 0u32;
 
+// Consts for the LLVM CallConv type, pre-cast to uint.
 
-const True: Bool = 1;
-const False: Bool = 0;
+enum CallConv {
+    CCallConv = 0,
+    FastCallConv = 8,
+    ColdCallConv = 9,
+    X86StdcallCallConv = 64,
+    X86FastcallCallConv = 65,
+}
 
-// Consts for the LLVM CallConv type, pre-cast to uint.
-// FIXME: figure out a way to merge these with the native
-// typedef and/or a enum type in the native module below.
-
-const LLVMCCallConv: uint = 0u;
-const LLVMFastCallConv: uint = 8u;
-const LLVMColdCallConv: uint = 9u;
-const LLVMX86StdcallCallConv: uint = 64u;
-const LLVMX86FastcallCallConv: uint = 65u;
-
-const LLVMDefaultVisibility: uint = 0u;
-const LLVMHiddenVisibility: uint = 1u;
-const LLVMProtectedVisibility: uint = 2u;
-
-const LLVMExternalLinkage: uint = 0u;
-const LLVMAvailableExternallyLinkage: uint = 1u;
-const LLVMLinkOnceAnyLinkage: uint = 2u;
-const LLVMLinkOnceODRLinkage: uint = 3u;
-const LLVMWeakAnyLinkage: uint = 4u;
-const LLVMWeakODRLinkage: uint = 5u;
-const LLVMAppendingLinkage: uint = 6u;
-const LLVMInternalLinkage: uint = 7u;
-const LLVMPrivateLinkage: uint = 8u;
-const LLVMDLLImportLinkage: uint = 9u;
-const LLVMDLLExportLinkage: uint = 10u;
-const LLVMExternalWeakLinkage: uint = 11u;
-const LLVMGhostLinkage: uint = 12u;
-const LLVMCommonLinkage: uint = 13u;
-const LLVMLinkerPrivateLinkage: uint = 14u;
-const LLVMLinkerPrivateWeakLinkage: uint = 15u;
-
-const LLVMZExtAttribute: uint = 1u;
-const LLVMSExtAttribute: uint = 2u;
-const LLVMNoReturnAttribute: uint = 4u;
-const LLVMInRegAttribute: uint = 8u;
-const LLVMStructRetAttribute: uint = 16u;
-const LLVMNoUnwindAttribute: uint = 32u;
-const LLVMNoAliasAttribute: uint = 64u;
-const LLVMByValAttribute: uint = 128u;
-const LLVMNestAttribute: uint = 256u;
-const LLVMReadNoneAttribute: uint = 512u;
-const LLVMReadOnlyAttribute: uint = 1024u;
-const LLVMNoInlineAttribute: uint = 2048u;
-const LLVMAlwaysInlineAttribute: uint = 4096u;
-const LLVMOptimizeForSizeAttribute: uint = 8192u;
-const LLVMStackProtectAttribute: uint = 16384u;
-const LLVMStackProtectReqAttribute: uint = 32768u;
-const LLVMAlignmentAttribute: uint = 2031616u;
-// 31 << 16
-const LLVMNoCaptureAttribute: uint = 2097152u;
-const LLVMNoRedZoneAttribute: uint = 4194304u;
-const LLVMNoImplicitFloatAttribute: uint = 8388608u;
-const LLVMNakedAttribute: uint = 16777216u;
-const LLVMInlineHintAttribute: uint = 33554432u;
-const LLVMStackAttribute: uint = 469762048u;
-// 7 << 26
-const LLVMUWTableAttribute: uint = 1073741824u;
-// 1 << 30
+enum Visibility {
+    LLVMDefaultVisibility = 0,
+    HiddenVisibility = 1,
+    ProtectedVisibility = 2,
+}
+
+enum Linkage {
+    ExternalLinkage = 0,
+    AvailableExternallyLinkage = 1,
+    LinkOnceAnyLinkage = 2,
+    LinkOnceODRLinkage = 3,
+    WeakAnyLinkage = 4,
+    WeakODRLinkage = 5,
+    AppendingLinkage = 6,
+    InternalLinkage = 7,
+    PrivateLinkage = 8,
+    DLLImportLinkage = 9,
+    DLLExportLinkage = 10,
+    ExternalWeakLinkage = 11,
+    GhostLinkage = 12,
+    CommonLinkage = 13,
+    LinkerPrivateLinkage = 14,
+    LinkerPrivateWeakLinkage = 15,
+    LinkerPrivateWeakDefAutoLinkage = 16,
+}
 
+enum Attribute {
+    ZExtAttribute = 1,
+    SExtAttribute = 2,
+    NoReturnAttribute = 4,
+    InRegAttribute = 8,
+    StructRetAttribute = 16,
+    NoUnwindAttribute = 32,
+    NoAliasAttribute = 64,
+    ByValAttribute = 128,
+    NestAttribute = 256,
+    ReadNoneAttribute = 512,
+    ReadOnlyAttribute = 1024,
+    NoInlineAttribute = 2048,
+    AlwaysInlineAttribute = 4096,
+    OptimizeForSizeAttribute = 8192,
+    StackProtectAttribute = 16384,
+    StackProtectReqAttribute = 32768,
+    // 31 << 16
+    AlignmentAttribute = 2031616,
+    NoCaptureAttribute = 2097152,
+    NoRedZoneAttribute = 4194304,
+    NoImplicitFloatAttribute = 8388608,
+    NakedAttribute = 16777216,
+    InlineHintAttribute = 33554432,
+    // 7 << 26
+    StackAttribute = 469762048,
+    ReturnsTwiceAttribute = 536870912,
+    // 1 << 30
+    UWTableAttribute = 1073741824,
+    NonLazyBindAttribute = 2147483648,
+}
 
 // Consts for the LLVM IntPredicate type, pre-cast to uint.
 // FIXME: as above.
 
-
-const LLVMIntEQ: uint = 32u;
-const LLVMIntNE: uint = 33u;
-const LLVMIntUGT: uint = 34u;
-const LLVMIntUGE: uint = 35u;
-const LLVMIntULT: uint = 36u;
-const LLVMIntULE: uint = 37u;
-const LLVMIntSGT: uint = 38u;
-const LLVMIntSGE: uint = 39u;
-const LLVMIntSLT: uint = 40u;
-const LLVMIntSLE: uint = 41u;
-
+enum IntPredicate {
+    IntEQ = 32,
+    IntNE = 33,
+    IntUGT = 34,
+    IntUGE = 35,
+    IntULT = 36,
+    IntULE = 37,
+    IntSGT = 38,
+    IntSGE = 39,
+    IntSLT = 40,
+    IntSLE = 41,
+}
 
 // Consts for the LLVM RealPredicate type, pre-case to uint.
 // FIXME: as above.
 
-const LLVMRealOEQ: uint = 1u;
-const LLVMRealOGT: uint = 2u;
-const LLVMRealOGE: uint = 3u;
-const LLVMRealOLT: uint = 4u;
-const LLVMRealOLE: uint = 5u;
-const LLVMRealONE: uint = 6u;
-
-const LLVMRealORD: uint = 7u;
-const LLVMRealUNO: uint = 8u;
-const LLVMRealUEQ: uint = 9u;
-const LLVMRealUGT: uint = 10u;
-const LLVMRealUGE: uint = 11u;
-const LLVMRealULT: uint = 12u;
-const LLVMRealULE: uint = 13u;
-const LLVMRealUNE: uint = 14u;
+enum RealPredicate {
+    RealOEQ = 1,
+    RealOGT = 2,
+    RealOGE = 3,
+    RealOLT = 4,
+    RealOLE = 5,
+    RealONE = 6,
+    RealORD = 7,
+    RealUNO = 8,
+    RealUEQ = 9,
+    RealUGT = 10,
+    RealUGE = 11,
+    RealULT = 12,
+    RealULE = 13,
+    RealUNE = 14,
+}
+
+// Opaque pointer types
+enum Module_opaque {}
+type ModuleRef = *Module_opaque;
+enum Context_opaque {}
+type ContextRef = *Context_opaque;
+enum Type_opaque {}
+type TypeRef = *Type_opaque;
+enum Value_opaque {}
+type ValueRef = *Value_opaque;
+enum BasicBlock_opaque {}
+type BasicBlockRef = *BasicBlock_opaque;
+enum Builder_opaque {}
+type BuilderRef = *Builder_opaque;
+enum MemoryBuffer_opaque {}
+type MemoryBufferRef = *MemoryBuffer_opaque;
+enum PassManager_opaque {}
+type PassManagerRef = *PassManager_opaque;
+enum PassManagerBuilder_opaque {}
+type PassManagerBuilderRef = *PassManagerBuilder_opaque;
+enum Use_opaque {}
+type UseRef = *Use_opaque;
+enum TargetData_opaque {}
+type TargetDataRef = *TargetData_opaque;
+enum ObjectFile_opaque {}
+type ObjectFileRef = *ObjectFile_opaque;
+enum SectionIterator_opaque {}
+type SectionIteratorRef = *SectionIterator_opaque;
 
 #[link_args = "-Lrustllvm"]
 #[link_name = "rustllvm"]
 #[abi = "cdecl"]
 native mod llvm {
-
-    type ModuleRef;
-    type ContextRef;
-    type TypeRef;
-    type TypeHandleRef;
-    type ValueRef;
-    type BasicBlockRef;
-    type BuilderRef;
-    type ModuleProviderRef;
-    type MemoryBufferRef;
-    type PassManagerRef;
-    type PassManagerBuilderRef;
-    type UseRef;
-    type TargetDataRef;
-
-    /* FIXME: These are enums in the C header. Represent them how, in rust? */
-    type Linkage;
-    type Attribute;
-    type Visibility;
-    type CallConv;
-    type IntPredicate;
-    type RealPredicate;
-    type Opcode;
-
     /* Create and destroy contexts. */
     fn LLVMContextCreate() -> ContextRef;
     fn LLVMGetGlobalContext() -> ContextRef;
@@ -419,12 +427,12 @@ fn LLVMConstInlineAsm(Ty: TypeRef, AsmString: sbuf, Constraints: sbuf,
     /* Operations on global variables, functions, and aliases (globals) */
     fn LLVMGetGlobalParent(Global: ValueRef) -> ModuleRef;
     fn LLVMIsDeclaration(Global: ValueRef) -> Bool;
-    fn LLVMGetLinkage(Global: ValueRef) -> Linkage;
-    fn LLVMSetLinkage(Global: ValueRef, Link: Linkage);
+    fn LLVMGetLinkage(Global: ValueRef) -> unsigned;
+    fn LLVMSetLinkage(Global: ValueRef, Link: unsigned);
     fn LLVMGetSection(Global: ValueRef) -> sbuf;
     fn LLVMSetSection(Global: ValueRef, Section: sbuf);
-    fn LLVMGetVisibility(Global: ValueRef) -> Visibility;
-    fn LLVMSetVisibility(Global: ValueRef, Viz: Visibility);
+    fn LLVMGetVisibility(Global: ValueRef) -> unsigned;
+    fn LLVMSetVisibility(Global: ValueRef, Viz: unsigned);
     fn LLVMGetAlignment(Global: ValueRef) -> unsigned;
     fn LLVMSetAlignment(Global: ValueRef, Bytes: unsigned);
 
@@ -466,9 +474,9 @@ fn LLVMGetOrInsertFunction(M: ModuleRef, Name: sbuf, FunctionTy: TypeRef)
     fn LLVMSetFunctionCallConv(Fn: ValueRef, CC: unsigned);
     fn LLVMGetGC(Fn: ValueRef) -> sbuf;
     fn LLVMSetGC(Fn: ValueRef, Name: sbuf);
-    fn LLVMAddFunctionAttr(Fn: ValueRef, PA: Attribute, HighPA: unsigned);
-    fn LLVMGetFunctionAttr(Fn: ValueRef) -> Attribute;
-    fn LLVMRemoveFunctionAttr(Fn: ValueRef, PA: Attribute, HighPA: unsigned);
+    fn LLVMAddFunctionAttr(Fn: ValueRef, PA: unsigned, HighPA: unsigned);
+    fn LLVMGetFunctionAttr(Fn: ValueRef) -> unsigned;
+    fn LLVMRemoveFunctionAttr(Fn: ValueRef, PA: unsigned, HighPA: unsigned);
 
     /* Operations on parameters */
     fn LLVMCountParams(Fn: ValueRef) -> unsigned;
@@ -479,9 +487,9 @@ fn LLVMGetOrInsertFunction(M: ModuleRef, Name: sbuf, FunctionTy: TypeRef)
     fn LLVMGetLastParam(Fn: ValueRef) -> ValueRef;
     fn LLVMGetNextParam(Arg: ValueRef) -> ValueRef;
     fn LLVMGetPreviousParam(Arg: ValueRef) -> ValueRef;
-    fn LLVMAddAttribute(Arg: ValueRef, PA: Attribute);
-    fn LLVMRemoveAttribute(Arg: ValueRef, PA: Attribute);
-    fn LLVMGetAttribute(Arg: ValueRef) -> Attribute;
+    fn LLVMAddAttribute(Arg: ValueRef, PA: unsigned);
+    fn LLVMRemoveAttribute(Arg: ValueRef, PA: unsigned);
+    fn LLVMGetAttribute(Arg: ValueRef) -> unsigned;
     fn LLVMSetParamAlignment(Arg: ValueRef, align: unsigned);
 
     /* Operations on basic blocks */
@@ -517,9 +525,9 @@ fn LLVMInsertBasicBlock(InsertBeforeBB: BasicBlockRef, Name: sbuf) ->
     /* Operations on call sites */
     fn LLVMSetInstructionCallConv(Instr: ValueRef, CC: unsigned);
     fn LLVMGetInstructionCallConv(Instr: ValueRef) -> unsigned;
-    fn LLVMAddInstrAttribute(Instr: ValueRef, index: unsigned, IA: Attribute);
+    fn LLVMAddInstrAttribute(Instr: ValueRef, index: unsigned, IA: unsigned);
     fn LLVMRemoveInstrAttribute(Instr: ValueRef, index: unsigned,
-                                IA: Attribute);
+                                IA: unsigned);
     fn LLVMSetInstrParamAlignment(Instr: ValueRef, index: unsigned,
                                   align: unsigned);
 
@@ -833,9 +841,6 @@ fn LLVMPassManagerBuilderPopulateFunctionPassManager
 
     /* Stuff that's in rustllvm/ because it's not upstream yet. */
 
-    type ObjectFileRef;
-    type SectionIteratorRef;
-
     /** Opens an object file. */
     fn LLVMCreateObjectFile(MemBuf: MemoryBufferRef) -> ObjectFileRef;
     /** Closes an object file. */
@@ -904,6 +909,16 @@ fn LLVMConstNamedStruct(S: TypeRef, ConstantVals: *ValueRef,
     fn LLVMLinkModules(Dest: ModuleRef, Src: ModuleRef) -> Bool;
 }
 
+fn SetInstructionCallConv(Instr: ValueRef, CC: CallConv) {
+    llvm::LLVMSetInstructionCallConv(Instr, CC as unsigned);
+}
+fn SetFunctionCallConv(Fn: ValueRef, CC: CallConv) {
+    llvm::LLVMSetFunctionCallConv(Fn, CC as unsigned);
+}
+fn SetLinkage(Global: ValueRef, Link: Linkage) {
+    llvm::LLVMSetLinkage(Global, Link as unsigned);
+}
+
 /* Memory-managed object interface to type handles. */
 
 type type_names = @{type_names: std::map::hashmap<TypeRef, str>,
@@ -914,11 +929,11 @@ fn associate_type(tn: type_names, s: str, t: TypeRef) {
     assert tn.named_types.insert(s, t);
 }
 
-fn type_has_name(tn: type_names, t: TypeRef) -> option::t<str> {
+fn type_has_name(tn: type_names, t: TypeRef) -> option<str> {
     ret tn.type_names.find(t);
 }
 
-fn name_has_type(tn: type_names, s: str) -> option::t<TypeRef> {
+fn name_has_type(tn: type_names, s: str) -> option<TypeRef> {
     ret tn.named_types.find(s);
 }
 
@@ -1069,7 +1084,7 @@ fn mk_pass_manager() -> pass_manager {
 
 type object_file = {llof: ObjectFileRef, dtor: @object_file_res};
 
-fn mk_object_file(llmb: MemoryBufferRef) -> option::t<object_file> {
+fn mk_object_file(llmb: MemoryBufferRef) -> option<object_file> {
     let llof = llvm::LLVMCreateObjectFile(llmb);
     if llof as int == 0 { ret option::none::<object_file>; }
     ret option::some({llof: llof, dtor: @object_file_res(llof)});
index e4e39730350d07f87a0eb6ad81cf5f5f885f6c89..4929b02b7af477faf8bb4fe858d65aada18a22d8 100644 (file)
@@ -137,7 +137,7 @@ fn default_native_lib_naming(sess: session::session, static: bool) ->
 
 fn find_library_crate(sess: session::session, ident: ast::ident,
                       metas: [@ast::meta_item])
-   -> option::t<{ident: str, data: @[u8]}> {
+   -> option<{ident: str, data: @[u8]}> {
 
     attr::require_unique_names(sess, metas);
     let metas = metas;
@@ -173,7 +173,7 @@ fn find_library_crate_aux(sess: session::session,
                           crate_name: str,
                           metas: [@ast::meta_item],
                           filesearch: filesearch::filesearch) ->
-   option::t<{ident: str, data: @[u8]}> {
+   option<{ident: str, data: @[u8]}> {
     let prefix: str = nn.prefix + crate_name + "-";
     let suffix: str = nn.suffix;
 
@@ -206,7 +206,7 @@ fn find_library_crate_aux(sess: session::session,
 }
 
 fn get_metadata_section(sess: session::session,
-                        filename: str) -> option::t<@[u8]> unsafe {
+                        filename: str) -> option<@[u8]> unsafe {
     let mb = str::as_buf(filename, {|buf|
         llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf)
                                    });
index 1f1593ae742d2356e299b589241b5d7dc47827c7..941fedb0c205223258123a979d2df3112122d05c 100644 (file)
@@ -63,7 +63,7 @@ fn get_enum_variants(tcx: ty::ctxt, def: ast::def_id) -> [ty::variant_info] {
 }
 
 fn get_impls_for_mod(cstore: cstore::cstore, def: ast::def_id,
-                     name: option::t<ast::ident>)
+                     name: option<ast::ident>)
     -> @[@middle::resolve::_impl] {
     let cdata = cstore::get_crate_data(cstore, def.crate);
     decoder::get_impls_for_mod(cdata, def.node, name)
@@ -82,7 +82,7 @@ fn get_type(tcx: ty::ctxt, def: ast::def_id) -> ty::ty_param_bounds_and_ty {
 }
 
 fn get_impl_iface(tcx: ty::ctxt, def: ast::def_id)
-    -> option::t<ty::t> {
+    -> option<ty::t> {
     let cstore = tcx.sess.cstore;
     let cdata = cstore::get_crate_data(cstore, def.crate);
     decoder::get_impl_iface(cdata, def.node, tcx)
index 426263d654a7adf31cf28f3e1b49f54805106acd..b26eb52eaf5254e3b758fb5dcf9cfcbec110fd22 100644 (file)
@@ -3,6 +3,7 @@
 import std::{ebml, map, io};
 import io::writer_util;
 import syntax::{ast, ast_util};
+import driver::session::session;
 import front::attr;
 import middle::ty;
 import common::*;
@@ -54,7 +55,7 @@ fn lookup_hash(d: ebml::doc, eq_fn: fn@([u8]) -> bool, hash: uint) ->
     ret result;
 }
 
-fn maybe_find_item(item_id: int, items: ebml::doc) -> option::t<ebml::doc> {
+fn maybe_find_item(item_id: int, items: ebml::doc) -> option<ebml::doc> {
     fn eq_item(bytes: [u8], item_id: int) -> bool {
         ret ebml::be_uint_from_bytes(@bytes, 0u, 4u) as int == item_id;
     }
@@ -91,7 +92,7 @@ fn variant_enum_id(d: ebml::doc) -> ast::def_id {
     ret parse_def_id(ebml::doc_data(tagdoc));
 }
 
-fn variant_disr_val(d: ebml::doc) -> option::t<int> {
+fn variant_disr_val(d: ebml::doc) -> option<int> {
     alt ebml::maybe_get_doc(d, tag_disr_val) {
       some(val_doc) {
         let val_buf = ebml::doc_data(val_doc);
@@ -117,7 +118,7 @@ fn item_type(item: ebml::doc, tcx: ty::ctxt, cdata: cmd) -> ty::t {
 }
 
 fn item_impl_iface(item: ebml::doc, tcx: ty::ctxt, cdata: cmd)
-    -> option::t<ty::t> {
+    -> option<ty::t> {
     let result = none;
     ebml::tagged_docs(item, tag_impl_iface) {|ity|
         let t = parse_ty_data(ity.data, cdata.cnum, ity.start, tcx, {|did|
@@ -128,15 +129,14 @@ fn item_impl_iface(item: ebml::doc, tcx: ty::ctxt, cdata: cmd)
     result
 }
 
-fn item_ty_param_bounds(item: ebml::doc, tcx: ty::ctxt, cdata: cmd,
-                        skip: bool) -> @[ty::param_bounds] {
-    let bounds = [], skip = skip;
+fn item_ty_param_bounds(item: ebml::doc, tcx: ty::ctxt, cdata: cmd)
+    -> @[ty::param_bounds] {
+    let bounds = [];
     ebml::tagged_docs(item, tag_items_data_item_ty_param_bounds) {|p|
         let bd = parse_bounds_data(p.data, p.start, cdata.cnum, tcx, {|did|
             translate_def_id(cdata, did)
         });
-        if skip { skip = false; }
-        else { bounds += [bd]; }
+        bounds += [bd];
     }
     @bounds
 }
@@ -198,7 +198,6 @@ fn lookup_def(cnum: ast::crate_num, data: @[u8], did_: ast::def_id) ->
           'f' { ast::def_fn(did, ast::impure_fn) }
           'p' { ast::def_fn(did, ast::pure_fn) }
           'y' { ast::def_ty(did) }
-          'T' { ast::def_native_ty(did) }
           't' { ast::def_ty(did) }
           'm' { ast::def_mod(did) }
           'n' { ast::def_native_mod(did) }
@@ -216,9 +215,8 @@ fn get_type(cdata: cmd, id: ast::node_id, tcx: ty::ctxt)
     -> ty::ty_param_bounds_and_ty {
     let item = lookup_item(id, cdata.data);
     let t = item_type(item, tcx, cdata);
-    let family = item_family(item);
-    let tp_bounds = if family_has_type_params(family) {
-        item_ty_param_bounds(item, tcx, cdata, family == ('I' as u8))
+    let tp_bounds = if family_has_type_params(item_family(item)) {
+        item_ty_param_bounds(item, tcx, cdata)
     } else { @[] };
     ret {bounds: tp_bounds, ty: t};
 }
@@ -228,7 +226,7 @@ fn get_type_param_count(data: @[u8], id: ast::node_id) -> uint {
 }
 
 fn get_impl_iface(cdata: cmd, id: ast::node_id, tcx: ty::ctxt)
-    -> option::t<ty::t> {
+    -> option<ty::t> {
     item_impl_iface(lookup_item(id, cdata.data), tcx, cdata)
 }
 
@@ -280,7 +278,7 @@ fn item_impl_methods(cdata: cmd, item: ebml::doc, base_tps: uint)
 }
 
 fn get_impls_for_mod(cdata: cmd, m_id: ast::node_id,
-                     name: option::t<ast::ident>)
+                     name: option<ast::ident>)
     -> @[@middle::resolve::_impl] {
     let data = cdata.data;
     let mod_item = lookup_item(m_id, data), result = [];
@@ -301,10 +299,12 @@ fn get_iface_methods(cdata: cmd, id: ast::node_id, tcx: ty::ctxt)
     let data = cdata.data;
     let item = lookup_item(id, data), result = [];
     ebml::tagged_docs(item, tag_item_method) {|mth|
-        let bounds = item_ty_param_bounds(mth, tcx, cdata, false);
+        let bounds = item_ty_param_bounds(mth, tcx, cdata);
         let name = item_name(mth);
         let ty = doc_type(mth, tcx, cdata);
-        let fty = alt ty::struct(tcx, ty) { ty::ty_fn(f) { f } };
+        let fty = alt ty::struct(tcx, ty) { ty::ty_fn(f) { f }
+          _ { tcx.sess.bug("get_iface_methods: id has non-function type");
+        } };
         result += [{ident: name, tps: bounds, fty: fty}];
     }
     @result
index e74a2d62ced46c2500aed3175e6413d350c0cbed..7cc2d56f1ac72d76aa68b7c9c93bb3019f35d28b 100644 (file)
@@ -8,8 +8,9 @@
 import common::*;
 import middle::trans::common::crate_ctxt;
 import middle::ty;
-import middle::ty::node_id_to_monotype;
+import middle::ty::node_id_to_type;
 import front::attr;
+import driver::session::session;
 
 export encode_metadata;
 export encoded_ty;
@@ -118,6 +119,9 @@ fn encode_module_item_paths(ebml_w: ebml::writer, module: _mod, path: [str],
             encode_def_id(ebml_w, local_def(it.id));
             ebml::end_tag(ebml_w);
           }
+          item_class(_,_,_,_) {
+              fail "encode: implement item_class";
+          }
           item_enum(variants, tps) {
             add_to_index(ebml_w, path, index, it.ident);
             ebml::start_tag(ebml_w, tag_paths_data_item);
@@ -243,7 +247,7 @@ fn encode_enum_variant_info(ecx: @encode_ctxt, ebml_w: ebml::writer,
         encode_name(ebml_w, variant.node.name);
         encode_enum_id(ebml_w, local_def(id));
         encode_type(ecx, ebml_w,
-                    node_id_to_monotype(ecx.ccx.tcx, variant.node.id));
+                    node_id_to_type(ecx.ccx.tcx, variant.node.id));
         if vec::len::<variant_arg>(variant.node.args) > 0u {
             encode_symbol(ecx, ebml_w, variant.node.id);
         }
@@ -275,6 +279,8 @@ fn encode_info_for_mod(ecx: @encode_ctxt, ebml_w: ebml::writer, md: _mod,
             }
         }
       }
+      _ { ecx.ccx.tcx.sess.bug("encode_info_for_mod: \
+             undocumented invariant"); }
     }
     ebml::end_tag(ebml_w);
 }
@@ -287,7 +293,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
         ebml::start_tag(ebml_w, tag_items_data_item);
         encode_def_id(ebml_w, local_def(item.id));
         encode_family(ebml_w, 'c' as u8);
-        encode_type(ecx, ebml_w, node_id_to_monotype(tcx, item.id));
+        encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
         encode_symbol(ecx, ebml_w, item.id);
         ebml::end_tag(ebml_w);
       }
@@ -301,7 +307,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
                         impure_fn { 'f' }
                       } as u8);
         encode_type_param_bounds(ebml_w, ecx, tps);
-        encode_type(ecx, ebml_w, node_id_to_monotype(tcx, item.id));
+        encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
         encode_symbol(ecx, ebml_w, item.id);
         ebml::end_tag(ebml_w);
       }
@@ -320,7 +326,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
         encode_def_id(ebml_w, local_def(item.id));
         encode_family(ebml_w, 'y' as u8);
         encode_type_param_bounds(ebml_w, ecx, tps);
-        encode_type(ecx, ebml_w, node_id_to_monotype(tcx, item.id));
+        encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
         encode_name(ebml_w, item.ident);
         ebml::end_tag(ebml_w);
       }
@@ -329,7 +335,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
         encode_def_id(ebml_w, local_def(item.id));
         encode_family(ebml_w, 't' as u8);
         encode_type_param_bounds(ebml_w, ecx, tps);
-        encode_type(ecx, ebml_w, node_id_to_monotype(tcx, item.id));
+        encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
         encode_name(ebml_w, item.ident);
         for v: variant in variants {
             encode_variant_id(ebml_w, local_def(v.node.id));
@@ -337,8 +343,11 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
         ebml::end_tag(ebml_w);
         encode_enum_variant_info(ecx, ebml_w, item.id, variants, index, tps);
       }
+      item_class(_,_,_,_) {
+          fail "encode: implement item_class";
+      }
       item_res(_, tps, _, _, ctor_id) {
-        let fn_ty = node_id_to_monotype(tcx, ctor_id);
+        let fn_ty = node_id_to_type(tcx, ctor_id);
 
         ebml::start_tag(ebml_w, tag_items_data_item);
         encode_def_id(ebml_w, local_def(ctor_id));
@@ -363,7 +372,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
         encode_def_id(ebml_w, local_def(item.id));
         encode_family(ebml_w, 'i' as u8);
         encode_type_param_bounds(ebml_w, ecx, tps);
-        encode_type(ecx, ebml_w, node_id_to_monotype(tcx, item.id));
+        encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
         encode_name(ebml_w, item.ident);
         for m in methods {
             ebml::start_tag(ebml_w, tag_item_method);
@@ -389,7 +398,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
             encode_family(ebml_w, 'f' as u8);
             encode_type_param_bounds(ebml_w, ecx, tps + m.tps);
             encode_type(ecx, ebml_w,
-                        node_id_to_monotype(tcx, m.id));
+                        node_id_to_type(tcx, m.id));
             encode_name(ebml_w, m.ident);
             encode_symbol(ecx, ebml_w, m.id);
             ebml::end_tag(ebml_w);
@@ -400,7 +409,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
         encode_def_id(ebml_w, local_def(item.id));
         encode_family(ebml_w, 'I' as u8);
         encode_type_param_bounds(ebml_w, ecx, tps);
-        encode_type(ecx, ebml_w, node_id_to_monotype(tcx, item.id));
+        encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
         encode_name(ebml_w, item.ident);
         let i = 0u;
         for mty in *ty::iface_methods(tcx, local_def(item.id)) {
@@ -420,12 +429,6 @@ fn encode_info_for_native_item(ecx: @encode_ctxt, ebml_w: ebml::writer,
                                nitem: @native_item) {
     ebml::start_tag(ebml_w, tag_items_data_item);
     alt nitem.node {
-      native_item_ty {
-        encode_def_id(ebml_w, local_def(nitem.id));
-        encode_family(ebml_w, 'T' as u8);
-        encode_type(ecx, ebml_w,
-                    ty::mk_native(ecx.ccx.tcx, local_def(nitem.id)));
-      }
       native_item_fn(fn_decl, tps) {
         let letter = alt fn_decl.purity {
           unsafe_fn { 'u' }
@@ -435,7 +438,7 @@ fn encode_info_for_native_item(ecx: @encode_ctxt, ebml_w: ebml::writer,
         encode_def_id(ebml_w, local_def(nitem.id));
         encode_family(ebml_w, letter);
         encode_type_param_bounds(ebml_w, ecx, tps);
-        encode_type(ecx, ebml_w, node_id_to_monotype(ecx.ccx.tcx, nitem.id));
+        encode_type(ecx, ebml_w, node_id_to_type(ecx.ccx.tcx, nitem.id));
         encode_symbol(ecx, ebml_w, nitem.id);
       }
     }
@@ -450,11 +453,11 @@ fn encode_info_for_items(ecx: @encode_ctxt, ebml_w: ebml::writer,
     encode_info_for_mod(ecx, ebml_w, crate_mod, crate_node_id, "");
     ecx.ccx.ast_map.items {|key, val|
         alt val {
-          middle::ast_map::node_item(i) {
+          middle::ast_map::node_item(i, _) {
             index += [{val: key, pos: ebml_w.writer.tell()}];
             encode_info_for_item(ecx, ebml_w, i, index);
           }
-          middle::ast_map::node_native_item(i) {
+          middle::ast_map::node_native_item(i, _) {
             index += [{val: key, pos: ebml_w.writer.tell()}];
             encode_info_for_native_item(ecx, ebml_w, i);
           }
index b7adcfadf12d54a1e37647fd78ff56e1d60dccc9..dc7496dddb350f7deda30f7f0c9a4c63a3b82e89 100644 (file)
@@ -255,7 +255,6 @@ fn parse_ty(st: @pstate, conv: conv_did) -> ty::t {
         ret ty::mk_res(st.tcx, def, inner, params);
       }
       'X' { ret ty::mk_var(st.tcx, parse_int(st)); }
-      'E' { let def = parse_def(st, conv); ret ty::mk_native(st.tcx, def); }
       'Y' { ret ty::mk_type(st.tcx); }
       'y' { ret ty::mk_send_type(st.tcx); }
       'C' {
@@ -354,7 +353,7 @@ fn parse_ty_fn(st: @pstate, conv: conv_did) -> ty::fn_ty {
           '#' { ast::by_val }
         };
         st.pos += 1u;
-        inputs += [{mode: mode, ty: parse_ty(st, conv)}];
+        inputs += [{mode: ast::expl(mode), ty: parse_ty(st, conv)}];
     }
     st.pos += 1u; // eat the ']'
     let cs = parse_constrs(st, conv);
index 5f78f305d8d6f14a5c2e28f4a6b7acf5d692cb97..a9baa4f74702e10368de15efad5162e1184a27d5 100644 (file)
@@ -5,6 +5,7 @@
 import std::map::hashmap;
 import option::{some, none};
 import syntax::ast::*;
+import driver::session::session;
 import middle::ty;
 import syntax::print::pprust::*;
 
@@ -162,11 +163,6 @@ fn enc_sty(w: io::writer, cx: @ctxt, st: ty::sty) {
         w.write_char(']');
       }
       ty::ty_var(id) { w.write_char('X'); w.write_str(int::str(id)); }
-      ty::ty_native(def) {
-        w.write_char('E');
-        w.write_str(cx.ds(def));
-        w.write_char('|');
-      }
       ty::ty_param(id, did) {
         w.write_char('p');
         w.write_str(cx.ds(did));
@@ -207,7 +203,7 @@ fn enc_proto(w: io::writer, proto: proto) {
 fn enc_ty_fn(w: io::writer, cx: @ctxt, ft: ty::fn_ty) {
     w.write_char('[');
     for arg: ty::arg in ft.inputs {
-        alt arg.mode {
+        alt ty::resolved_mode(cx.tcx, arg.mode) {
           by_mut_ref { w.write_char('&'); }
           by_move { w.write_char('-'); }
           by_copy { w.write_char('+'); }
index a8a88dfa193e6a7b93d5136611bf750987066cb6..a6177e015c58eb1e27815db58c7317e9e9ab72c5 100644 (file)
@@ -6,10 +6,12 @@
 import visit::vt;
 import core::{vec, option};
 import std::list;
+import std::util::unreachable;
 import option::{some, none, is_none};
 import list::list;
 import driver::session::session;
 import pat_util::*;
+import util::ppaux::ty_to_str;
 
 // This is not an alias-analyser (though it would merit from becoming one, or
 // getting input from one, to be more precise). It is a pass that checks
@@ -25,7 +27,7 @@ enum unsafe_ty { contains(ty::t), mut_contains(ty::t), }
 
 type binding = @{node_id: node_id,
                  span: span,
-                 root_var: option::t<node_id>,
+                 root_var: option<node_id>,
                  local_id: uint,
                  unsafe_tys: [unsafe_ty],
                  mutable copied: copied};
@@ -34,7 +36,7 @@ enum unsafe_ty { contains(ty::t), mut_contains(ty::t), }
 type scope = {bs: [binding],
               invalid: @mutable list<@invalid>};
 
-fn mk_binding(cx: ctx, id: node_id, span: span, root_var: option::t<node_id>,
+fn mk_binding(cx: ctx, id: node_id, span: span, root_var: option<node_id>,
               unsafe_tys: [unsafe_ty]) -> binding {
     alt root_var {
       some(r_id) { cx.ref_map.insert(id, r_id); }
@@ -80,9 +82,11 @@ fn visit_fn(cx: @ctx, _fk: visit::fn_kind, decl: ast::fn_decl,
     let fty = ty::node_id_to_type(cx.tcx, id);
     let args = ty::ty_fn_args(cx.tcx, fty);
     for arg in args {
-        if arg.mode == ast::by_val &&
-           ty::type_has_dynamic_size(cx.tcx, arg.ty) {
+        alt ty::resolved_mode(cx.tcx, arg.mode) {
+          ast::by_val if ty::type_has_dynamic_size(cx.tcx, arg.ty) {
             err(*cx, sp, "can not pass a dynamically-sized type by value");
+          }
+          _ { /* fallthrough */ }
         }
     }
 
@@ -224,7 +228,8 @@ fn check_call(cx: ctx, sc: scope, f: @ast::expr, args: [@ast::expr])
     for arg_t: ty::arg in arg_ts {
         let arg = args[i];
         let root = expr_root(cx, arg, false);
-        if arg_t.mode == ast::by_mut_ref {
+        alt ty::resolved_mode(cx.tcx, arg_t.mode) {
+          ast::by_mut_ref {
             alt path_def(cx, arg) {
               some(def) {
                 let dnum = ast_util::def_id_of_def(def).node;
@@ -232,18 +237,21 @@ fn check_call(cx: ctx, sc: scope, f: @ast::expr, args: [@ast::expr])
               }
               _ { }
             }
+          }
+          ast::by_ref | ast::by_val | ast::by_move | ast::by_copy { }
         }
         let root_var = path_def_id(cx, root.ex);
+        let arg_copied = alt ty::resolved_mode(cx.tcx, arg_t.mode) {
+          ast::by_move | ast::by_copy { copied }
+          ast::by_mut_ref { not_allowed }
+          ast::by_ref | ast::by_val { not_copied }
+        };
         bindings += [@{node_id: arg.id,
                        span: arg.span,
                        root_var: root_var,
                        local_id: 0u,
                        unsafe_tys: unsafe_set(root.mut),
-                       mutable copied: alt arg_t.mode {
-                         ast::by_move | ast::by_copy { copied }
-                         ast::by_mut_ref { not_allowed }
-                         _ { not_copied }
-                       }}];
+                       mutable copied: arg_copied}];
         i += 1u;
     }
     let f_may_close =
@@ -277,7 +285,8 @@ fn check_call(cx: ctx, sc: scope, f: @ast::expr, args: [@ast::expr])
         for unsafe_ty in b.unsafe_tys {
             let i = 0u;
             for arg_t: ty::arg in arg_ts {
-                let mut_alias = arg_t.mode == ast::by_mut_ref;
+                let mut_alias =
+                    (ast::by_mut_ref == ty::arg_mode(cx.tcx, arg_t));
                 if i != j &&
                        ty_can_unsafely_include(cx, unsafe_ty, arg_t.ty,
                                                mut_alias) &&
@@ -425,7 +434,7 @@ fn check_assign(cx: @ctx, dest: @ast::expr, src: @ast::expr, sc: scope,
     check_lval(cx, dest, sc, v);
 }
 
-fn check_if(c: @ast::expr, then: ast::blk, els: option::t<@ast::expr>,
+fn check_if(c: @ast::expr, then: ast::blk, els: option<@ast::expr>,
             sc: scope, v: vt<scope>) {
     v.visit_expr(c, sc, v);
     let orig_invalid = *sc.invalid;
@@ -474,14 +483,14 @@ fn test_scope(cx: ctx, sc: scope, b: binding, p: @ast::path) {
     }
 }
 
-fn path_def(cx: ctx, ex: @ast::expr) -> option::t<ast::def> {
+fn path_def(cx: ctx, ex: @ast::expr) -> option<ast::def> {
     ret alt ex.node {
           ast::expr_path(_) { some(cx.tcx.def_map.get(ex.id)) }
           _ { none }
         }
 }
 
-fn path_def_id(cx: ctx, ex: @ast::expr) -> option::t<ast::node_id> {
+fn path_def_id(cx: ctx, ex: @ast::expr) -> option<ast::node_id> {
     alt ex.node {
       ast::expr_path(_) {
         ret some(ast_util::def_id_of_def(cx.tcx.def_map.get(ex.id)).node);
@@ -558,7 +567,7 @@ fn copy_is_expensive(tcx: ty::ctxt, ty: ty::t) -> bool {
     fn score_ty(tcx: ty::ctxt, ty: ty::t) -> uint {
         ret alt ty::struct(tcx, ty) {
           ty::ty_nil | ty::ty_bot | ty::ty_bool | ty::ty_int(_) |
-          ty::ty_uint(_) | ty::ty_float(_) | ty::ty_type | ty::ty_native(_) |
+          ty::ty_uint(_) | ty::ty_float(_) | ty::ty_type |
           ty::ty_ptr(_) { 1u }
           ty::ty_box(_) | ty::ty_iface(_, _) { 3u }
           ty::ty_constr(t, _) | ty::ty_res(_, t, _) { score_ty(tcx, t) }
@@ -575,6 +584,11 @@ fn score_ty(tcx: ty::ctxt, ty: ty::t) -> uint {
             for f in fs { sum += score_ty(tcx, f.mt.ty); }
             sum
           }
+          _ {
+            tcx.sess.warn(#fmt("score_ty: unexpected type %s",
+               ty_to_str(tcx, ty)));
+            1u // ???
+          }
         };
     }
     ret score_ty(tcx, ty) > 8u;
@@ -582,12 +596,12 @@ fn score_ty(tcx: ty::ctxt, ty: ty::t) -> uint {
 
 type pattern_root = {id: node_id,
                      name: ident,
-                     mut: option::t<unsafe_ty>,
+                     mut: option<unsafe_ty>,
                      span: span};
 
-fn pattern_roots(tcx: ty::ctxt, mut: option::t<unsafe_ty>, pat: @ast::pat)
+fn pattern_roots(tcx: ty::ctxt, mut: option<unsafe_ty>, pat: @ast::pat)
     -> [pattern_root] {
-    fn walk(tcx: ty::ctxt, mut: option::t<unsafe_ty>, pat: @ast::pat,
+    fn walk(tcx: ty::ctxt, mut: option<unsafe_ty>, pat: @ast::pat,
             &set: [pattern_root]) {
         alt normalize_pat(tcx, pat).node {
           ast::pat_wild | ast::pat_lit(_) | ast::pat_range(_, _) {}
@@ -602,23 +616,28 @@ fn walk(tcx: ty::ctxt, mut: option::t<unsafe_ty>, pat: @ast::pat,
           ast::pat_rec(fs, _) {
             let ty = ty::node_id_to_type(tcx, pat.id);
             for f in fs {
-                let m = ty::get_field(tcx, ty, f.ident).mt.mut != ast::imm;
-                walk(tcx, m ? some(contains(ty)) : mut, f.pat, set);
+                let m = ty::get_field(tcx, ty, f.ident).mt.mut != ast::imm,
+                    c = if m { some(contains(ty)) } else { mut };
+                walk(tcx, c, f.pat, set);
             }
           }
           ast::pat_box(p) {
             let ty = ty::node_id_to_type(tcx, pat.id);
             let m = alt ty::struct(tcx, ty) {
               ty::ty_box(mt) { mt.mut != ast::imm }
-            };
-            walk(tcx, m ? some(contains(ty)) : mut, p, set);
+              _ { tcx.sess.span_bug(pat.span, "box pat has non-box type"); }
+            },
+                c = if m  {some(contains(ty)) } else { mut };
+            walk(tcx, c, p, set);
           }
           ast::pat_uniq(p) {
             let ty = ty::node_id_to_type(tcx, pat.id);
             let m = alt ty::struct(tcx, ty) {
               ty::ty_uniq(mt) { mt.mut != ast::imm }
-            };
-            walk(tcx, m ? some(contains(ty)) : mut, p, set);
+              _ { tcx.sess.span_bug(pat.span, "uniq pat has non-uniq type"); }
+            },
+                c = if m { some(contains(ty)) } else { mut };
+            walk(tcx, c, p, set);
           }
         }
     }
@@ -630,7 +649,7 @@ fn walk(tcx: ty::ctxt, mut: option::t<unsafe_ty>, pat: @ast::pat,
 // Wraps the expr_root in mut.rs to also handle roots that exist through
 // return-by-reference
 fn expr_root(cx: ctx, ex: @ast::expr, autoderef: bool)
-    -> {ex: @ast::expr, mut: option::t<unsafe_ty>} {
+    -> {ex: @ast::expr, mut: option<unsafe_ty>} {
     let base_root = mut::expr_root(cx.tcx, ex, autoderef);
     let unsafe_ty = none;
     for d in *base_root.ds {
@@ -639,12 +658,12 @@ fn expr_root(cx: ctx, ex: @ast::expr, autoderef: bool)
     ret {ex: base_root.ex, mut: unsafe_ty};
 }
 
-fn unsafe_set(from: option::t<unsafe_ty>) -> [unsafe_ty] {
+fn unsafe_set(from: option<unsafe_ty>) -> [unsafe_ty] {
     alt from { some(t) { [t] } _ { [] } }
 }
 
 fn find_invalid(id: node_id, lst: list<@invalid>)
-    -> option::t<@invalid> {
+    -> option<@invalid> {
     let cur = lst;
     while true {
         alt cur {
@@ -669,6 +688,10 @@ fn append_invalid(dest: list<@invalid>, src: list<@invalid>,
             }
             cur = *tail;
           }
+          list::nil {
+              fail "append_invalid: stop doesn't appear to be \
+                 a postfix of src";
+          }
         }
     }
     ret dest;
@@ -683,6 +706,10 @@ fn filter_invalid(src: list<@invalid>, bs: [binding]) -> list<@invalid> {
             if !is_none(p) { out = list::cons(head, @out); }
             cur = *tail;
           }
+          list::nil {
+            // typestate would help...
+            unreachable();
+          }
         }
     }
     ret out;
index 58c6bfc29142a66d9c00a3ec3507f9ae3893f623..c47c0d9b9f42ebf862df447229336d7029a2a63d 100644 (file)
@@ -4,10 +4,13 @@
 import syntax::ast_util;
 import syntax::{visit, codemap};
 
+enum path_elt { path_mod(str), path_name(str) }
+type path = [path_elt];
+
 enum ast_node {
-    node_item(@item),
-    node_native_item(@native_item),
-    node_method(@method),
+    node_item(@item, @path),
+    node_native_item(@native_item, @path),
+    node_method(@method, @path),
     node_expr(@expr),
     // Locals are numbered, because the alias analysis needs to know in which
     // order they are introduced.
@@ -17,110 +20,78 @@ enum ast_node {
 }
 
 type map = std::map::map<node_id, ast_node>;
-type ctx = @{map: map, mutable local_id: uint};
+type ctx = {map: map, mutable path: path, mutable local_id: uint};
+type vt = visit::vt<ctx>;
 
 fn map_crate(c: crate) -> map {
-    let cx = @{map: std::map::new_int_hash(),
-               mutable local_id: 0u};
-
-    let v_map = visit::mk_simple_visitor
-        (@{visit_item: bind map_item(cx, _),
-           visit_native_item: bind map_native_item(cx, _),
-           visit_expr: bind map_expr(cx, _),
-           visit_fn: bind map_fn(cx, _, _, _, _, _),
-           visit_local: bind map_local(cx, _),
-           visit_arm: bind map_arm(cx, _)
-           with *visit::default_simple_visitor()});
-    visit::visit_crate(c, (), v_map);
+    let cx = {map: std::map::new_int_hash(),
+              mutable path: [],
+              mutable local_id: 0u};
+    visit::visit_crate(c, cx, visit::mk_vt(@{
+        visit_item: map_item,
+        visit_native_item: map_native_item,
+        visit_expr: map_expr,
+        visit_fn: map_fn,
+        visit_local: map_local,
+        visit_arm: map_arm
+        with *visit::default_visitor()
+    }));
     ret cx.map;
 }
 
-fn map_fn(cx: ctx, _fk: visit::fn_kind, decl: fn_decl, _body: blk,
-          _sp: codemap::span, _id: node_id) {
+fn map_fn(fk: visit::fn_kind, decl: fn_decl, body: blk,
+          sp: codemap::span, id: node_id, cx: ctx, v: vt) {
     for a in decl.inputs {
         cx.map.insert(a.id, node_arg(a, cx.local_id));
         cx.local_id += 1u;
     }
+    visit::visit_fn(fk, decl, body, sp, id, cx, v);
 }
 
-fn map_local(cx: ctx, loc: @local) {
-    pat_util::pat_bindings(loc.node.pat) {|p|
-        cx.map.insert(p.id, node_local(cx.local_id));
+fn map_local(loc: @local, cx: ctx, v: vt) {
+    pat_util::pat_bindings(loc.node.pat) {|p_id, _s, _p|
+        cx.map.insert(p_id, node_local(cx.local_id));
         cx.local_id += 1u;
     };
+    visit::visit_local(loc, cx, v);
 }
 
-fn map_arm(cx: ctx, arm: arm) {
-    pat_util::pat_bindings(arm.pats[0]) {|p|
-        cx.map.insert(p.id, node_local(cx.local_id));
+fn map_arm(arm: arm, cx: ctx, v: vt) {
+    pat_util::pat_bindings(arm.pats[0]) {|p_id, _s, _p|
+        cx.map.insert(p_id, node_local(cx.local_id));
         cx.local_id += 1u;
     };
+    visit::visit_arm(arm, cx, v);
 }
 
-fn map_item(cx: ctx, i: @item) {
-    cx.map.insert(i.id, node_item(i));
+fn map_item(i: @item, cx: ctx, v: vt) {
+    cx.map.insert(i.id, node_item(i, @cx.path));
     alt i.node {
       item_impl(_, _, _, ms) {
-        for m in ms { cx.map.insert(m.id, node_method(m)); }
+        for m in ms { cx.map.insert(m.id, node_method(m, @cx.path)); }
       }
       item_res(_, _, _, dtor_id, ctor_id) {
         cx.map.insert(ctor_id, node_res_ctor(i));
-        cx.map.insert(dtor_id, node_item(i));
+        cx.map.insert(dtor_id, node_item(i, @cx.path));
       }
       _ { }
     }
+    alt i.node {
+      item_mod(_) | item_native_mod(_) { cx.path += [path_mod(i.ident)]; }
+      _ { cx.path += [path_name(i.ident)]; }
+    }
+    visit::visit_item(i, cx, v);
+    vec::pop(cx.path);
 }
 
-fn map_native_item(cx: ctx, i: @native_item) {
-    cx.map.insert(i.id, node_native_item(i));
+fn map_native_item(i: @native_item, cx: ctx, v: vt) {
+    cx.map.insert(i.id, node_native_item(i, @cx.path));
+    visit::visit_native_item(i, cx, v);
 }
 
-fn map_expr(cx: ctx, ex: @expr) {
+fn map_expr(ex: @expr, cx: ctx, v: vt) {
     cx.map.insert(ex.id, node_expr(ex));
-}
-
-fn node_span(node: ast_node) -> codemap::span {
-    alt node {
-      node_item(item) { item.span }
-      node_native_item(nitem) { nitem.span }
-      node_expr(expr) { expr.span }
-    }
-}
-
-#[cfg(test)]
-mod test {
-    import syntax::ast_util;
-
-    #[test]
-    fn test_node_span_item() {
-        let expected: codemap::span = ast_util::mk_sp(20u, 30u);
-        let node =
-            node_item(@{ident: "test",
-                        attrs: [],
-                        id: 0,
-                        node: item_mod({view_items: [], items: []}),
-                        span: expected});
-        assert (node_span(node) == expected);
-    }
-
-    #[test]
-    fn test_node_span_native_item() {
-        let expected: codemap::span = ast_util::mk_sp(20u, 30u);
-        let node =
-            node_native_item(@{ident: "test",
-                               attrs: [],
-                               node: native_item_ty,
-                               id: 0,
-                               span: expected});
-        assert (node_span(node) == expected);
-    }
-
-    #[test]
-    fn test_node_span_expr() {
-        let expected: codemap::span = ast_util::mk_sp(20u, 30u);
-        let node = node_expr(@{id: 0, node: expr_break, span: expected});
-        assert (node_span(node) == expected);
-    }
+    visit::visit_expr(ex, cx, v);
 }
 
 // Local Variables:
index 4357f754a58609f85c2e5d69db0b179627282f27..9d31e089e107b3dead1bf5596e162d0f5846657a 100644 (file)
@@ -28,7 +28,7 @@ fn visit_expr(ex: @expr, cx: ctx, v: visit::vt<ctx>) {
         v.visit_expr(f, cx, v);
         let i = 0u;
         for arg_t in ty::ty_fn_args(cx.tcx, ty::expr_ty(cx.tcx, f)) {
-            cx.allow_block = arg_t.mode == by_ref;
+            cx.allow_block = (ty::arg_mode(cx.tcx, arg_t) == by_ref);
             v.visit_expr(args[i], cx, v);
             i += 1u;
         }
index e78b9ddb77f8f9cd180b8ce5be3dc4d08425783f..2577ed03a932879f8404f172dc64084ebdc42ba6 100644 (file)
@@ -1,10 +1,14 @@
+
 import syntax::ast::*;
 import syntax::ast_util::{variant_def_ids, dummy_sp, compare_lit_exprs,
-                          lit_expr_eq};
+        lit_expr_eq, unguarded_pat};
+import syntax::codemap::span;
 import pat_util::*;
 import syntax::visit;
 import option::{some, none};
 import driver::session::session;
+import middle::ty;
+import middle::ty::*;
 
 fn check_crate(tcx: ty::ctxt, crate: @crate) {
     let v =
@@ -18,15 +22,20 @@ fn check_crate(tcx: ty::ctxt, crate: @crate) {
 fn check_expr(tcx: ty::ctxt, ex: @expr, &&s: (), v: visit::vt<()>) {
     visit::visit_expr(ex, s, v);
     alt ex.node {
-        expr_alt(_, arms) {
-            check_arms(tcx, pat_util::normalize_arms(tcx, arms));
+        expr_alt(scrut, arms) {
+            check_arms(tcx, ex.span, scrut,
+                       pat_util::normalize_arms(tcx, arms));
         }
         _ { }
     }
 }
 
-fn check_arms(tcx: ty::ctxt, arms: [arm]) {
+fn check_arms(tcx: ty::ctxt, sp:span, scrut: @expr, arms: [arm]) {
     let i = 0;
+    let scrut_ty = expr_ty(tcx, scrut);
+    /* (Could both checks be done in a single pass?) */
+
+    /* Check for unreachable patterns */
     for arm: arm in arms {
         for arm_pat: @pat in arm.pats {
             let reachable = true;
@@ -47,6 +56,97 @@ fn check_arms(tcx: ty::ctxt, arms: [arm]) {
         }
         i += 1;
     }
+
+    /* Check for exhaustiveness */
+
+    check_exhaustive(tcx, sp, scrut_ty,
+       vec::concat(vec::filter_map(arms, unguarded_pat)));
+}
+
+// Precondition: patterns have been normalized
+// (not checked statically yet)
+fn check_exhaustive(tcx: ty::ctxt, sp:span, scrut_ty:ty::t, pats:[@pat]) {
+    let represented : [def_id] = [];
+    /* Determine the type of the scrutinee */
+    /* If it's not an enum, exit (bailing out on checking non-enum alts
+       for now) */
+    /* Otherwise, get the list of variants and make sure each one is
+     represented. Then recurse on the columns. */
+
+    let ty_def_id = alt ty::struct(tcx, scrut_ty) {
+            ty_enum(id, _) { id }
+            _ { ret; } };
+
+    let variants = *enum_variants(tcx, ty_def_id);
+    for pat in pats {
+        if !is_refutable(tcx, pat) {
+                /* automatically makes this alt complete */ ret;
+        }
+        alt pat.node {
+                // want the def_id for the constructor
+            pat_enum(id,_) {
+                alt tcx.def_map.find(pat.id) {
+                    some(def_variant(_, variant_def_id)) {
+                        represented += [variant_def_id];
+                    }
+                    _ { tcx.sess.span_bug(pat.span, "check_exhaustive:
+                          pat_tag not bound to a variant"); }
+                }
+            }
+            _ { tcx.sess.span_bug(pat.span, "check_exhaustive: ill-typed \
+                  pattern");   // we know this has enum type,
+            }                  // so anything else should be impossible
+         }
+    }
+    fn not_represented(v: [def_id], &&vinfo: variant_info) -> bool {
+        !vec::member(vinfo.id, v)
+    }
+    // Could be more efficient (bitvectors?)
+    alt vec::find(variants, bind not_represented(represented,_)) {
+        some(bad) {
+        // complain
+        // TODO: give examples of cases that aren't covered
+            tcx.sess.note("Patterns not covered include:");
+            tcx.sess.note(bad.name);
+            tcx.sess.span_err(sp, "Non-exhaustive pattern");
+        }
+        _ {}
+    }
+    // Otherwise, check subpatterns
+    // inefficient
+    for variant in variants {
+        // rows consists of the argument list for each pat that's an enum
+        let rows : [[@pat]] = [];
+        for pat in pats {
+            alt pat.node {
+               pat_enum(id, args) {
+                  alt tcx.def_map.find(pat.id) {
+                      some(def_variant(_,variant_id))
+                        if variant_id == variant.id { rows += [args]; }
+                      _ { }
+                  }
+               }
+               _ {}
+            }
+        }
+        if check vec::is_not_empty(rows) {
+             let i = 0u;
+             for it in rows[0] {
+                let column = [it];
+                // Annoying -- see comment in
+                // tstate::states::find_pre_post_state_loop
+                check vec::is_not_empty(rows);
+                for row in vec::tail(rows) {
+                  column += [row[i]];
+                }
+                check_exhaustive(tcx, sp, pat_ty(tcx, it), column);
+                i += 1u;
+             }
+        }
+        // This shouldn't actually happen, since there were no
+        // irrefutable patterns if we got here.
+        else { cont; }
+    }
 }
 
 fn pattern_supersedes(tcx: ty::ctxt, a: @pat, b: @pat) -> bool {
@@ -145,8 +245,8 @@ fn is_refutable(tcx: ty::ctxt, pat: @pat) -> bool {
       pat_wild | pat_ident(_, none) { false }
       pat_lit(_) { true }
       pat_rec(fields, _) {
-        for field: field_pat in fields {
-            if is_refutable(tcx, field.pat) { ret true; }
+        for it: field_pat in fields {
+            if is_refutable(tcx, it.pat) { ret true; }
         }
         false
       }
@@ -156,10 +256,11 @@ fn is_refutable(tcx: ty::ctxt, pat: @pat) -> bool {
       }
       pat_enum(_, args) {
         let vdef = variant_def_ids(tcx.def_map.get(pat.id));
-        if vec::len(*ty::enum_variants(tcx, vdef.tg)) != 1u { ret true; }
+        if vec::len(*ty::enum_variants(tcx, vdef.enm)) != 1u { ret true; }
         for p: @pat in args { if is_refutable(tcx, p) { ret true; } }
         false
       }
+      pat_range(_, _) { true }
     }
 }
 
index eec014a47f7271c166892f010befcd5c276bb76f..d04abffb3201dc297bc2d76ec6ac85c6f1f6c767 100644 (file)
@@ -73,14 +73,14 @@ fn check_expr(sess: session, method_map: typeck::method_map, e: @expr,
       expr_lit(@{node: lit_int(v, t), _}) {
         if t != ty_char {
             if (v as u64) > ast_util::int_ty_max(
-                t == ty_i ? sess.targ_cfg.int_type : t) {
+                if t == ty_i { sess.targ_cfg.int_type } else { t }) {
                 sess.span_err(e.span, "literal out of range for its type");
             }
         }
       }
       expr_lit(@{node: lit_uint(v, t), _}) {
         if v > ast_util::uint_ty_max(
-            t == ty_u ? sess.targ_cfg.uint_type : t) {
+            if t == ty_u { sess.targ_cfg.uint_type } else { t }) {
             sess.span_err(e.span, "literal out of range for its type");
         }
       }
index 05752acbcd4c39a863920e330f2197e58fa6d4a2..e0ad5a948159a28ea16a5183dbfb72670a40069d 100644 (file)
@@ -2,16 +2,17 @@
 import std::fs;
 import std::map::hashmap;
 import lib::llvm::llvm;
-import lib::llvm::llvm::ValueRef;
+import lib::llvm::ValueRef;
 import trans::common::*;
 import trans::base;
 import trans::build::B;
 import middle::ty;
-import syntax::{ast, codemap};
+import syntax::{ast, codemap, ast_util};
 import codemap::span;
 import ast::ty;
 import pat_util::*;
 import util::ppaux::ty_to_str;
+import driver::session::session;
 
 export create_local_var;
 export create_function;
@@ -142,7 +143,7 @@ fn md_from_metadata<T>(val: debug_metadata) -> T unsafe {
 }
 
 fn cached_metadata<T: copy>(cache: metadata_cache, mdtag: int,
-                           eq: fn(md: T) -> bool) -> option::t<T> unsafe {
+                           eq: fn(md: T) -> bool) -> option<T> unsafe {
     if cache.contains_key(mdtag) {
         let items = cache.get(mdtag);
         for item in items {
@@ -156,7 +157,7 @@ fn cached_metadata<T: copy>(cache: metadata_cache, mdtag: int,
 }
 
 fn create_compile_unit(cx: @crate_ctxt, full_path: str)
-    -> @metadata<compile_unit_md> {
+    -> @metadata<compile_unit_md> unsafe {
     let cache = get_cache(cx);
     let tg = CompileUnitTag;
     alt cached_metadata::<@metadata<compile_unit_md>>(cache, tg,
@@ -167,7 +168,7 @@ fn create_compile_unit(cx: @crate_ctxt, full_path: str)
 
     let work_dir = cx.sess.working_dir;
     let file_path = if str::starts_with(full_path, work_dir) {
-        str::slice(full_path, str::byte_len(work_dir),
+        str::unsafe::slice_bytes(full_path, str::byte_len(work_dir),
                    str::byte_len(full_path))
     } else {
         full_path
@@ -224,11 +225,20 @@ fn line_from_span(cm: codemap::codemap, sp: span) -> uint {
     codemap::lookup_char_pos(cm, sp.lo).line
 }
 
-fn create_block(cx: @block_ctxt, sp: span) -> @metadata<block_md> {
-    //let cache = get_cache(bcx_ccx(cx));
+fn create_block(cx: @block_ctxt) -> @metadata<block_md> {
+    let cache = get_cache(bcx_ccx(cx));
+    let cx = cx;
+    while option::is_none(cx.block_span) {
+        alt cx.parent {
+          parent_none { fail "BAD"; /*break;*/ }
+          parent_some(b) { cx = b; }
+        }
+    }
+    let sp = option::get(cx.block_span);
+
     let start = codemap::lookup_char_pos(bcx_ccx(cx).sess.codemap,
                                          sp.lo);
-    let fname = start.filename;
+    let fname = start.file.name;
     let end = codemap::lookup_char_pos(bcx_ccx(cx).sess.codemap,
                                        sp.hi);
     let tg = LexicalBlockTag;
@@ -240,25 +250,25 @@ fn create_block(cx: @block_ctxt, sp: span) -> @metadata<block_md> {
     }*/
 
     let parent = alt cx.parent {
-      parent_none { create_function(cx.fcx, sp).node }
-      parent_some(bcx) { create_block(bcx, sp).node }
+        parent_none { create_function(cx.fcx).node }
+        parent_some(bcx) { create_block(bcx).node }
     };
     let file_node = create_file(bcx_ccx(cx), fname);
-    /*let unique_id = alt cache.find(LexicalBlockTag) {
+    let unique_id = alt cache.find(LexicalBlockTag) {
       option::some(v) { vec::len(v) as int }
       option::none { 0 }
-    };*/
+    };
     let lldata = [lltag(tg),
                   parent,
                   lli32(start.line as int),
                   lli32(start.col as int),
-                  file_node.node/*,
-                  lli32(unique_id)*/
+                  file_node.node,
+                  lli32(unique_id)
                  ];
-      let val = llmdnode(lldata);
-      let mdval = @{node: val, data: {start: start, end: end}};
-      //update_cache(cache, tg, block_metadata(mdval));
-      ret mdval;
+    let val = llmdnode(lldata);
+    let mdval = @{node: val, data: {start: start, end: end}};
+    //update_cache(cache, tg, block_metadata(mdval));
+    ret mdval;
 }
 
 fn size_and_align_of<T>() -> (int, int) {
@@ -297,6 +307,8 @@ fn create_basic_type(cx: @crate_ctxt, t: ty::t, ty: @ast::ty)
         ast::ty_f32 {("f32", size_and_align_of::<f32>(), DW_ATE_float)}
         ast::ty_f64 {("f64", size_and_align_of::<f64>(), DW_ATE_float)}
       }}
+      _ { cx.tcx.sess.span_bug(ty.span,
+             "create_basic_type: unhandled type"); }
     };
 
     let fname = filename_from_span(cx, ty.span);
@@ -444,8 +456,8 @@ fn create_boxed_type(cx: @crate_ctxt, outer: ty::t, _inner: ty::t,
 
 fn create_composite_type(type_tag: int, name: str, file: ValueRef, line: int,
                          size: int, align: int, offset: int,
-                         derived: option::t<ValueRef>,
-                         members: option::t<[ValueRef]>)
+                         derived: option<ValueRef>,
+                         members: option<[ValueRef]>)
     -> ValueRef {
     let lldata = [lltag(type_tag),
                   file,
@@ -456,25 +468,31 @@ fn create_composite_type(type_tag: int, name: str, file: ValueRef, line: int,
                   lli64(align), // align
                   lli64(offset), // offset
                   lli32(0), // flags
-                  option::is_none(derived) ? llnull() : // derived from
-                                             option::get(derived),
-                  option::is_none(members) ? llnull() : // members
-                                             llmdnode(option::get(members)),
+                  if option::is_none(derived) {
+                      llnull()
+                  } else { // derived from
+                      option::get(derived)
+                  },
+                  if option::is_none(members) {
+                      llnull()
+                  } else { //members
+                      llmdnode(option::get(members))
+                  },
                   lli32(0),  // runtime language
                   llnull()
                  ];
     ret llmdnode(lldata);
 }
 
-fn create_vec(cx: @crate_ctxt, vec_t: ty::t, elem_t: ty::t, vec_ty: @ast::ty)
+fn create_vec(cx: @crate_ctxt, vec_t: ty::t, elem_t: ty::t,
+              vec_ty_span: codemap::span, elem_ty: @ast::ty)
     -> @metadata<tydesc_md> {
-    let fname = filename_from_span(cx, vec_ty.span);
+    let fname = filename_from_span(cx, vec_ty_span);
     let file_node = create_file(cx, fname);
-    let elem_ty = alt vec_ty.node { ast::ty_vec(mt) { mt.ty } };
     let elem_ty_md = create_ty(cx, elem_t, elem_ty);
     let tcx = ccx_tcx(cx);
     let scx = create_structure(file_node, ty_to_str(tcx, vec_t), 0);
-    let uint_ty = @{node: ast::ty_uint(ast::ty_u), span: vec_ty.span};
+    let uint_ty = @{node: ast::ty_uint(ast::ty_u), span: vec_ty_span};
     let size_t_type = create_basic_type(cx, ty::mk_uint(tcx), uint_ty);
     add_member(scx, "fill", 0, sys::size_of::<ctypes::size_t>() as int,
                sys::align_of::<ctypes::size_t>() as int, size_t_type.node);
@@ -501,12 +519,14 @@ fn member_size_and_align(ty: @ast::ty) -> (int, int) {
         ast::ty_i8 { size_and_align_of::<i8>() }
         ast::ty_i16 { size_and_align_of::<i16>() }
         ast::ty_i32 { size_and_align_of::<i32>() }
+        ast::ty_i64 { size_and_align_of::<i64>() }
       }}
       ast::ty_uint(m) { alt m {
         ast::ty_u { size_and_align_of::<uint>() }
         ast::ty_u8 { size_and_align_of::<i8>() }
         ast::ty_u16 { size_and_align_of::<u16>() }
         ast::ty_u32 { size_and_align_of::<u32>() }
+        ast::ty_u64 { size_and_align_of::<u64>() }
       }}
       ast::ty_float(m) { alt m {
         ast::ty_f { size_and_align_of::<float>() }
@@ -527,6 +547,7 @@ fn member_size_and_align(ty: @ast::ty) -> (int, int) {
       ast::ty_vec(_) {
         size_and_align_of::<ctypes::uintptr_t>()
       }
+      _ { fail "member_size_and_align: can't handle this type"; }
     }
 }
 
@@ -563,6 +584,9 @@ fn t_to_ty(cx: @crate_ctxt, t: ty::t, span: span) -> @ast::ty {
           }
           ty::ty_vec(mt) { ast::ty_vec({ty: t_to_ty(cx, mt.ty, span),
                                         mut: mt.mut}) }
+          _ {
+            cx.tcx.sess.span_bug(span, "t_to_ty: Can't handle this type");
+          }
         };
         ret @{node: ty, span: span};
     }
@@ -571,6 +595,7 @@ fn t_to_ty(cx: @crate_ctxt, t: ty::t, span: span) -> @ast::ty {
       ast::ty_box(mt) {
         let inner_t = alt ty::struct(ccx_tcx(cx), t) {
           ty::ty_box(boxed) { boxed.ty }
+          _ { cx.tcx.sess.span_bug(ty.span, "t_to_ty was incoherent"); }
         };
         let md = create_ty(cx, inner_t, mt.ty);
         let box = create_boxed_type(cx, t, inner_t, ty.span, md);
@@ -580,6 +605,8 @@ fn t_to_ty(cx: @crate_ctxt, t: ty::t, span: span) -> @ast::ty {
       ast::ty_uniq(mt) {
         let inner_t = alt ty::struct(ccx_tcx(cx), t) {
           ty::ty_uniq(boxed) { boxed.ty }
+          // Hoping we'll have a way to eliminate this check soon.
+          _ { cx.tcx.sess.span_bug(ty.span, "t_to_ty was incoherent"); }
         };
         let md = create_ty(cx, inner_t, mt.ty);
         ret create_pointer_type(cx, t, ty.span, md);
@@ -596,7 +623,8 @@ fn t_to_ty(cx: @crate_ctxt, t: ty::t, span: span) -> @ast::ty {
 
       ast::ty_vec(mt) {
         let inner_t = ty::sequence_element_type(ccx_tcx(cx), t);
-        let v = create_vec(cx, t, inner_t, ty);
+        let inner_ast_t = t_to_ty(cx, inner_t, mt.ty.span);
+        let v = create_vec(cx, t, inner_t, ty.span, inner_ast_t);
         ret create_pointer_type(cx, t, ty.span, v);
       }
 
@@ -604,8 +632,8 @@ fn t_to_ty(cx: @crate_ctxt, t: ty::t, span: span) -> @ast::ty {
     };
 }
 
-fn filename_from_span(cx: @crate_ctxt, sp: span) -> str {
-    codemap::lookup_char_pos(cx.sess.codemap, sp.lo).filename
+fn filename_from_span(cx: @crate_ctxt, sp: codemap::span) -> str {
+    codemap::lookup_char_pos(cx.sess.codemap, sp.lo).file.name
 }
 
 fn create_var(type_tag: int, context: ValueRef, name: str, file: ValueRef,
@@ -635,15 +663,17 @@ fn create_local_var(bcx: @block_ctxt, local: @ast::local)
     let name = path_to_ident(alt pat_util::normalize_pat(bcx_tcx(bcx),
                                            local.node.pat).node {
       ast::pat_ident(ident, _) { ident /*XXX deal w/ optional node binding*/ }
-    });
+      _ { bcx_tcx(bcx).sess.span_bug(local.span, "create_local_var: \
+             weird pattern in local"); }
+     });
     let loc = codemap::lookup_char_pos(cx.sess.codemap,
                                        local.span.lo);
-    let ty = base::node_id_type(cx, local.node.id);
+    let ty = node_id_type(bcx, local.node.id);
     let tymd = create_ty(cx, ty, local.node.ty);
-    let filemd = create_file(cx, loc.filename);
+    let filemd = create_file(cx, loc.file.name);
     let context = alt bcx.parent {
-      parent_none { create_function(bcx.fcx, local.span).node }
-      parent_some(_) { create_block(bcx, local.span).node }
+        parent_none { create_function(bcx.fcx).node }
+        parent_some(_) { create_block(bcx).node }
     };
     let mdnode = create_var(tg, context, name, filemd.node,
                             loc.line as int, tymd.node);
@@ -652,9 +682,15 @@ fn create_local_var(bcx: @block_ctxt, local: @ast::local)
 
     let llptr = alt bcx.fcx.lllocals.find(local.node.id) {
       option::some(local_mem(v)) { v }
+      option::some(_) {
+        bcx_tcx(bcx).sess.span_bug(local.span, "local is bound to \
+                something weird");
+      }
       option::none {
         alt bcx.fcx.lllocals.get(local.node.pat.id) {
           local_imm(v) { v }
+          _ { bcx_tcx(bcx).sess.span_bug(local.span, "local is bound to \
+                something weird"); }
         }
       }
     };
@@ -681,10 +717,10 @@ fn create_arg(bcx: @block_ctxt, arg: ast::arg, sp: span)
     };*/
     let loc = codemap::lookup_char_pos(cx.sess.codemap,
                                        sp.lo);
-    let ty = base::node_id_type(cx, arg.id);
+    let ty = node_id_type(bcx, arg.id);
     let tymd = create_ty(cx, ty, arg.ty);
-    let filemd = create_file(cx, loc.filename);
-    let context = create_function(bcx.fcx, sp);
+    let filemd = create_file(cx, loc.file.name);
+    let context = create_function(bcx.fcx);
     let mdnode = create_var(tg, context.node, arg.ident, filemd.node,
                             loc.line as int, tymd.node);
     let mdval = @{node: mdnode, data: {id: arg.id}};
@@ -704,7 +740,7 @@ fn update_source_pos(cx: @block_ctxt, s: span) {
         ret;
     }
     let cm = bcx_ccx(cx).sess.codemap;
-    let blockmd = create_block(cx, s);
+    let blockmd = create_block(cx);
     let loc = codemap::lookup_char_pos(cm, s.lo);
     let scopedata = [lli32(loc.line as int),
                      lli32(loc.col as int),
@@ -714,30 +750,37 @@ fn update_source_pos(cx: @block_ctxt, s: span) {
     llvm::LLVMSetCurrentDebugLocation(trans::build::B(cx), dbgscope);
 }
 
-fn create_function(fcx: @fn_ctxt, sp: span) -> @metadata<subprogram_md> {
+fn create_function(fcx: @fn_ctxt) -> @metadata<subprogram_md> {
     let cx = fcx_ccx(fcx);
     let dbg_cx = option::get(cx.dbg_cx);
 
     #debug("~~");
     log(debug, fcx.id);
 
-    //log(debug, codemap::span_to_str(sp, cx.sess.codemap));
+    let sp = option::get(fcx.span);
+    log(debug, codemap::span_to_str(sp, cx.sess.codemap));
 
     let (ident, ret_ty, id) = alt cx.ast_map.get(fcx.id) {
-      ast_map::node_item(item) {
+      ast_map::node_item(item, _) {
         alt item.node {
           ast::item_fn(decl, _, _) | ast::item_res(decl, _, _, _, _) {
             (item.ident, decl.output, item.id)
           }
+          _ { fcx_tcx(fcx).sess.span_bug(item.span, "create_function: item \
+                bound to non-function"); }
         }
       }
-      ast_map::node_method(method) {
+      ast_map::node_method(method, _) {
           (method.ident, method.decl.output, method.id)
       }
       ast_map::node_res_ctor(item) {
-        alt item.node { ast::item_res(decl, _, _, _, ctor_id) {
-          (item.ident, decl.output, ctor_id)
-        }}
+        alt item.node {
+            ast::item_res(decl, _, _, _, ctor_id) {
+              (item.ident, decl.output, ctor_id)
+            }
+            _ { fcx_tcx(fcx).sess.span_bug(item.span, "create_function: \
+                  expected an item_res here"); }
+          }
       }
       ast_map::node_expr(expr) {
         alt expr.node {
@@ -747,26 +790,30 @@ fn create_function(fcx: @fn_ctxt, sp: span) -> @metadata<subprogram_md> {
           ast::expr_fn_block(decl, _) {
             (dbg_cx.names("fn"), decl.output, expr.id)
           }
+          _ { fcx_tcx(fcx).sess.span_bug(expr.span, "create_function: \
+                  expected an expr_fn or fn_block here"); }
         }
       }
+      _ { fcx_tcx(fcx).sess.bug("create_function: unexpected \
+            sort of node"); }
     };
 
     log(debug, ident);
     log(debug, id);
 
-    /*let cache = get_cache(cx);
+    let cache = get_cache(cx);
     alt cached_metadata::<@metadata<subprogram_md>>(
         cache, SubprogramTag, {|md| md.data.id == id}) {
       option::some(md) { ret md; }
       option::none {}
-    }*/
+    }
 
-    let path = str::connect(fcx.lcx.path + [ident], "::");
+    let path = path_str(fcx.path);
 
     let loc = codemap::lookup_char_pos(cx.sess.codemap,
                                        sp.lo);
-    let file_node = create_file(cx, loc.filename).node;
-    let key = cx.item_symbols.contains_key(fcx.id) ? fcx.id : id;
+    let file_node = create_file(cx, loc.file.name).node;
+    let key = if cx.item_symbols.contains_key(fcx.id) { fcx.id } else { id };
     let mangled = cx.item_symbols.get(key);
     let ty_node = if cx.sess.opts.extra_debuginfo {
         alt ret_ty.node {
@@ -805,6 +852,6 @@ fn create_function(fcx: @fn_ctxt, sp: span) -> @metadata<subprogram_md> {
     let val = llmdnode(fn_metadata);
     add_named_metadata(cx, "llvm.dbg.sp", val);
     let mdval = @{node: val, data: {id: id}};
-    //update_cache(cache, SubprogramTag, subprogram_metadata(mdval));
+    update_cache(cache, SubprogramTag, subprogram_metadata(mdval));
     ret mdval;
 }
diff --git a/src/comp/middle/gc.rs b/src/comp/middle/gc.rs
deleted file mode 100644 (file)
index 4bcc2a2..0000000
+++ /dev/null
@@ -1,139 +0,0 @@
-// Routines useful for garbage collection.
-
-import lib::llvm::True;
-import lib::llvm::llvm::ValueRef;
-import trans::base::get_tydesc;
-import trans::common::*;
-import trans::base;
-import option::none;
-import str;
-import driver::session::session;
-
-import lll = lib::llvm::llvm;
-import bld = trans::build;
-
-type ctxt = @{mutable next_tydesc_num: uint};
-
-fn mk_ctxt() -> ctxt { ret @{mutable next_tydesc_num: 0u}; }
-
-fn add_global(ccx: @crate_ctxt, llval: ValueRef, name: str) -> ValueRef {
-    let llglobal =
-        str::as_buf(name,
-                    {|buf|
-                        lll::LLVMAddGlobal(ccx.llmod, val_ty(llval), buf)
-                    });
-    lll::LLVMSetInitializer(llglobal, llval);
-    lll::LLVMSetGlobalConstant(llglobal, True);
-    ret llglobal;
-}
-
-fn add_gc_root(cx: @block_ctxt, llval: ValueRef, ty: ty::t) -> @block_ctxt {
-    let bcx = cx;
-    let ccx = bcx_ccx(cx);
-    if !type_is_gc_relevant(bcx_tcx(cx), ty) ||
-           ty::type_has_dynamic_size(bcx_tcx(cx), ty) {
-        ret bcx;
-    }
-
-    let gc_cx = bcx_ccx(cx).gc_cx;
-
-    // FIXME (issue #839): For now, we are unconditionally zeroing out all
-    // GC-relevant types. Eventually we should use typestate for this.
-    bcx = base::zero_alloca(bcx, llval, ty);
-
-    let ti = none;
-    let td_r = get_tydesc(bcx, ty, false, ti);
-    bcx = td_r.result.bcx;
-    let lltydesc = td_r.result.val;
-
-    let gcroot = bcx_ccx(bcx).intrinsics.get("llvm.gcroot");
-    let llvalptr = bld::PointerCast(bcx, llval, T_ptr(T_ptr(T_i8())));
-
-    alt td_r.kind {
-      tk_derived {
-        // It's a derived type descriptor. First, spill it.
-        let lltydescptr = base::alloca(bcx, val_ty(lltydesc));
-
-        let llderivedtydescs =
-            base::llderivedtydescs_block_ctxt(bcx_fcx(bcx));
-        bld::Store(llderivedtydescs, lltydesc, lltydescptr);
-
-        let number = gc_cx.next_tydesc_num;
-        gc_cx.next_tydesc_num += 1u;
-
-        let lldestindex =
-            add_global(bcx_ccx(bcx), C_struct([C_int(ccx, 0),
-                                               C_uint(ccx, number)]),
-                       "rust_gc_tydesc_dest_index");
-        let llsrcindex =
-            add_global(bcx_ccx(bcx), C_struct([C_int(ccx, 1),
-                                               C_uint(ccx, number)]),
-                       "rust_gc_tydesc_src_index");
-
-        lldestindex = lll::LLVMConstPointerCast(lldestindex, T_ptr(T_i8()));
-        llsrcindex = lll::LLVMConstPointerCast(llsrcindex, T_ptr(T_i8()));
-
-        lltydescptr =
-            bld::PointerCast(llderivedtydescs, lltydescptr,
-                             T_ptr(T_ptr(T_i8())));
-
-        bld::Call(llderivedtydescs, gcroot, [lltydescptr, lldestindex]);
-        bld::Call(bcx, gcroot, [llvalptr, llsrcindex]);
-      }
-      tk_param {
-        bcx_tcx(cx).sess.bug("we should never be trying to root values " +
-                                 "of a type parameter");
-      }
-      tk_static {
-        // Static type descriptor.
-
-        let llstaticgcmeta =
-            add_global(bcx_ccx(bcx), C_struct([C_int(ccx, 2), lltydesc]),
-                       "rust_gc_tydesc_static_gc_meta");
-        let llstaticgcmetaptr =
-            lll::LLVMConstPointerCast(llstaticgcmeta, T_ptr(T_i8()));
-
-        bld::Call(bcx, gcroot, [llvalptr, llstaticgcmetaptr]);
-      }
-    }
-
-    ret bcx;
-}
-
-fn type_is_gc_relevant(cx: ty::ctxt, ty: ty::t) -> bool {
-    alt ty::struct(cx, ty) {
-      ty::ty_nil | ty::ty_bot | ty::ty_bool | ty::ty_int(_) |
-      ty::ty_float(_) | ty::ty_uint(_) | ty::ty_str |
-      ty::ty_type | ty::ty_ptr(_) | ty::ty_native(_) {
-        ret false;
-      }
-      ty::ty_rec(fields) {
-        for f in fields { if type_is_gc_relevant(cx, f.mt.ty) { ret true; } }
-        ret false;
-      }
-      ty::ty_tup(elts) {
-        for elt in elts { if type_is_gc_relevant(cx, elt) { ret true; } }
-        ret false;
-      }
-      ty::ty_enum(did, tps) {
-        let variants = ty::enum_variants(cx, did);
-        for variant in *variants {
-            for aty in variant.args {
-                let arg_ty = ty::substitute_type_params(cx, tps, aty);
-                if type_is_gc_relevant(cx, arg_ty) { ret true; }
-            }
-        }
-        ret false;
-      }
-      ty::ty_vec(tm) {
-        ret type_is_gc_relevant(cx, tm.ty);
-      }
-      ty::ty_constr(sub, _) { ret type_is_gc_relevant(cx, sub); }
-      ty::ty_box(_) | ty::ty_uniq(_) | ty::ty_fn(_) |
-      ty::ty_param(_, _) | ty::ty_res(_, _, _) { ret true; }
-      ty::ty_var(_) {
-        fail "ty_var in type_is_gc_relevant";
-      }
-    }
-}
-
index db35362f3ea087181333b52f881ec318edc98330..8e02389f2d2de64e3817b1d5cbe5ca59853c6ba8 100644 (file)
@@ -59,7 +59,7 @@ fn check_crate(tcx: ty::ctxt, method_map: typeck::method_map,
 // closure.
 fn with_appropriate_checker(cx: ctx, id: node_id,
                             b: fn(fn@(ctx, ty::t, sp: span))) {
-    let fty = ty::node_id_to_monotype(cx.tcx, id);
+    let fty = ty::node_id_to_type(cx.tcx, id);
     alt ty::ty_fn_proto(cx.tcx, fty) {
       proto_uniq { b(check_send); }
       proto_box { b(check_copy); }
@@ -142,7 +142,9 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) {
           some(ex) {
             // All noncopyable fields must be overridden
             let t = ty::expr_ty(cx.tcx, ex);
-            let ty_fields = alt ty::struct(cx.tcx, t) { ty::ty_rec(f) { f } };
+            let ty_fields = alt ty::struct(cx.tcx, t) { ty::ty_rec(f) { f }
+              _ { cx.tcx.sess.span_bug(ex.span,
+                     "Bad expr type in record"); } };
             for tf in ty_fields {
                 if !vec::any(fields, {|f| f.node.ident == tf.ident}) &&
                     !ty::kind_can_be_copied(ty::type_kind(cx.tcx, tf.mt.ty)) {
@@ -163,13 +165,15 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) {
       expr_call(f, args, _) {
         let i = 0u;
         for arg_t in ty::ty_fn_args(cx.tcx, ty::expr_ty(cx.tcx, f)) {
-            alt arg_t.mode { by_copy { maybe_copy(cx, args[i]); } _ {} }
+            alt ty::arg_mode(cx.tcx, arg_t) {
+              by_copy { maybe_copy(cx, args[i]); }
+              by_ref | by_val | by_mut_ref | by_move { }
+            }
             i += 1u;
         }
       }
       expr_path(_) {
-        let substs = ty::node_id_to_ty_param_substs_opt_and_ty(cx.tcx, e.id);
-        alt substs.substs {
+        alt cx.tcx.node_type_substs.find(e.id) {
           some(ts) {
             let did = ast_util::def_id_of_def(cx.tcx.def_map.get(e.id));
             let bounds = ty::lookup_item_type(cx.tcx, did).bounds;
@@ -189,7 +193,6 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) {
           none {}
         }
       }
-      expr_ternary(_, a, b) { maybe_copy(cx, a); maybe_copy(cx, b); }
       expr_fn(_, _, _, cap_clause) {
         check_fn_cap_clause(cx, e.id, *cap_clause);
       }
@@ -217,9 +220,24 @@ fn maybe_copy(cx: ctx, ex: @expr) {
     check_copy_ex(cx, ex, true);
 }
 
+fn is_nullary_variant(cx: ctx, ex: @expr) -> bool {
+    alt ex.node {
+      expr_path(_) {
+        alt cx.tcx.def_map.get(ex.id) {
+          def_variant(edid, vdid) {
+            vec::len(ty::enum_variant_with_id(cx.tcx, edid, vdid).args) == 0u
+          }
+          _ { false }
+        }
+      }
+      _ { false }
+    }
+}
+
 fn check_copy_ex(cx: ctx, ex: @expr, _warn: bool) {
     if ty::expr_is_lval(cx.method_map, ex) &&
-       !cx.last_uses.contains_key(ex.id) {
+       !cx.last_uses.contains_key(ex.id) &&
+       !is_nullary_variant(cx, ex) {
         let ty = ty::expr_ty(cx.tcx, ex);
         check_copy(cx, ty, ex.span);
         // FIXME turn this on again once vector types are no longer unique.
index af078afe53f2080b71006bd322f9bad9c927c73e..9c7fd7c0bc1cd321c5bbf4cf72023be64eab8195 100644 (file)
@@ -2,6 +2,7 @@
 import syntax::ast::*;
 import syntax::codemap::span;
 import std::list::{is_not_empty, list, nil, cons, tail};
+import std::util::unreachable;
 import core::{vec, option};
 import std::list;
 
@@ -64,7 +65,7 @@ fn find_last_uses(c: @crate, def_map: resolve::def_map,
 }
 
 fn ex_is_blockish(cx: ctx, id: node_id) -> bool {
-    alt ty::struct(cx.tcx, ty::node_id_to_monotype(cx.tcx, id)) {
+    alt ty::struct(cx.tcx, ty::node_id_to_type(cx.tcx, id)) {
       ty::ty_fn({proto: p, _}) if is_blockish(p) { true }
       _ { false }
     }
@@ -88,9 +89,6 @@ fn visit_expr(ex: @expr, cx: ctx, v: visit::vt<ctx>) {
         v.visit_expr(coll, cx, v);
         visit_block(loop, cx) {|| visit::visit_block(blk, cx, v);}
       }
-      expr_ternary(_, _, _) {
-        v.visit_expr(ast_util::ternary_to_if(ex), cx, v);
-      }
       expr_alt(input, arms) {
         v.visit_expr(input, cx, v);
         let before = cx.current, sets = [];
@@ -159,7 +157,7 @@ fn visit_expr(ex: @expr, cx: ctx, v: visit::vt<ctx>) {
                 fns += [arg];
               }
               _ {
-                alt arg_ts[i].mode {
+                alt ty::arg_mode(cx.tcx, arg_ts[i]) {
                   by_mut_ref { clear_if_path(cx, arg, v, false); }
                   _ { v.visit_expr(arg, cx, v); }
                 }
@@ -226,6 +224,11 @@ fn add_block_exit(cx: ctx, tp: block_type) -> bool {
             }
             cur = *tail;
           }
+          nil {
+            // typestate can't use the while loop condition --
+            // *sigh*
+            unreachable();
+          }
         }
     }
     ret false;
@@ -283,11 +286,21 @@ fn clear_in_current(cx: ctx, my_def: node_id, to: bool) {
 fn clear_def_if_path(cx: ctx, d: def, to: bool)
     -> option<node_id> {
     alt d {
-      def_local(def_id, let_copy) | def_arg(def_id, by_copy) |
-      def_arg(def_id, by_move) {
+      def_local(def_id, let_copy) {
         clear_in_current(cx, def_id.node, to);
         some(def_id.node)
       }
+      def_arg(def_id, m) {
+        alt ty::resolved_mode(cx.tcx, m) {
+          by_copy | by_move {
+            clear_in_current(cx, def_id.node, to);
+            some(def_id.node)
+          }
+          by_ref | by_val | by_mut_ref {
+            none
+          }
+        }
+      }
       _ {
         none
       }
@@ -295,7 +308,7 @@ fn clear_def_if_path(cx: ctx, d: def, to: bool)
 }
 
 fn clear_if_path(cx: ctx, ex: @expr, v: visit::vt<ctx>, to: bool)
-    -> option::t<node_id> {
+    -> option<node_id> {
     alt ex.node {
       expr_path(_) {
         ret clear_def_if_path(cx, cx.def_map.get(ex.id), to);
index 838764171f0e1677b738286db3f57acc0076824b..f2f5666a346519eaa7c2990de58362270afc28b5 100644 (file)
@@ -51,6 +51,7 @@ fn meta_to_option(meta: @ast::meta_item) -> (option, bool) {
           ast::meta_word(name) {
             str_to_option(name)
           }
+          _ { fail "meta_to_option: meta_list contains a non-meta-word"; }
         };
     }
 
index 7ecdd8be8f1adf9c9464bd29c6c9a00118bba5b5..b0e7b1ff5476caeee1ba597d014dc947a489a833 100644 (file)
@@ -78,6 +78,7 @@ fn maybe_auto_unbox(tcx: ty::ctxt, t: ty::t) -> {t: ty::t, ds: [deref]} {
               ty::ty_str {
                 ds += [@{mut: false, kind: index, outer_t: auto_unbox.t}];
               }
+              _ { break; }
             }
             ds += auto_unbox.ds;
             ex = base;
@@ -92,6 +93,8 @@ fn maybe_auto_unbox(tcx: ty::ctxt, t: ty::t) -> {t: ty::t, ds: [deref]} {
                   ty::ty_res(_, _, _) { }
                   ty::ty_enum(_, _) { }
                   ty::ty_ptr(mt) { is_mut = mt.mut == mut; ptr = true; }
+                  _ { tcx.sess.span_bug(base.span, "Ill-typed base \
+                        expression in deref"); }
                 }
                 ds += [@{mut: is_mut, kind: unbox(ptr && is_mut),
                          outer_t: base_t}];
@@ -225,26 +228,27 @@ fn check_call(cx: @ctx, f: @expr, args: [@expr]) {
     let arg_ts = ty::ty_fn_args(cx.tcx, ty::expr_ty(cx.tcx, f));
     let i = 0u;
     for arg_t: ty::arg in arg_ts {
-        alt arg_t.mode {
+        alt ty::resolved_mode(cx.tcx, arg_t.mode) {
           by_mut_ref { check_lval(cx, args[i], msg_mut_ref); }
           by_move { check_lval(cx, args[i], msg_move_out); }
-          _ {}
+          by_ref | by_val | by_copy { }
         }
         i += 1u;
     }
 }
 
-fn check_bind(cx: @ctx, f: @expr, args: [option::t<@expr>]) {
+fn check_bind(cx: @ctx, f: @expr, args: [option<@expr>]) {
     let arg_ts = ty::ty_fn_args(cx.tcx, ty::expr_ty(cx.tcx, f));
     let i = 0u;
     for arg in args {
         alt arg {
           some(expr) {
-            alt (alt arg_ts[i].mode {
+            let o_msg = alt ty::resolved_mode(cx.tcx, arg_ts[i].mode) {
               by_mut_ref { some("by mutable reference") }
               by_move { some("by move") }
               _ { none }
-            }) {
+            };
+            alt o_msg {
               some(name) {
                 cx.tcx.sess.span_err(
                     expr.span, "can not bind an argument passed " + name);
@@ -258,17 +262,21 @@ fn check_bind(cx: @ctx, f: @expr, args: [option::t<@expr>]) {
     }
 }
 
-fn is_immutable_def(cx: @ctx, def: def) -> option::t<str> {
+fn is_immutable_def(cx: @ctx, def: def) -> option<str> {
     alt def {
       def_fn(_, _) | def_mod(_) | def_native_mod(_) | def_const(_) |
       def_use(_) {
         some("static item")
       }
-      def_arg(_, by_ref) | def_arg(_, by_val) |
-      def_arg(_, mode_infer) { some("argument") }
+      def_arg(_, m) {
+        alt ty::resolved_mode(cx.tcx, m) {
+          by_ref | by_val { some("argument") }
+          by_mut_ref | by_move | by_copy { none }
+        }
+      }
       def_self(_) { some("self argument") }
       def_upvar(_, inner, node_id) {
-        let ty = ty::node_id_to_monotype(cx.tcx, node_id);
+        let ty = ty::node_id_to_type(cx.tcx, node_id);
         let proto = ty::ty_fn_proto(cx.tcx, ty);
         ret alt proto {
           proto_any | proto_block { is_immutable_def(cx, *inner) }
index 023d49db8a1246eb8282d0f3d4c02f96dccf1368..8a5c2706bb1a8e69bed0e854a5614d39c8eca933 100644 (file)
@@ -3,6 +3,7 @@
 import syntax::ast_util::respan;
 import syntax::fold;
 import syntax::fold::*;
+import syntax::codemap::span;
 
 export normalize_arms;
 export normalize_pat;
@@ -80,10 +81,8 @@ fn normalize_arms(tcx: ty::ctxt, arms:[arm]) -> [arm] {
 // use the node_id of their namesake in the first pattern.
 fn pat_id_map(tcx: ty::ctxt, pat: @pat) -> pat_id_map {
     let map = std::map::new_str_hash::<node_id>();
-    pat_bindings(normalize_pat(tcx, pat)) {|bound|
-        let name = path_to_ident(alt bound.node
-           { pat_ident(n, _) { n } });
-        map.insert(name, bound.id);
+    pat_bindings(normalize_pat(tcx, pat)) {|p_id, _s, n|
+      map.insert(path_to_ident(n), p_id);
     };
     ret map;
 }
@@ -91,10 +90,11 @@ fn pat_id_map(tcx: ty::ctxt, pat: @pat) -> pat_id_map {
 // This does *not* normalize. The pattern should be already normalized
 // if you want to get a normalized pattern out of it.
 // Could return a constrained type in order to express that (future work)
-fn pat_bindings(pat: @pat, it: fn(@pat)) {
+fn pat_bindings(pat: @pat, it: fn(node_id, span, @path)) {
   alt pat.node {
-      pat_ident(_, option::none) { it(pat); }
-      pat_ident(_, option::some(sub)) { it(pat); pat_bindings(sub, it); }
+      pat_ident(pth, option::none) { it(pat.id, pat.span, pth); }
+      pat_ident(pth, option::some(sub)) { it(pat.id, pat.span, pth);
+        pat_bindings(sub, it); }
       pat_enum(_, sub) { for p in sub { pat_bindings(p, it); } }
       pat_rec(fields, _) { for f in fields { pat_bindings(f.pat, it); } }
       pat_tup(elts) { for elt in elts { pat_bindings(elt, it); } }
@@ -106,7 +106,7 @@ fn pat_bindings(pat: @pat, it: fn(@pat)) {
 
 fn pat_binding_ids(pat: @pat) -> [node_id] {
     let found = [];
-    pat_bindings(pat) {|b| found += [b.id]; };
+    pat_bindings(pat) {|b_id, _sp, _pt| found += [b_id]; };
     ret found;
 }
 
index f6fe2a79e4be02bcdcfd85a64794c78fcd0adf2d..2ba68b927f0ae1417ca48d5464e1a5a41a3c4f02 100644 (file)
@@ -45,22 +45,22 @@ enum scope {
 type scopes = list<scope>;
 
 enum import_state {
-    todo(ast::node_id, ast::ident, @[ast::ident], codemap::span, scopes),
-    is_glob(@[ast::ident], scopes, codemap::span),
+    todo(ast::node_id, ast::ident, @[ast::ident], span, scopes),
+    is_glob(@[ast::ident], scopes, span),
     resolving(span),
-    resolved(option::t<def>, /* value */
-             option::t<def>, /* type */
-             option::t<def>, /* module */
+    resolved(option<def>, /* value */
+             option<def>, /* type */
+             option<def>, /* module */
              @[@_impl], /* impls */
              /* used for reporting unused import warning */
-             ast::ident, codemap::span),
+             ast::ident, span),
 }
 
 enum glob_import_state {
     glob_resolving(span),
-    glob_resolved(option::t<def>,  /* value */
-                  option::t<def>,  /* type */
-                  option::t<def>), /* module */
+    glob_resolved(option<def>,  /* value */
+                  option<def>,  /* type */
+                  option<def>), /* module */
 }
 
 type ext_hash = hashmap<{did: def_id, ident: str, ns: namespace}, def>;
@@ -83,11 +83,13 @@ fn eq(v1: key, v2: key) -> bool {
 }
 
 enum mod_index_entry {
-    mie_view_item(@ast::view_item),
-    mie_import_ident(node_id, codemap::span),
+    mie_view_item(ident, node_id, span),
+    mie_import_ident(node_id, span),
     mie_item(@ast::item),
     mie_native_item(@ast::native_item),
-    mie_enum_variant(/* enum item */@ast::item, /* variant index */uint),
+    mie_enum_variant(/* variant index */uint,
+                     /*parts of enum item*/ [variant],
+                    node_id, span),
 }
 
 type mod_index = hashmap<ident, list<mod_index_entry>>;
@@ -96,7 +98,7 @@ enum mod_index_entry {
 type glob_imp_def = {def: def, item: @ast::view_item};
 
 type indexed_mod = {
-    m: option::t<ast::_mod>,
+    m: option<ast::_mod>,
     index: mod_index,
     mutable glob_imports: [glob_imp_def],
     glob_imported_names: hashmap<str, glob_import_state>,
@@ -111,7 +113,7 @@ enum mod_index_entry {
 type ext_map = hashmap<def_id, [ident]>;
 type exp_map = hashmap<str, @mutable [def]>;
 type impl_map = hashmap<node_id, iscopes>;
-type impl_cache = hashmap<def_id, option::t<@[@_impl]>>;
+type impl_cache = hashmap<def_id, option<@[@_impl]>>;
 
 type env =
     {cstore: cstore::cstore,
@@ -129,7 +131,7 @@ enum mod_index_entry {
                     mutable data: [ast::node_id]},
      mutable reported: [{ident: str, sc: scope}],
      mutable ignored_imports: [node_id],
-     mutable current_tp: option::t<uint>,
+     mutable current_tp: option<uint>,
      mutable resolve_unexported: bool,
      sess: session};
 
@@ -278,6 +280,8 @@ fn link_glob(e: @env, vi: @ast::view_item, sc: scopes, _v: vt<scopes>) {
                   scope_crate {
                     e.mod_map.get(ast::crate_node_id).glob_imports += [glob];
                   }
+                  _ { e.sess.span_bug(vi.span, "Unexpected scope in a glob \
+                       import"); }
                 }
             }
           }
@@ -294,6 +298,7 @@ fn resolve_imports(e: env) {
             resolve_import(e, local_def(node_id), name, *path, span, scopes);
           }
           resolved(_, _, _, _, _, _) | is_glob(_, _, _) { }
+          _ { e.sess.bug("Shouldn't see a resolving in resolve_imports"); }
         }
     };
     e.used_imports.track = false;
@@ -319,7 +324,7 @@ fn resolve_capture_item(e: @env, sc: scopes, &&cap_item: @ast::capture_item) {
     maybe_insert(e, cap_item.id, dcur);
 }
 
-fn maybe_insert(e: @env, id: node_id, def: option::t<def>) {
+fn maybe_insert(e: @env, id: node_id, def: option<def>) {
     if option::is_some(def) { e.def_map.insert(id, option::get(def)); }
 }
 
@@ -444,6 +449,7 @@ fn visit_item_with_scope(e: @env, i: @ast::item, sc: scopes, v: vt<scopes>) {
         alt ifce { some(ty) { v.visit_ty(ty, sc, v); } _ {} }
         v.visit_ty(sty, sc, v);
         for m in methods {
+            v.visit_ty_params(m.tps, sc, v);
             let msc = cons(scope_method(i.id, tps + m.tps), @sc);
             v.visit_fn(visit::fk_method(m.ident, []),
                        m.decl, m.body, m.span, m.id, msc, v);
@@ -474,10 +480,11 @@ fn visit_fn_with_scope(e: @env, fk: visit::fn_kind, decl: ast::fn_decl,
     // is this a main fn declaration?
     alt fk {
       visit::fk_item_fn(nm, _) {
-        if is_main_name([nm]) && !e.sess.building_library {
+        if is_main_name([ast_map::path_name(nm)]) &&
+           !e.sess.building_library {
             // This is a main function -- set it in the session
             // as the main ID
-            e.sess.main_fn = some(id);
+            e.sess.main_fn = some((id, sp));
         }
       }
       _ { /* fallthrough */ }
@@ -572,7 +579,7 @@ fn visit_local_with_scope(e: @env, loc: @local, sc:scopes, v:vt<scopes>) {
 
 
 fn follow_import(e: env, sc: scopes, path: [ident], sp: span) ->
-   option::t<def> {
+   option<def> {
     let path_len = vec::len(path);
     let dcur = lookup_in_scope_strict(e, sc, sp, path[0], ns_module);
     let i = 1u;
@@ -617,7 +624,7 @@ fn resolve_constr(e: @env, c: @ast::constr, sc: scopes, _v: vt<scopes>) {
 fn resolve_import(e: env, defid: ast::def_id, name: ast::ident,
                   ids: [ast::ident], sp: codemap::span, sc: scopes) {
     fn register(e: env, id: node_id, cx: ctxt, sp: codemap::span,
-                name: ast::ident, lookup: fn(namespace) -> option::t<def>,
+                name: ast::ident, lookup: fn(namespace) -> option<def>,
                 impls: [@_impl]) {
         let val = lookup(ns_val(ns_any_value)), typ = lookup(ns_type),
             md = lookup(ns_module);
@@ -664,6 +671,9 @@ fn lst(my_id: node_id, vis: [@view_item]) -> [node_id] {
             lst(id,
                 option::get(e.mod_map.get(ast::crate_node_id).m).view_items)
           }
+          _ {
+              e.sess.bug("find_imports_after: nil or unexpected scope");
+          }
         }
     }
     // This function has cleanup code at the end. Do not return without going
@@ -737,7 +747,7 @@ fn ns_name(ns: namespace) -> str {
 enum ctxt { in_mod(def), in_scope(scopes), }
 
 fn unresolved_err(e: env, cx: ctxt, sp: span, name: ident, kind: str) {
-    fn find_fn_or_mod_scope(sc: scopes) -> option::t<scope> {
+    fn find_fn_or_mod_scope(sc: scopes) -> option<scope> {
         let sc = sc;
         while true {
             alt sc {
@@ -794,7 +804,7 @@ fn mk_unresolved_msg(id: ident, kind: str) -> str {
 
 // Lookup helpers
 fn lookup_path_strict(e: env, sc: scopes, sp: span, pth: ast::path_,
-                      ns: namespace) -> option::t<def> {
+                      ns: namespace) -> option<def> {
     let n_idents = vec::len(pth.idents);
     let headns = if n_idents == 1u { ns } else { ns_module };
 
@@ -818,7 +828,7 @@ fn lookup_path_strict(e: env, sc: scopes, sp: span, pth: ast::path_,
 }
 
 fn lookup_in_scope_strict(e: env, sc: scopes, sp: span, name: ident,
-                          ns: namespace) -> option::t<def> {
+                          ns: namespace) -> option<def> {
     alt lookup_in_scope(e, sc, sp, name, ns) {
       none {
         unresolved_err(e, in_scope(sc), sp, name, ns_name(ns));
@@ -838,7 +848,7 @@ fn scope_is_fn(sc: scope) -> bool {
 // Returns:
 //   none - does not close
 //   some(node_id) - closes via the expr w/ node_id
-fn scope_closes(sc: scope) -> option::t<node_id> {
+fn scope_closes(sc: scope) -> option<node_id> {
     alt sc {
       scope_fn_expr(_, node_id, _) { some(node_id) }
       _ { none }
@@ -865,9 +875,9 @@ fn def_is_ty_arg(d: def) -> bool {
 }
 
 fn lookup_in_scope(e: env, sc: scopes, sp: span, name: ident, ns: namespace)
-   -> option::t<def> {
+   -> option<def> {
     fn in_scope(e: env, sp: span, name: ident, s: scope, ns: namespace) ->
-       option::t<def> {
+       option<def> {
         alt s {
           scope_crate {
             ret lookup_in_local_mod(e, ast::crate_node_id, sp,
@@ -903,6 +913,10 @@ fn in_scope(e: env, sp: span, name: ident, s: scope, ns: namespace) ->
               ast::native_item_fn(decl, ty_params) {
                 ret lookup_in_fn(e, name, decl, ty_params, ns);
               }
+              _ {
+                  e.sess.span_bug(it.span, "lookup_in_scope: \
+                    scope_native_item doesn't refer to a native item");
+              }
             }
           }
           scope_bare_fn(decl, _, ty_params) |
@@ -990,7 +1004,7 @@ fn in_scope(e: env, sp: span, name: ident, s: scope, ns: namespace) ->
 }
 
 fn lookup_in_ty_params(e: env, name: ident, ty_params: [ast::ty_param])
-    -> option::t<def> {
+    -> option<def> {
     let n = 0u;
     for tp: ast::ty_param in ty_params {
         if str::eq(tp.ident, name) && alt e.current_tp {
@@ -998,23 +1012,23 @@ fn lookup_in_ty_params(e: env, name: ident, ty_params: [ast::ty_param])
         } { ret some(ast::def_ty_param(local_def(tp.id), n)); }
         n += 1u;
     }
-    ret none;
+    ret none::<def>;
 }
 
-fn lookup_in_pat(e: env, name: ident, pat: @ast::pat) -> option::t<def_id> {
+fn lookup_in_pat(e: env, name: ident, pat: @ast::pat) -> option<def_id> {
     let found = none;
 
-    pat_util::pat_bindings(normalize_pat_def_map(e.def_map, pat)) {|bound|
-        let p_name = alt bound.node { ast::pat_ident(n, _) { n } };
-        if str::eq(path_to_ident(p_name), name)
-                    { found = some(local_def(bound.id)); }
+    pat_util::pat_bindings(normalize_pat_def_map(e.def_map, pat))
+     {|p_id, _sp, n|
+        if str::eq(path_to_ident(n), name)
+                    { found = some(local_def(p_id)); }
     };
     ret found;
 }
 
 fn lookup_in_fn(e: env, name: ident, decl: ast::fn_decl,
                 ty_params: [ast::ty_param],
-                ns: namespace) -> option::t<def> {
+                ns: namespace) -> option<def> {
     alt ns {
       ns_val(ns_any_value) {
         for a: ast::arg in decl.inputs {
@@ -1031,7 +1045,7 @@ fn lookup_in_fn(e: env, name: ident, decl: ast::fn_decl,
 
 
 fn lookup_in_block(e: env, name: ident, sp: span, b: ast::blk_, pos: uint,
-                   loc_pos: uint, ns: namespace) -> option::t<def> {
+                   loc_pos: uint, ns: namespace) -> option<def> {
     let i = vec::len(b.stmts);
     while i > 0u {
         i -= 1u;
@@ -1113,12 +1127,13 @@ fn lookup_in_block(e: env, name: ident, sp: span, b: ast::blk_, pos: uint,
               _ {}
             }
           }
+          _ { e.sess.span_bug(vi.span, "Unexpected view_item in block"); }
         }
     }
     ret none;
 }
 
-fn found_def_item(i: @ast::item, ns: namespace) -> option::t<def> {
+fn found_def_item(i: @ast::item, ns: namespace) -> option<def> {
     alt i.node {
       ast::item_const(_, _) {
         if ns == ns_val(ns_any_value) {
@@ -1153,7 +1168,7 @@ fn found_def_item(i: @ast::item, ns: namespace) -> option::t<def> {
 }
 
 fn lookup_in_mod_strict(e: env, m: def, sp: span, name: ident,
-                        ns: namespace, dr: dir) -> option::t<def> {
+                        ns: namespace, dr: dir) -> option<def> {
     alt lookup_in_mod(e, m, sp, name, ns, dr) {
       none {
         unresolved_err(e, in_mod(m), sp, name, ns_name(ns));
@@ -1164,7 +1179,7 @@ fn lookup_in_mod_strict(e: env, m: def, sp: span, name: ident,
 }
 
 fn lookup_in_mod(e: env, m: def, sp: span, name: ident, ns: namespace,
-                 dr: dir) -> option::t<def> {
+                 dr: dir) -> option<def> {
     let defid = def_id_of_def(m);
     if defid.crate != ast::local_crate {
         // examining a module in an external crate
@@ -1188,19 +1203,19 @@ fn lookup_in_mod(e: env, m: def, sp: span, name: ident, ns: namespace,
       ast::def_native_mod(defid) {
         ret lookup_in_local_native_mod(e, defid.node, sp, name, ns);
       }
+      _ {
+          // Precondition
+          e.sess.span_bug(sp, "lookup_in_mod was passed a non-mod def");
+      }
     }
 }
 
-fn found_view_item(e: env, vi: @ast::view_item) -> option::t<def> {
-    alt vi.node {
-      ast::view_item_use(_, _, id) {
-        let cnum = cstore::get_use_stmt_cnum(e.cstore, id);
-        ret some(ast::def_mod({crate: cnum, node: ast::crate_node_id}));
-      }
-    }
+fn found_view_item(e: env, id: node_id) -> def {
+    let cnum = cstore::get_use_stmt_cnum(e.cstore, id);
+    ret ast::def_mod({crate: cnum, node: ast::crate_node_id});
 }
 
-fn lookup_import(e: env, defid: def_id, ns: namespace) -> option::t<def> {
+fn lookup_import(e: env, defid: def_id, ns: namespace) -> option<def> {
     // Imports are simply ignored when resolving themselves.
     if vec::member(defid.node, e.ignored_imports) { ret none; }
     alt e.imports.get(defid.node) {
@@ -1219,11 +1234,14 @@ fn lookup_import(e: env, defid: def_id, ns: namespace) -> option::t<def> {
         ret alt ns { ns_val(_) { val } ns_type { typ }
                      ns_module { md } };
       }
+      is_glob(_,_,_) {
+          e.sess.bug("lookup_import: can't handle is_glob");
+      }
     }
 }
 
 fn lookup_in_local_native_mod(e: env, node_id: node_id, sp: span, id: ident,
-                              ns: namespace) -> option::t<def> {
+                              ns: namespace) -> option<def> {
     ret lookup_in_local_mod(e, node_id, sp, id, ns, inside);
 }
 
@@ -1232,7 +1250,7 @@ fn is_exported(e: env, i: ident, m: _mod) -> bool {
 }
 
 fn lookup_in_local_mod(e: env, node_id: node_id, sp: span, id: ident,
-                       ns: namespace, dr: dir) -> option::t<def> {
+                       ns: namespace, dr: dir) -> option<def> {
     let info = e.mod_map.get(node_id);
     if dr == outside && !is_exported(e, id, option::get(info.m)) {
         // if we're in a native mod, then dr==inside, so info.m is some _mod
@@ -1259,13 +1277,16 @@ fn lookup_in_local_mod(e: env, node_id: node_id, sp: span, id: ident,
 }
 
 fn lookup_in_globs(e: env, globs: [glob_imp_def], sp: span, id: ident,
-                   ns: namespace, dr: dir) -> option::t<def> {
+                   ns: namespace, dr: dir) -> option<def> {
     fn lookup_in_mod_(e: env, def: glob_imp_def, sp: span, name: ident,
-                      ns: namespace, dr: dir) -> option::t<glob_imp_def> {
+                      ns: namespace, dr: dir) -> option<glob_imp_def> {
         alt def.item.node {
           ast::view_item_import_glob(_, id) {
             if vec::member(id, e.ignored_imports) { ret none; }
           }
+          _ {
+            e.sess.span_bug(sp, "lookup_in_globs: not a glob");
+          }
         }
         alt lookup_in_mod(e, def.def, sp, name, ns, dr) {
           some(d) { option::some({def: d, item: def.item}) }
@@ -1290,7 +1311,7 @@ fn lookup_in_mod_(e: env, def: glob_imp_def, sp: span, name: ident,
 }
 
 fn lookup_glob_in_mod(e: env, info: @indexed_mod, sp: span, id: ident,
-                      wanted_ns: namespace, dr: dir) -> option::t<def> {
+                      wanted_ns: namespace, dr: dir) -> option<def> {
     // since we don't know what names we have in advance,
     // absence takes the place of todo()
     if !info.glob_imported_names.contains_key(id) {
@@ -1319,34 +1340,25 @@ fn lookup_glob_in_mod(e: env, info: @indexed_mod, sp: span, id: ident,
 }
 
 fn lookup_in_mie(e: env, mie: mod_index_entry, ns: namespace) ->
-   option::t<def> {
+   option<def> {
     alt mie {
-      mie_view_item(view_item) {
-        if ns == ns_module { ret found_view_item(e, view_item); }
+      mie_view_item(_, id, _) {
+         if ns == ns_module { ret some(found_view_item(e, id)); }
       }
       mie_import_ident(id, _) { ret lookup_import(e, local_def(id), ns); }
       mie_item(item) { ret found_def_item(item, ns); }
-      mie_enum_variant(item, variant_idx) {
-        alt item.node {
-          ast::item_enum(variants, _) {
-              alt ns {
-                  ns_val(_) {
-                     let vid = variants[variant_idx].node.id;
-                     ret some(ast::def_variant(local_def(item.id),
+      mie_enum_variant(variant_idx, variants, parent_id, parent_span) {
+         alt ns {
+            ns_val(_) {
+               let vid = variants[variant_idx].node.id;
+               ret some(ast::def_variant(local_def(parent_id),
                                         local_def(vid)));
-                  }
-                  _ { ret none::<def>; }
-              }
-          }
-        }
+            }
+            _ { ret none::<def>; }
+         }
       }
       mie_native_item(native_item) {
         alt native_item.node {
-          ast::native_item_ty {
-            if ns == ns_type {
-                ret some(ast::def_native_ty(local_def(native_item.id)));
-            }
-          }
           ast::native_item_fn(decl, _) {
             if ns == ns_val(ns_any_value) {
                 ret some(ast::def_fn(local_def(native_item.id),
@@ -1373,8 +1385,8 @@ fn index_mod(md: ast::_mod) -> mod_index {
     let index = new_str_hash::<list<mod_index_entry>>();
     for it: @ast::view_item in md.view_items {
         alt it.node {
-          ast::view_item_use(ident, _, _) {
-            add_to_index(index, ident, mie_view_item(it));
+          ast::view_item_use(ident, _, id) {
+           add_to_index(index, ident, mie_view_item(ident, id, it.span));
           }
           ast::view_item_import(ident, _, id) {
             add_to_index(index, ident, mie_import_ident(id, it.span));
@@ -1404,10 +1416,14 @@ fn index_mod(md: ast::_mod) -> mod_index {
             let variant_idx: uint = 0u;
             for v: ast::variant in variants {
                 add_to_index(index, v.node.name,
-                             mie_enum_variant(it, variant_idx));
+                             mie_enum_variant(variant_idx, variants,
+                                             it.id, it.span));
                 variant_idx += 1u;
             }
           }
+          ast::item_class(_, items, ctor_decl, _) {
+              fail "resolve::index_mod: item_class";
+          }
         }
     }
     ret index;
@@ -1417,8 +1433,9 @@ fn index_nmod(md: ast::native_mod) -> mod_index {
     let index = new_str_hash::<list<mod_index_entry>>();
     for it: @ast::view_item in md.view_items {
         alt it.node {
-          ast::view_item_use(ident, _, _) {
-            add_to_index(index, ident, mie_view_item(it));
+          ast::view_item_use(ident, _, id) {
+            add_to_index(index, ident, mie_view_item(ident, id,
+                                                     it.span));
           }
           ast::view_item_import(ident, _, id) {
             add_to_index(index, ident, mie_import_ident(id, it.span));
@@ -1430,6 +1447,7 @@ fn index_nmod(md: ast::native_mod) -> mod_index {
             }
           }
           ast::view_item_import_glob(_, _) | ast::view_item_export(_, _) { }
+          _ { /* tag exports */ }
         }
     }
     for it: @ast::native_item in md.items {
@@ -1448,7 +1466,7 @@ fn ns_for_def(d: def) -> namespace {
       ast::def_upvar(_, _, _) |  ast::def_self(_) { ns_val(ns_any_value) }
       ast::def_mod(_) | ast::def_native_mod(_) { ns_module }
       ast::def_ty(_) | ast::def_binding(_) | ast::def_use(_) |
-      ast::def_native_ty(_) { ns_type }
+      ast::def_ty_param(_, _) { ns_type }
     }
 }
 
@@ -1467,7 +1485,7 @@ fn ns_ok(wanted:namespace, actual:namespace) -> bool {
 }
 
 fn lookup_external(e: env, cnum: int, ids: [ident], ns: namespace) ->
-   option::t<def> {
+   option<def> {
     for d: def in csearch::lookup_defs(e.sess.cstore, cnum, ids) {
         e.ext_map.insert(def_id_of_def(d), ids);
         if ns_ok(ns, ns_for_def(d)) { ret some(d); }
@@ -1528,10 +1546,10 @@ fn dup(e: env, sp: span, word: str, name: ident) {
 
 fn mie_span(mie: mod_index_entry) -> span {
     ret alt mie {
-          mie_view_item(item) { item.span }
+          mie_view_item(_, _, span) { span }
           mie_import_ident(_, span) { span }
           mie_item(item) { item.span }
-          mie_enum_variant(item, _) { item.span }
+          mie_enum_variant(_, _, _, span) { span }
           mie_native_item(item) { item.span }
         };
 }
@@ -1558,9 +1576,8 @@ fn typaram_names(tps: [ast::ty_param]) -> [ident] {
 }
 
 fn check_pat(e: @env, ch: checker, p: @ast::pat) {
-    pat_util::pat_bindings(normalize_pat_def_map(e.def_map, p)) {|p|
-        let ident = path_to_ident(alt p.node { pat_ident(n, _) { n } });
-        add_name(ch, p.span, ident);
+    pat_util::pat_bindings(normalize_pat_def_map(e.def_map, p)) {|_i, p_sp, n|
+       add_name(ch, p_sp, path_to_ident(n));
     };
 }
 
@@ -1606,14 +1623,13 @@ fn check_block(e: @env, b: ast::blk, &&x: (), v: vt<()>) {
               ast::decl_local(locs) {
                 let local_values = checker(*e, "value");
                 for (_, loc) in locs {
-                        pat_util::pat_bindings
-                            (normalize_pat_def_map(e.def_map, loc.node.pat))
-                            {|p|
-                            let ident = path_to_ident(alt p.node
-                                 { pat_ident(n, _) { n } });
-                        add_name(local_values, p.span, ident);
-                        check_name(values, p.span, ident);
-                    };
+                     pat_util::pat_bindings
+                        (normalize_pat_def_map(e.def_map, loc.node.pat))
+                            {|_i, p_sp, n|
+                            let ident = path_to_ident(n);
+                            add_name(local_values, p_sp, ident);
+                            check_name(values, p_sp, ident);
+                          };
                 }
               }
               ast::decl_item(it) {
@@ -1716,7 +1732,7 @@ fn lookup_glob_any(e: @env, info: @indexed_mod, sp: span, path: str,
         is_some(m) || is_some(v) || is_some(t)
     }
 
-    fn maybe_add_reexport(e: @env, path: str, def: option::t<def>) {
+    fn maybe_add_reexport(e: @env, path: str, def: option<def>) {
         alt def {
           some(def) {
             alt e.exp_map.find(path) {
@@ -1806,8 +1822,9 @@ fn check_enum_ok(e: @env, sp:span, id: ident, val: @indexed_mod)
                             some(ms) {
                                 list::iter(ms) {|m|
                                    alt m {
-                                     mie_enum_variant(parent_item,_) {
-                                       if parent_item.id != parent_id {
+                                     mie_enum_variant(_, _, actual_parent_id,
+                                                     _) {
+                                       if actual_parent_id != parent_id {
                                           e.sess.span_err(vi.span,
                                            #fmt("variant %s \
                                            doesn't belong to enum %s",
@@ -1849,7 +1866,7 @@ fn resolve_impls(e: @env, c: @ast::crate) {
 }
 
 fn find_impls_in_view_item(e: env, vi: @ast::view_item,
-                           &impls: [@_impl], sc: option::t<iscopes>) {
+                           &impls: [@_impl], sc: option<iscopes>) {
     fn lookup_imported_impls(e: env, id: ast::node_id,
                              act: fn(@[@_impl])) {
         alt e.imports.get(id) {
@@ -1859,6 +1876,10 @@ fn lookup_imported_impls(e: env, id: ast::node_id,
                            scopes);
             alt e.imports.get(id) {
               resolved(_, _, _, is, _, _) { act(is); }
+              _ {
+                  e.sess.bug("Undocumented invariant in \
+                    lookup_imported_impls");
+              }
             }
           }
           _ {}
@@ -1898,6 +1919,8 @@ fn lookup_imported_impls(e: env, id: ast::node_id,
                 _ {}
               }
             }
+            _ { e.sess.span_bug(vi.span, "Undocumented invariant in \
+                  find_impls_in_view_item"); }
           }
       }
       _ {}
@@ -1905,8 +1928,8 @@ fn lookup_imported_impls(e: env, id: ast::node_id,
 }
 
 fn find_impls_in_item(e: env, i: @ast::item, &impls: [@_impl],
-                      name: option::t<ident>,
-                      ck_exports: option::t<ast::_mod>) {
+                      name: option<ident>,
+                      ck_exports: option<ast::_mod>) {
     alt i.node {
       ast::item_impl(_, ifce, _, mthds) {
         if alt name { some(n) { n == i.ident } _ { true } } &&
@@ -1928,7 +1951,7 @@ fn find_impls_in_item(e: env, i: @ast::item, &impls: [@_impl],
 }
 
 fn find_impls_in_mod_by_id(e: env, defid: def_id, &impls: [@_impl],
-                           name: option::t<ident>) {
+                           name: option<ident>) {
     let cached;
     alt e.impl_cache.find(defid) {
       some(some(v)) { cached = v; }
@@ -1962,7 +1985,7 @@ fn find_impls_in_mod_by_id(e: env, defid: def_id, &impls: [@_impl],
 }
 
 fn find_impls_in_mod(e: env, m: def, &impls: [@_impl],
-                     name: option::t<ident>) {
+                     name: option<ident>) {
     alt m {
       ast::def_mod(defid) {
         find_impls_in_mod_by_id(e, defid, impls, name);
@@ -1985,7 +2008,7 @@ fn visit_block_with_impl_scope(e: @env, b: ast::blk, sc: iscopes,
           _ {}
         }
     }
-    let sc = vec::len(impls) > 0u ? cons(@impls, @sc) : sc;
+    let sc = if vec::len(impls) > 0u { cons(@impls, @sc) } else { sc };
     visit::visit_block(b, sc, v);
 }
 
@@ -1997,8 +2020,11 @@ fn visit_mod_with_impl_scope(e: @env, m: ast::_mod, s: span, id: node_id,
     }
     for i in m.items { find_impls_in_item(*e, i, impls, none, none); }
     let impls = @impls;
-    visit::visit_mod(m, s, id,
-                     vec::len(*impls) > 0u ? cons(impls, @sc) : sc, v);
+    visit::visit_mod(m, s, id, if vec::len(*impls) > 0u {
+                                   cons(impls, @sc)
+                               } else {
+                                   sc
+                               }, v);
     e.impl_map.insert(id, cons(impls, @nil));
 }
 
index 389f490e8e9c2c6d8fe03c40eb0183196c28db50..500a8591516f4ffdb2345caa350021269795d764 100644 (file)
@@ -2,8 +2,7 @@
 // This substitutes for the runtime tags used by e.g. MLs.
 
 import lib::llvm::llvm;
-import lib::llvm::{True, False};
-import lib::llvm::llvm::{ModuleRef, TypeRef, ValueRef};
+import lib::llvm::{True, False, ModuleRef, TypeRef, ValueRef};
 import driver::session;
 import driver::session::session;
 import trans::base;
@@ -97,9 +96,7 @@ fn mk_global(ccx: @crate_ctxt, name: str, llval: ValueRef, internal: bool) ->
     lib::llvm::llvm::LLVMSetGlobalConstant(llglobal, True);
 
     if internal {
-        lib::llvm::llvm::LLVMSetLinkage(llglobal,
-                                        lib::llvm::LLVMInternalLinkage as
-                                            lib::llvm::llvm::Linkage);
+        lib::llvm::SetLinkage(llglobal, lib::llvm::InternalLinkage);
     }
 
     ret llglobal;
@@ -327,8 +324,7 @@ fn shape_of(ccx: @crate_ctxt, t: ty::t, ty_param_map: [uint]) -> [u8] {
       ty::ty_bot { s += [shape_u8]; }
       ty::ty_int(ast::ty_i) { s += [s_int(ccx.tcx)]; }
       ty::ty_float(ast::ty_f) { s += [s_float(ccx.tcx)]; }
-      ty::ty_uint(ast::ty_u) | ty::ty_ptr(_) |
-      ty::ty_native(_) { s += [s_uint(ccx.tcx)]; }
+      ty::ty_uint(ast::ty_u) | ty::ty_ptr(_) { s += [s_uint(ccx.tcx)]; }
       ty::ty_type { s += [s_tydesc(ccx.tcx)]; }
       ty::ty_send_type { s += [s_send_tydesc(ccx.tcx)]; }
       ty::ty_int(ast::ty_i8) { s += [shape_i8]; }
@@ -451,6 +447,12 @@ fn shape_of(ccx: @crate_ctxt, t: ty::t, ty_param_map: [uint]) -> [u8] {
       ty::ty_opaque_closure_ptr(_) {
         s += [shape_opaque_closure_ptr];
       }
+      ty::ty_constr(inner_t, _) {
+        s += shape_of(ccx, inner_t, ty_param_map);
+      }
+      ty::ty_named(_, _) {
+        ccx.tcx.sess.bug("shape_of: shouldn't see a ty_named");
+      }
     }
 
     ret s;
@@ -468,15 +470,6 @@ fn shape_of_variant(ccx: @crate_ctxt, v: ty::variant_info,
     ret s;
 }
 
-//fn variant_names(ccx: @crate_ctxt, tag_id: ast::def_id) -> [str] {
-//    assert ast::local_crate == tag_id.crate;
-//    alt ccx.tcx.items.get(tag_id.node) {
-//      ast_map::node_item(@{node: ast::item_tag(variants, _), _}) {
-//        vec::map(variants) {|variant| variant.node.name}
-//      }
-//    }
-//}
-
 fn gen_enum_shapes(ccx: @crate_ctxt) -> ValueRef {
     // Loop over all the enum variants and write their shapes into a
     // data buffer. As we do this, it's possible for us to discover
@@ -600,9 +593,8 @@ fn gen_shape_tables(ccx: @crate_ctxt) {
                        [lltagstable, llresourcestable]);
     lib::llvm::llvm::LLVMSetInitializer(ccx.shape_cx.llshapetables, lltables);
     lib::llvm::llvm::LLVMSetGlobalConstant(ccx.shape_cx.llshapetables, True);
-    lib::llvm::llvm::LLVMSetLinkage(ccx.shape_cx.llshapetables,
-                                    lib::llvm::LLVMInternalLinkage as
-                                        lib::llvm::llvm::Linkage);
+    lib::llvm::SetLinkage(ccx.shape_cx.llshapetables,
+                          lib::llvm::InternalLinkage);
 }
 
 // ______________________________________________________________________
@@ -699,6 +691,7 @@ fn static_size_of_enum(cx: @crate_ctxt, t: ty::t)
         cx.enum_sizes.insert(t, max_size);
         ret max_size;
       }
+      _ { cx.tcx.sess.bug("static_size_of_enum called on non-enum"); }
     }
 }
 
@@ -779,6 +772,11 @@ fn align_elements(cx: @block_ctxt, elts: [ty::t]) -> metrics {
 
         { bcx: bcx, sz: sz, align: C_int(ccx, 1) }
       }
+      _ {
+        // Precondition?
+        bcx_tcx(cx).sess.bug("dynamic_metrics: type has static \
+          size");
+      }
     }
 }
 
index 9cca779a37b783ca4f4ead3d1f81933bf1187372..310717937e9ca5bf0cdb405b6c5e3dd6bdc14d87 100644 (file)
@@ -3,16 +3,18 @@
 
 import driver::session::session;
 import lib::llvm::llvm;
-import lib::llvm::llvm::{ValueRef, BasicBlockRef};
+import lib::llvm::{ValueRef, BasicBlockRef};
 import pat_util::*;
 import build::*;
-import base::{new_sub_block_ctxt, new_scope_block_ctxt, load_if_immediate};
+import base::{new_sub_block_ctxt, new_scope_block_ctxt,
+              new_real_block_ctxt, load_if_immediate};
 import syntax::ast;
 import syntax::ast_util;
 import syntax::ast_util::{dummy_sp};
 import syntax::ast::def_id;
 import syntax::codemap::span;
 import syntax::print::pprust::pat_to_str;
+import back::abi;
 
 import common::*;
 
@@ -20,7 +22,7 @@
 // range)
 enum opt {
     lit(@ast::expr),
-    var(/* disr val */int, /* variant dids */{tg: def_id, var: def_id}),
+    var(/* disr val */int, /* variant dids */{enm: def_id, var: def_id}),
     range(@ast::expr, @ast::expr)
 }
 fn opt_eq(a: opt, b: opt) -> bool {
@@ -68,7 +70,7 @@ fn trans_opt(bcx: @block_ctxt, o: opt) -> opt_result {
 // FIXME: invariant -- pat_id is bound in the def_map?
 fn variant_opt(ccx: @crate_ctxt, pat_id: ast::node_id) -> opt {
     let vdef = ast_util::variant_def_ids(ccx.tcx.def_map.get(pat_id));
-    let variants = ty::enum_variants(ccx.tcx, vdef.tg);
+    let variants = ty::enum_variants(ccx.tcx, vdef.enm);
     for v: ty::variant_info in *variants {
         if vdef.var == v.id { ret var(v.disr_val, vdef); }
     }
@@ -76,7 +78,7 @@ fn variant_opt(ccx: @crate_ctxt, pat_id: ast::node_id) -> opt {
 }
 
 type bind_map = [{ident: ast::ident, val: ValueRef}];
-fn assoc(key: str, list: bind_map) -> option::t<ValueRef> {
+fn assoc(key: str, list: bind_map) -> option<ValueRef> {
     for elt: {ident: ast::ident, val: ValueRef} in list {
         if str::eq(elt.ident, key) { ret some(elt.val); }
     }
@@ -87,7 +89,7 @@ fn assoc(key: str, list: bind_map) -> option::t<ValueRef> {
     @{pats: [@ast::pat],
       bound: bind_map,
       data: @{body: BasicBlockRef,
-              guard: option::t<@ast::expr>,
+              guard: option<@ast::expr>,
               id_map: pat_id_map}};
 type match = [match_branch];
 
@@ -119,7 +121,7 @@ fn expand_nested_bindings(m: match, col: uint, val: ValueRef) -> match {
     result
 }
 
-type enter_pat = fn@(@ast::pat) -> option::t<[@ast::pat]>;
+type enter_pat = fn@(@ast::pat) -> option<[@ast::pat]>;
 
 fn enter_match(m: match, col: uint, val: ValueRef, e: enter_pat) -> match {
     let result = [];
@@ -152,7 +154,7 @@ fn matches_always(p: @ast::pat) -> bool {
                 _ { false }
         }
     }
-    fn e(p: @ast::pat) -> option::t<[@ast::pat]> {
+    fn e(p: @ast::pat) -> option<[@ast::pat]> {
         ret if matches_always(p) { some([]) } else { none };
     }
     ret enter_match(m, col, val, e);
@@ -162,7 +164,7 @@ fn enter_opt(ccx: @crate_ctxt, m: match, opt: opt, col: uint, enum_size: uint,
              val: ValueRef) -> match {
     let dummy = @{id: 0, node: ast::pat_wild, span: dummy_sp()};
     fn e(ccx: @crate_ctxt, dummy: @ast::pat, opt: opt, size: uint,
-         p: @ast::pat) -> option::t<[@ast::pat]> {
+         p: @ast::pat) -> option<[@ast::pat]> {
         alt p.node {
           ast::pat_enum(ctor, subpats) {
             ret if opt_eq(variant_opt(ccx, p.id), opt) {
@@ -185,7 +187,7 @@ fn enter_rec(m: match, col: uint, fields: [ast::ident], val: ValueRef) ->
    match {
     let dummy = @{id: 0, node: ast::pat_wild, span: dummy_sp()};
     fn e(dummy: @ast::pat, fields: [ast::ident], p: @ast::pat) ->
-       option::t<[@ast::pat]> {
+       option<[@ast::pat]> {
         alt p.node {
           ast::pat_rec(fpats, _) {
             let pats = [];
@@ -207,7 +209,7 @@ fn e(dummy: @ast::pat, fields: [ast::ident], p: @ast::pat) ->
 fn enter_tup(m: match, col: uint, val: ValueRef, n_elts: uint) -> match {
     let dummy = @{id: 0, node: ast::pat_wild, span: dummy_sp()};
     fn e(dummy: @ast::pat, n_elts: uint, p: @ast::pat) ->
-       option::t<[@ast::pat]> {
+       option<[@ast::pat]> {
         alt p.node {
           ast::pat_tup(elts) { ret some(elts); }
           _ { ret some(vec::init_elt(n_elts, dummy)); }
@@ -218,7 +220,7 @@ fn e(dummy: @ast::pat, n_elts: uint, p: @ast::pat) ->
 
 fn enter_box(m: match, col: uint, val: ValueRef) -> match {
     let dummy = @{id: 0, node: ast::pat_wild, span: dummy_sp()};
-    fn e(dummy: @ast::pat, p: @ast::pat) -> option::t<[@ast::pat]> {
+    fn e(dummy: @ast::pat, p: @ast::pat) -> option<[@ast::pat]> {
         alt p.node {
           ast::pat_box(sub) { ret some([sub]); }
           _ { ret some([dummy]); }
@@ -229,7 +231,7 @@ fn e(dummy: @ast::pat, p: @ast::pat) -> option::t<[@ast::pat]> {
 
 fn enter_uniq(m: match, col: uint, val: ValueRef) -> match {
     let dummy = @{id: 0, node: ast::pat_wild, span: dummy_sp()};
-    fn e(dummy: @ast::pat, p: @ast::pat) -> option::t<[@ast::pat]> {
+    fn e(dummy: @ast::pat, p: @ast::pat) -> option<[@ast::pat]> {
         alt p.node {
           ast::pat_uniq(sub) { ret some([sub]); }
           _ { ret some([dummy]); }
@@ -261,24 +263,24 @@ fn add_to_set(&set: [opt], val: opt) {
 }
 
 fn extract_variant_args(bcx: @block_ctxt, pat_id: ast::node_id,
-                        vdefs: {tg: def_id, var: def_id}, val: ValueRef) ->
+                        vdefs: {enm: def_id, var: def_id}, val: ValueRef) ->
    {vals: [ValueRef], bcx: @block_ctxt} {
-    let ccx = bcx.fcx.lcx.ccx, bcx = bcx;
+    let ccx = bcx.fcx.ccx, bcx = bcx;
     // invariant:
     // pat_id must have the same length ty_param_substs as vdefs?
     let ty_param_substs = ty::node_id_to_type_params(ccx.tcx, pat_id);
     let blobptr = val;
-    let variants = ty::enum_variants(ccx.tcx, vdefs.tg);
+    let variants = ty::enum_variants(ccx.tcx, vdefs.enm);
     let args = [];
     let size =
-        vec::len(ty::enum_variant_with_id(ccx.tcx, vdefs.tg, vdefs.var).args);
+       vec::len(ty::enum_variant_with_id(ccx.tcx, vdefs.enm, vdefs.var).args);
     if size > 0u && vec::len(*variants) != 1u {
         let enumptr =
             PointerCast(bcx, val, T_opaque_enum_ptr(ccx));
         blobptr = GEPi(bcx, enumptr, [0, 1]);
     }
     let i = 0u;
-    let vdefs_tg = vdefs.tg;
+    let vdefs_tg = vdefs.enm;
     let vdefs_var = vdefs.var;
     while i < size {
         check (valid_variant_index(i, bcx, vdefs_tg, vdefs_var));
@@ -401,13 +403,16 @@ fn compile_submatch(bcx: @block_ctxt, m: match, vals: [ValueRef], f: mk_fail,
 
     let col = pick_col(m);
     let val = vals[col];
-    let m = has_nested_bindings(m, col) ?
-        expand_nested_bindings(m, col, val) : m;
+    let m = if has_nested_bindings(m, col) {
+                expand_nested_bindings(m, col, val)
+            } else {
+                m
+            };
 
     let vals_left =
         vec::slice(vals, 0u, col) +
             vec::slice(vals, col + 1u, vec::len(vals));
-    let ccx = bcx.fcx.lcx.ccx;
+    let ccx = bcx.fcx.ccx;
     let pat_id = 0;
     for br: match_branch in m {
         // Find a real id (we're adding placeholder wildcard patterns, but
@@ -418,9 +423,8 @@ fn compile_submatch(bcx: @block_ctxt, m: match, vals: [ValueRef], f: mk_fail,
     let rec_fields = collect_record_fields(m, col);
     // Separate path for extracting and binding record fields
     if vec::len(rec_fields) > 0u {
-        let rec_ty = ty::node_id_to_monotype(ccx.tcx, pat_id);
-        let fields =
-            alt ty::struct(ccx.tcx, rec_ty) { ty::ty_rec(fields) { fields } };
+        let rec_ty = ty::node_id_to_type(ccx.tcx, pat_id);
+        let fields = ty::get_fields(ccx.tcx, rec_ty);
         let rec_vals = [];
         for field_name: ast::ident in rec_fields {
             let ix = option::get(ty::field_idx(field_name, fields));
@@ -436,10 +440,14 @@ fn compile_submatch(bcx: @block_ctxt, m: match, vals: [ValueRef], f: mk_fail,
     }
 
     if any_tup_pat(m, col) {
-        let tup_ty = ty::node_id_to_monotype(ccx.tcx, pat_id);
+        let tup_ty = ty::node_id_to_type(ccx.tcx, pat_id);
         let n_tup_elts =
             alt ty::struct(ccx.tcx, tup_ty) {
               ty::ty_tup(elts) { vec::len(elts) }
+              _ {
+                  ccx.sess.bug("Non-tuple type in tuple\
+                    pattern");
+              }
             };
         let tup_vals = [], i = 0u;
         while i < n_tup_elts {
@@ -458,7 +466,7 @@ fn compile_submatch(bcx: @block_ctxt, m: match, vals: [ValueRef], f: mk_fail,
     // Unbox in case of a box field
     if any_box_pat(m, col) {
         let box = Load(bcx, val);
-        let unboxed = GEPi(bcx, box, [0, back::abi::box_rc_field_body]);
+        let unboxed = GEPi(bcx, box, [0, abi::box_field_body]);
         compile_submatch(bcx, enter_box(m, col, val), [unboxed] + vals_left,
                          f, exits);
         ret;
@@ -479,7 +487,7 @@ enum branch_kind { no_branch, single, switch, compare, }
     if vec::len(opts) > 0u {
         alt opts[0] {
           var(_, vdef) {
-            if vec::len(*ty::enum_variants(ccx.tcx, vdef.tg)) == 1u {
+            if vec::len(*ty::enum_variants(ccx.tcx, vdef.enm)) == 1u {
                 kind = single;
             } else {
                 let enumptr =
@@ -491,8 +499,12 @@ enum branch_kind { no_branch, single, switch, compare, }
           }
           lit(l) {
             test_val = Load(bcx, val);
-            let pty = ty::node_id_to_monotype(ccx.tcx, pat_id);
-            kind = ty::type_is_integral(ccx.tcx, pty) ? switch : compare;
+            let pty = ty::node_id_to_type(ccx.tcx, pat_id);
+            kind = if ty::type_is_integral(ccx.tcx, pty) {
+                       switch
+                   } else {
+                       compare
+                   };
           }
           range(_, _) {
             test_val = Load(bcx, val);
@@ -533,6 +545,8 @@ enum branch_kind { no_branch, single, switch, compare, }
                 llvm::LLVMAddCase(sw, r.val, opt_cx.llbb);
                 bcx = r.bcx;
               }
+              _ { bcx_tcx(bcx).sess.bug("Someone forgot to\
+                    document an invariant in compile_submatch"); }
             }
           }
           compare {
@@ -616,8 +630,11 @@ fn make_phi_bindings(bcx: @block_ctxt, map: [exit_node],
         // Copy references that the alias analysis considered unsafe
         ids.values {|node_id|
             if bcx_ccx(bcx).copy_map.contains_key(node_id) {
-                let local = alt bcx.fcx.lllocals.get(node_id) {
-                  local_mem(x) { x }
+                let local = alt bcx.fcx.lllocals.find(node_id) {
+                  some(local_mem(x)) { x }
+                  _ { bcx_tcx(bcx).sess.bug("Someone \
+                        forgot to document an invariant in \
+                        make_phi_bindings"); }
                 };
                 let e_ty = ty::node_id_to_type(bcx_tcx(bcx), node_id);
                 let {bcx: abcx, val: alloc} = base::alloc_ty(bcx, e_ty);
@@ -651,7 +668,8 @@ fn trans_alt(cx: @block_ctxt, expr: @ast::expr, arms_: [ast::arm],
     let arms = normalize_arms(bcx_tcx(cx), arms_);
 
     for a: ast::arm in arms {
-        let body = new_scope_block_ctxt(er.bcx, "case_body");
+        let body = new_real_block_ctxt(er.bcx, "case_body",
+                                       a.body.span);
         let id_map = pat_util::pat_id_map(bcx_tcx(cx), a.pats[0]);
         bodies += [body];
         for p: @ast::pat in a.pats {
@@ -665,7 +683,7 @@ fn trans_alt(cx: @block_ctxt, expr: @ast::expr, arms_: [ast::arm],
     // Cached fail-on-fallthrough block
     let fail_cx = @mutable none;
     fn mk_fail(cx: @block_ctxt, sp: span,
-               done: @mutable option::t<BasicBlockRef>) -> BasicBlockRef {
+               done: @mutable option<BasicBlockRef>) -> BasicBlockRef {
         alt *done { some(bb) { ret bb; } _ { } }
         let fail_cx = new_sub_block_ctxt(cx, "case_fallthrough");
         base::trans_fail(fail_cx, some(sp), "non-exhaustive match failure");;
@@ -674,7 +692,7 @@ fn mk_fail(cx: @block_ctxt, sp: span,
     }
 
     let exit_map = [];
-    let t = base::node_id_type(cx.fcx.lcx.ccx, expr.id);
+    let t = node_id_type(cx, expr.id);
     let vr = base::spill_if_immediate(er.bcx, er.val, t);
     compile_submatch(vr.bcx, match, [vr.val],
                      bind mk_fail(alt_cx, expr.span, fail_cx), exit_map);
@@ -701,13 +719,13 @@ fn mk_fail(cx: @block_ctxt, sp: span,
 // Not alt-related, but similar to the pattern-munging code above
 fn bind_irrefutable_pat(bcx: @block_ctxt, pat: @ast::pat, val: ValueRef,
                         make_copy: bool) -> @block_ctxt {
-    let ccx = bcx.fcx.lcx.ccx, bcx = bcx;
+    let ccx = bcx.fcx.ccx, bcx = bcx;
 
     // Necessary since bind_irrefutable_pat is called outside trans_alt
     alt normalize_pat(bcx_tcx(bcx), pat).node {
       ast::pat_ident(_,inner) {
         if make_copy || ccx.copy_map.contains_key(pat.id) {
-            let ty = ty::node_id_to_monotype(ccx.tcx, pat.id);
+            let ty = node_id_type(bcx, pat.id);
             // FIXME: Could constrain pat_bind to make this
             // check unnecessary.
             check (type_has_static_size(ccx, ty));
@@ -735,9 +753,8 @@ fn bind_irrefutable_pat(bcx: @block_ctxt, pat: @ast::pat, val: ValueRef,
         }
       }
       ast::pat_rec(fields, _) {
-        let rec_ty = ty::node_id_to_monotype(ccx.tcx, pat.id);
-        let rec_fields =
-            alt ty::struct(ccx.tcx, rec_ty) { ty::ty_rec(fields) { fields } };
+        let rec_ty = node_id_type(bcx, pat.id);
+        let rec_fields = ty::get_fields(ccx.tcx, rec_ty);
         for f: ast::field_pat in fields {
             let ix = option::get(ty::field_idx(f.ident, rec_fields));
             // how to get rid of this check?
@@ -747,7 +764,7 @@ fn bind_irrefutable_pat(bcx: @block_ctxt, pat: @ast::pat, val: ValueRef,
         }
       }
       ast::pat_tup(elems) {
-        let tup_ty = ty::node_id_to_monotype(ccx.tcx, pat.id);
+        let tup_ty = node_id_type(bcx, pat.id);
         let i = 0u;
         for elem in elems {
             // how to get rid of this check?
@@ -760,7 +777,7 @@ fn bind_irrefutable_pat(bcx: @block_ctxt, pat: @ast::pat, val: ValueRef,
       ast::pat_box(inner) {
         let box = Load(bcx, val);
         let unboxed =
-            GEPi(bcx, box, [0, back::abi::box_rc_field_body]);
+            GEPi(bcx, box, [0, abi::box_field_body]);
         bcx = bind_irrefutable_pat(bcx, inner, unboxed, true);
       }
       ast::pat_uniq(inner) {
index 03c98dfa827df708e2dcba7900a43e5efe9a8410..37e410e9d5c91c1359f9f34e771fab98f62a267a 100644 (file)
 import driver::session;
 import session::session;
 import front::attr;
-import middle::{ty, gc, resolve, debuginfo};
 import middle::freevars::*;
 import back::{link, abi, upcall};
 import syntax::{ast, ast_util, codemap};
+import ast_util::local_def;
 import syntax::visit;
 import syntax::codemap::span;
 import syntax::print::pprust::{expr_to_str, stmt_to_str, path_to_str};
@@ -32,7 +32,7 @@
 import visit::vt;
 import util::common::*;
 import lib::llvm::{llvm, mk_target_data, mk_type_names};
-import lib::llvm::llvm::{ModuleRef, ValueRef, TypeRef, BasicBlockRef};
+import lib::llvm::{ModuleRef, ValueRef, TypeRef, BasicBlockRef};
 import lib::llvm::{True, False};
 import link::{mangle_internal_name_by_type_only,
               mangle_internal_name_by_seq,
 import metadata::{csearch, cstore};
 import util::ppaux::{ty_to_str, ty_to_short_str};
 
+import shape::static_size_of_enum;
 import common::*;
 import build::*;
+import ast_map::{path, path_mod, path_name};
 
 fn type_of_1(bcx: @block_ctxt, t: ty::t) -> TypeRef {
     let cx = bcx_ccx(bcx);
@@ -61,16 +63,18 @@ fn type_of(cx: @crate_ctxt, t: ty::t) : type_has_static_size(cx, t)
 
 fn type_of_explicit_args(cx: @crate_ctxt, inputs: [ty::arg]) ->
    [TypeRef] {
-    let atys = [];
-    for arg in inputs {
+    let tcx = ccx_tcx(cx);
+    vec::map(inputs) {|arg|
         let arg_ty = arg.ty;
         // FIXME: would be nice to have a constraint on arg
         // that would obviate the need for this check
         check non_ty_var(cx, arg_ty);
         let llty = type_of_inner(cx, arg_ty);
-        atys += [arg.mode == ast::by_val ? llty : T_ptr(llty)];
+        alt ty::resolved_mode(tcx, arg.mode) {
+          ast::by_val { llty }
+          _ { T_ptr(llty) }
+        }
     }
-    ret atys;
 }
 
 
@@ -90,7 +94,7 @@ fn type_of_fn(cx: @crate_ctxt, inputs: [ty::arg],
     atys += [out_ty];
 
     // Arg 1: Environment
-    atys += [T_opaque_cbox_ptr(cx)];
+    atys += [T_opaque_box_ptr(cx)];
 
     // Args >2: ty params, if not acquired via capture...
     for bounds in params {
@@ -110,9 +114,6 @@ fn type_of_fn(cx: @crate_ctxt, inputs: [ty::arg],
 // Given a function type and a count of ty params, construct an llvm type
 fn type_of_fn_from_ty(cx: @crate_ctxt, fty: ty::t,
                       param_bounds: [ty::param_bounds]) -> TypeRef {
-    // FIXME: Check should be unnecessary, b/c it's implied
-    // by returns_non_ty_var(t). Make that a postcondition
-    // (see Issue #586)
     let ret_ty = ty::ty_fn_ret(cx.tcx, fty);
     ret type_of_fn(cx, ty::ty_fn_args(cx.tcx, fty),
                    ret_ty, param_bounds);
@@ -124,7 +125,6 @@ fn type_of_inner(cx: @crate_ctxt, t: ty::t)
 
     if cx.lltypes.contains_key(t) { ret cx.lltypes.get(t); }
     let llty = alt ty::struct(cx.tcx, t) {
-      ty::ty_native(_) { T_ptr(T_i8()) }
       ty::ty_nil { T_nil() }
       ty::ty_bot {
         T_nil() /* ...I guess? */
@@ -193,7 +193,7 @@ fn type_of_inner(cx: @crate_ctxt, t: ty::t)
         T_struct(tys)
       }
       ty::ty_opaque_closure_ptr(_) {
-        T_opaque_cbox_ptr(cx)
+        T_opaque_box_ptr(cx)
       }
       ty::ty_constr(subt,_) {
         // FIXME: could be a constraint on ty_fn
@@ -223,13 +223,12 @@ fn type_of_enum(cx: @crate_ctxt, did: ast::def_id, t: ty::t)
     }
 }
 
-fn type_of_ty_param_bounds_and_ty(lcx: @local_ctxt,
-                                 tpt: ty::ty_param_bounds_and_ty) -> TypeRef {
-    let cx = lcx.ccx;
+fn type_of_ty_param_bounds_and_ty
+    (ccx: @crate_ctxt, tpt: ty::ty_param_bounds_and_ty) -> TypeRef {
     let t = tpt.ty;
-    alt ty::struct(cx.tcx, t) {
+    alt ty::struct(ccx.tcx, t) {
       ty::ty_fn(_) {
-        ret type_of_fn_from_ty(cx, t, *tpt.bounds);
+        ret type_of_fn_from_ty(ccx, t, *tpt.bounds);
       }
       _ {
         // fall through
@@ -238,8 +237,8 @@ fn type_of_ty_param_bounds_and_ty(lcx: @local_ctxt,
     // FIXME: could have a precondition on tpt, but that
     // doesn't work right now because one predicate can't imply
     // another
-    check (type_has_static_size(cx, t));
-    type_of(cx, t)
+    check type_has_static_size(ccx, t);
+    type_of(ccx, t)
 }
 
 fn type_of_or_i8(bcx: @block_ctxt, typ: ty::t) -> TypeRef {
@@ -287,17 +286,17 @@ fn log_fn_time(ccx: @crate_ctxt, name: str, start: time::timeval,
 }
 
 
-fn decl_fn(llmod: ModuleRef, name: str, cc: uint, llty: TypeRef) ->
-    ValueRef {
-    let llfn: ValueRef =
-        str::as_buf(name, {|buf|
-            llvm::LLVMGetOrInsertFunction(llmod, buf, llty) });
-    llvm::LLVMSetFunctionCallConv(llfn, cc as c_uint);
+fn decl_fn(llmod: ModuleRef, name: str, cc: lib::llvm::CallConv,
+           llty: TypeRef) -> ValueRef {
+    let llfn: ValueRef = str::as_buf(name, {|buf|
+        llvm::LLVMGetOrInsertFunction(llmod, buf, llty)
+    });
+    lib::llvm::SetFunctionCallConv(llfn, cc);
     ret llfn;
 }
 
 fn decl_cdecl_fn(llmod: ModuleRef, name: str, llty: TypeRef) -> ValueRef {
-    ret decl_fn(llmod, name, lib::llvm::LLVMCCallConv, llty);
+    ret decl_fn(llmod, name, lib::llvm::CCallConv, llty);
 }
 
 
@@ -306,13 +305,12 @@ fn decl_cdecl_fn(llmod: ModuleRef, name: str, llty: TypeRef) -> ValueRef {
 fn decl_internal_cdecl_fn(llmod: ModuleRef, name: str, llty: TypeRef) ->
    ValueRef {
     let llfn = decl_cdecl_fn(llmod, name, llty);
-    llvm::LLVMSetLinkage(llfn,
-                         lib::llvm::LLVMInternalLinkage as llvm::Linkage);
+    lib::llvm::SetLinkage(llfn, lib::llvm::InternalLinkage);
     ret llfn;
 }
 
 fn get_extern_fn(externs: hashmap<str, ValueRef>, llmod: ModuleRef, name: str,
-                 cc: uint, ty: TypeRef) -> ValueRef {
+                 cc: lib::llvm::CallConv, ty: TypeRef) -> ValueRef {
     if externs.contains_key(name) { ret externs.get(name); }
     let f = decl_fn(llmod, name, cc, ty);
     externs.insert(name, f);
@@ -331,12 +329,11 @@ fn get_simple_extern_fn(cx: @block_ctxt,
                         externs: hashmap<str, ValueRef>,
                         llmod: ModuleRef,
                         name: str, n_args: int) -> ValueRef {
-    let ccx = cx.fcx.lcx.ccx;
+    let ccx = cx.fcx.ccx;
     let inputs = vec::init_elt::<TypeRef>(n_args as uint, ccx.int_type);
     let output = ccx.int_type;
     let t = T_fn(inputs, output);
-    ret get_extern_fn(externs, llmod, name,
-                      lib::llvm::LLVMCCallConv, t);
+    ret get_extern_fn(externs, llmod, name, lib::llvm::CCallConv, t);
 }
 
 fn trans_native_call(cx: @block_ctxt, externs: hashmap<str, ValueRef>,
@@ -352,14 +349,9 @@ fn trans_native_call(cx: @block_ctxt, externs: hashmap<str, ValueRef>,
     ret Call(cx, llnative, call_args);
 }
 
-fn trans_free_if_not_gc(cx: @block_ctxt, v: ValueRef) -> @block_ctxt {
-    let ccx = bcx_ccx(cx);
-    if !ccx.sess.opts.do_gc {
-        Call(cx, ccx.upcalls.free,
-             [PointerCast(cx, v, T_ptr(T_i8())),
-              C_int(bcx_ccx(cx), 0)]);
-    }
-    ret cx;
+fn trans_free(cx: @block_ctxt, v: ValueRef) -> @block_ctxt {
+    Call(cx, bcx_ccx(cx).upcalls.free, [PointerCast(cx, v, T_ptr(T_i8()))]);
+    cx
 }
 
 fn trans_shared_free(cx: @block_ctxt, v: ValueRef) -> @block_ctxt {
@@ -369,22 +361,15 @@ fn trans_shared_free(cx: @block_ctxt, v: ValueRef) -> @block_ctxt {
 }
 
 fn umax(cx: @block_ctxt, a: ValueRef, b: ValueRef) -> ValueRef {
-    let cond = ICmp(cx, lib::llvm::LLVMIntULT, a, b);
+    let cond = ICmp(cx, lib::llvm::IntULT, a, b);
     ret Select(cx, cond, b, a);
 }
 
 fn umin(cx: @block_ctxt, a: ValueRef, b: ValueRef) -> ValueRef {
-    let cond = ICmp(cx, lib::llvm::LLVMIntULT, a, b);
+    let cond = ICmp(cx, lib::llvm::IntULT, a, b);
     ret Select(cx, cond, a, b);
 }
 
-fn align_to(cx: @block_ctxt, off: ValueRef, align: ValueRef) -> ValueRef {
-    let mask = Sub(cx, align, C_int(bcx_ccx(cx), 1));
-    let bumped = Add(cx, off, mask);
-    ret And(cx, bumped, Not(cx, mask));
-}
-
-
 // Returns the real size of the given type for the current target.
 fn llsize_of_real(cx: @crate_ctxt, t: TypeRef) -> uint {
     ret llvm::LLVMStoreSizeOfType(cx.td.lltd, t) as uint;
@@ -489,37 +474,6 @@ fn simplifier(ccx: @crate_ctxt, typ: ty::t) -> ty::t {
     ret ty::fold_ty(ccx.tcx, ty::fm_general(bind simplifier(ccx, _)), typ);
 }
 
-
-// Computes the size of the data part of a non-dynamically-sized enum.
-fn static_size_of_enum(cx: @crate_ctxt, t: ty::t)
-    : type_has_static_size(cx, t) -> uint {
-    if cx.enum_sizes.contains_key(t) { ret cx.enum_sizes.get(t); }
-    alt ty::struct(cx.tcx, t) {
-      ty::ty_enum(tid, subtys) {
-        // Compute max(variant sizes).
-
-        let max_size = 0u;
-        let variants = ty::enum_variants(cx.tcx, tid);
-        for variant: ty::variant_info in *variants {
-            let tup_ty = simplify_type(cx, ty::mk_tup(cx.tcx, variant.args));
-            // Perform any type parameter substitutions.
-
-            tup_ty = ty::substitute_type_params(cx.tcx, subtys, tup_ty);
-            // Here we possibly do a recursive call.
-
-            // FIXME: Avoid this check. Since the parent has static
-            // size, any field must as well. There should be a way to
-            // express that with constrained types.
-            check (type_has_static_size(cx, tup_ty));
-            let this_size = llsize_of_real(cx, type_of(cx, tup_ty));
-            if max_size < this_size { max_size = this_size; }
-        }
-        cx.enum_sizes.insert(t, max_size);
-        ret max_size;
-      }
-    }
-}
-
 fn dynamic_size_of(cx: @block_ctxt, t: ty::t) -> result {
     fn align_elements(cx: @block_ctxt, elts: [ty::t]) -> result {
         //
@@ -600,6 +554,9 @@ fn align_elements(cx: @block_ctxt, elts: [ty::t]) -> result {
             } else { max_size_val };
         ret rslt(bcx, total_size);
       }
+      // Precondition?
+      _ { bcx_tcx(cx).sess.fatal("trans::dynamic_size_of alled on something \
+            with static size"); }
     }
 }
 
@@ -634,6 +591,8 @@ fn dynamic_align_of(cx: @block_ctxt, t: ty::t) -> result {
         }
         ret rslt(bcx, a);
       }
+      _ { bcx_tcx(cx).sess.bug("trans::dynamic_align_of called on \
+            something with static size"); }
     }
 }
 
@@ -792,54 +751,54 @@ fn trans_shared_malloc(cx: @block_ctxt, llptr_ty: TypeRef, llsize: ValueRef)
     ret rslt(cx, PointerCast(cx, rval, llptr_ty));
 }
 
-// trans_malloc_boxed_raw: expects an unboxed type and returns a pointer to
-// enough space for something of that type, along with space for a reference
-// count; in other words, it allocates a box for something of that type.
-fn trans_malloc_boxed_raw(cx: @block_ctxt, t: ty::t) -> result {
-    let bcx = cx;
-
-    // Synthesize a fake box type structurally so we have something
-    // to measure the size of.
-
-    // We synthesize two types here because we want both the type of the
-    // pointer and the pointee.  boxed_body is the type that we measure the
-    // size of; box_ptr is the type that's converted to a TypeRef and used as
-    // the pointer cast target in trans_raw_malloc.
+// Returns a pointer to the body for the box. The box may be an opaque
+// box. The result will be casted to the type of body_t, if it is statically
+// known.
+//
+// The runtime equivalent is box_body() in "rust_internal.h".
+fn opaque_box_body(bcx: @block_ctxt,
+                      body_t: ty::t,
+                      boxptr: ValueRef) -> ValueRef {
+    let ccx = bcx_ccx(bcx);
+    let boxptr = PointerCast(bcx, boxptr, T_ptr(T_box_header(ccx)));
+    let bodyptr = GEPi(bcx, boxptr, [1]);
+    if check type_has_static_size(ccx, body_t) {
+        PointerCast(bcx, bodyptr, T_ptr(type_of(ccx, body_t)))
+    } else {
+        PointerCast(bcx, bodyptr, T_ptr(T_i8()))
+    }
+}
 
-    // The mk_int here is the space being
-    // reserved for the refcount.
-    let boxed_body = ty::mk_tup(bcx_tcx(bcx), [ty::mk_int(bcx_tcx(cx)), t]);
-    let box_ptr = ty::mk_imm_box(bcx_tcx(bcx), t);
-    let r = size_of(cx, boxed_body);
-    let llsz = r.val; bcx = r.bcx;
+// trans_malloc_boxed_raw: expects an unboxed type and returns a pointer to
+// enough space for a box of that type.  This includes a rust_opaque_box
+// header.
+fn trans_malloc_boxed_raw(bcx: @block_ctxt, t: ty::t,
+                          &static_ti: option<@tydesc_info>) -> result {
+    let bcx = bcx;
+    let ccx = bcx_ccx(bcx);
 
     // Grab the TypeRef type of box_ptr, because that's what trans_raw_malloc
     // wants.
-    // FIXME: Could avoid this check with a postcondition on mk_imm_box?
-    // (requires Issue #586)
-    let ccx = bcx_ccx(bcx);
+    let box_ptr = ty::mk_imm_box(bcx_tcx(bcx), t);
     check (type_has_static_size(ccx, box_ptr));
     let llty = type_of(ccx, box_ptr);
 
-    let ti = none;
-    let tydesc_result = get_tydesc(bcx, t, true, ti);
-    let lltydesc = tydesc_result.result.val; bcx = tydesc_result.result.bcx;
+    // Get the tydesc for the body:
+    let {bcx, val: lltydesc} = get_tydesc(bcx, t, true, static_ti).result;
 
-    let rval = Call(cx, ccx.upcalls.malloc,
-                    [llsz, lltydesc]);
-    ret rslt(cx, PointerCast(cx, rval, llty));
+    // Allocate space:
+    let rval = Call(bcx, ccx.upcalls.malloc, [lltydesc]);
+    ret rslt(bcx, PointerCast(bcx, rval, llty));
 }
 
 // trans_malloc_boxed: usefully wraps trans_malloc_box_raw; allocates a box,
 // initializes the reference count to 1, and pulls out the body and rc
-fn trans_malloc_boxed(cx: @block_ctxt, t: ty::t) ->
+fn trans_malloc_boxed(bcx: @block_ctxt, t: ty::t) ->
    {bcx: @block_ctxt, box: ValueRef, body: ValueRef} {
-    let res = trans_malloc_boxed_raw(cx, t);
-    let box = res.val;
-    let rc = GEPi(res.bcx, box, [0, abi::box_rc_field_refcnt]);
-    Store(res.bcx, C_int(bcx_ccx(cx), 1), rc);
-    let body = GEPi(res.bcx, box, [0, abi::box_rc_field_body]);
-    ret {bcx: res.bcx, box: res.val, body: body};
+    let ti = none;
+    let {bcx, val:box} = trans_malloc_boxed_raw(bcx, t, ti);
+    let body = GEPi(bcx, box, [0, abi::box_field_body]);
+    ret {bcx: bcx, box: box, body: body};
 }
 
 // Type descriptor and type glue stuff
@@ -861,28 +820,19 @@ fn field_of_tydesc(cx: @block_ctxt, t: ty::t, escapes: bool, field: int) ->
 // constructing derived tydescs.
 fn linearize_ty_params(cx: @block_ctxt, t: ty::t) ->
    {params: [uint], descs: [ValueRef]} {
-    let param_vals: [ValueRef] = [];
-    let param_defs: [uint] = [];
-    type rr =
-        {cx: @block_ctxt, mutable vals: [ValueRef], mutable defs: [uint]};
-
-    fn linearizer(r: @rr, t: ty::t) {
-        alt ty::struct(bcx_tcx(r.cx), t) {
+    let param_vals = [], param_defs = [];
+    ty::walk_ty(bcx_tcx(cx), t) {|t|
+        alt ty::struct(bcx_tcx(cx), t) {
           ty::ty_param(pid, _) {
-            let seen: bool = false;
-            for d: uint in r.defs { if d == pid { seen = true; } }
-            if !seen {
-                r.vals += [r.cx.fcx.lltyparams[pid].desc];
-                r.defs += [pid];
+            if !vec::any(param_defs, {|d| d == pid}) {
+                param_vals += [cx.fcx.lltyparams[pid].desc];
+                param_defs += [pid];
             }
           }
           _ { }
         }
     }
-    let x = @{cx: cx, mutable vals: param_vals, mutable defs: param_defs};
-    let f = bind linearizer(x, _);
-    ty::walk_ty(bcx_tcx(cx), t, f);
-    ret {params: x.defs, descs: x.vals};
+    ret {params: param_defs, descs: param_vals};
 }
 
 fn trans_stack_local_derived_tydesc(cx: @block_ctxt, llsz: ValueRef,
@@ -912,7 +862,7 @@ fn trans_stack_local_derived_tydesc(cx: @block_ctxt, llsz: ValueRef,
 }
 
 fn get_derived_tydesc(cx: @block_ctxt, t: ty::t, escapes: bool,
-                      &static_ti: option::t<@tydesc_info>) -> result {
+                      &static_ti: option<@tydesc_info>) -> result {
     alt cx.fcx.derived_tydescs.find(t) {
       some(info) {
         // If the tydesc escapes in this context, the cached derived
@@ -983,7 +933,7 @@ fn get_derived_tydesc(cx: @block_ctxt, t: ty::t, escapes: bool,
 type get_tydesc_result = {kind: tydesc_kind, result: result};
 
 fn get_tydesc(cx: @block_ctxt, t: ty::t, escapes: bool,
-              &static_ti: option::t<@tydesc_info>)
+              &static_ti: option<@tydesc_info>)
    -> get_tydesc_result {
 
     // Is the supplied type a type param? If so, return the passed-in tydesc.
@@ -1018,7 +968,7 @@ fn get_static_tydesc(cx: @block_ctxt, t: ty::t, ty_params: [uint])
       some(info) { ret info; }
       none {
         bcx_ccx(cx).stats.n_static_tydescs += 1u;
-        let info = declare_tydesc(cx.fcx.lcx, t, ty_params);
+        let info = declare_tydesc(cx.fcx.ccx, t, ty_params);
         bcx_ccx(cx).tydescs.insert(t, info);
         ret info;
       }
@@ -1026,46 +976,38 @@ fn get_static_tydesc(cx: @block_ctxt, t: ty::t, ty_params: [uint])
 }
 
 fn set_no_inline(f: ValueRef) {
-    llvm::LLVMAddFunctionAttr(f,
-                              lib::llvm::LLVMNoInlineAttribute as
-                                  lib::llvm::llvm::Attribute,
+    llvm::LLVMAddFunctionAttr(f, lib::llvm::NoInlineAttribute as c_uint,
                               0u as c_uint);
 }
 
 // Tell LLVM to emit the information necessary to unwind the stack for the
 // function f.
 fn set_uwtable(f: ValueRef) {
-    llvm::LLVMAddFunctionAttr(f,
-                              lib::llvm::LLVMUWTableAttribute as
-                                  lib::llvm::llvm::Attribute,
+    llvm::LLVMAddFunctionAttr(f, lib::llvm::UWTableAttribute as c_uint,
                               0u as c_uint);
 }
 
 fn set_always_inline(f: ValueRef) {
-    llvm::LLVMAddFunctionAttr(f,
-                              lib::llvm::LLVMAlwaysInlineAttribute as
-                                  lib::llvm::llvm::Attribute,
+    llvm::LLVMAddFunctionAttr(f, lib::llvm::AlwaysInlineAttribute as c_uint,
                               0u as c_uint);
 }
 
 fn set_custom_stack_growth_fn(f: ValueRef) {
     // TODO: Remove this hack to work around the lack of u64 in the FFI.
-    llvm::LLVMAddFunctionAttr(f, 0 as lib::llvm::llvm::Attribute,
-                              1u as c_uint);
+    llvm::LLVMAddFunctionAttr(f, 0u as c_uint, 1u as c_uint);
 }
 
-fn set_glue_inlining(cx: @local_ctxt, f: ValueRef, t: ty::t) {
-    if ty::type_is_structural(cx.ccx.tcx, t) {
+fn set_glue_inlining(ccx: @crate_ctxt, f: ValueRef, t: ty::t) {
+    if ty::type_is_structural(ccx.tcx, t) {
         set_no_inline(f);
     } else { set_always_inline(f); }
 }
 
 
 // Generates the declaration for (but doesn't emit) a type descriptor.
-fn declare_tydesc(cx: @local_ctxt, t: ty::t, ty_params: [uint])
+fn declare_tydesc(ccx: @crate_ctxt, t: ty::t, ty_params: [uint])
     -> @tydesc_info {
-    log(debug, "+++ declare_tydesc " + ty_to_str(cx.ccx.tcx, t));
-    let ccx = cx.ccx;
+    log(debug, "+++ declare_tydesc " + ty_to_str(ccx.tcx, t));
     let llsize;
     let llalign;
     if check type_has_static_size(ccx, t) {
@@ -1080,64 +1022,59 @@ fn declare_tydesc(cx: @local_ctxt, t: ty::t, ty_params: [uint])
         llalign = C_int(ccx, 0);
     }
     let name;
-    if cx.ccx.sess.opts.debuginfo {
-        name = mangle_internal_name_by_type_only(cx.ccx, t, "tydesc");
+    if ccx.sess.opts.debuginfo {
+        name = mangle_internal_name_by_type_only(ccx, t, "tydesc");
         name = sanitize(name);
-    } else { name = mangle_internal_name_by_seq(cx.ccx, "tydesc"); }
-    let gvar =
-        str::as_buf(name,
-                    {|buf|
-                        llvm::LLVMAddGlobal(ccx.llmod, ccx.tydesc_type, buf)
-                    });
+    } else { name = mangle_internal_name_by_seq(ccx, "tydesc"); }
+    let gvar = str::as_buf(name, {|buf|
+        llvm::LLVMAddGlobal(ccx.llmod, ccx.tydesc_type, buf)
+    });
     let info =
         @{ty: t,
           tydesc: gvar,
           size: llsize,
           align: llalign,
-          mutable take_glue: none::<ValueRef>,
-          mutable drop_glue: none::<ValueRef>,
-          mutable free_glue: none::<ValueRef>,
-          mutable cmp_glue: none::<ValueRef>,
+          mutable take_glue: none,
+          mutable drop_glue: none,
+          mutable free_glue: none,
+          mutable cmp_glue: none,
           ty_params: ty_params};
-    log(debug, "--- declare_tydesc " + ty_to_str(cx.ccx.tcx, t));
+    log(debug, "--- declare_tydesc " + ty_to_str(ccx.tcx, t));
     ret info;
 }
 
 type glue_helper = fn@(@block_ctxt, ValueRef, ty::t);
 
-fn declare_generic_glue(cx: @local_ctxt, t: ty::t, llfnty: TypeRef, name: str)
-   -> ValueRef {
+fn declare_generic_glue(ccx: @crate_ctxt, t: ty::t, llfnty: TypeRef,
+                        name: str) -> ValueRef {
     let name = name;
     let fn_nm;
-    if cx.ccx.sess.opts.debuginfo {
-        fn_nm = mangle_internal_name_by_type_only(cx.ccx, t, "glue_" + name);
+    if ccx.sess.opts.debuginfo {
+        fn_nm = mangle_internal_name_by_type_only(ccx, t, "glue_" + name);
         fn_nm = sanitize(fn_nm);
-    } else { fn_nm = mangle_internal_name_by_seq(cx.ccx, "glue_" + name); }
-    let llfn = decl_cdecl_fn(cx.ccx.llmod, fn_nm, llfnty);
-    set_glue_inlining(cx, llfn, t);
+    } else { fn_nm = mangle_internal_name_by_seq(ccx, "glue_" + name); }
+    let llfn = decl_cdecl_fn(ccx.llmod, fn_nm, llfnty);
+    set_glue_inlining(ccx, llfn, t);
     ret llfn;
 }
 
 // FIXME: was this causing the leak?
-fn make_generic_glue_inner(cx: @local_ctxt, t: ty::t,
+fn make_generic_glue_inner(ccx: @crate_ctxt, t: ty::t,
                            llfn: ValueRef, helper: glue_helper,
                            ty_params: [uint]) -> ValueRef {
-    let fcx = new_fn_ctxt(cx, llfn);
-    llvm::LLVMSetLinkage(llfn,
-                         lib::llvm::LLVMInternalLinkage as llvm::Linkage);
-    cx.ccx.stats.n_glues_created += 1u;
+    let fcx = new_fn_ctxt(ccx, [], llfn, none);
+    lib::llvm::SetLinkage(llfn, lib::llvm::InternalLinkage);
+    ccx.stats.n_glues_created += 1u;
     // Any nontrivial glue is with values passed *by alias*; this is a
     // requirement since in many contexts glue is invoked indirectly and
     // the caller has no idea if it's dealing with something that can be
     // passed by value.
 
-    let ccx = cx.ccx;
-    let llty =
-        if check type_has_static_size(ccx, t) {
-            T_ptr(type_of(ccx, t))
-        } else { T_ptr(T_i8()) };
+    let llty = if check type_has_static_size(ccx, t) {
+        T_ptr(type_of(ccx, t))
+    } else { T_ptr(T_i8()) };
 
-    let ty_param_count = vec::len::<uint>(ty_params);
+    let ty_param_count = vec::len(ty_params);
     let lltyparams = llvm::LLVMGetParam(llfn, 2u as c_uint);
     let load_env_bcx = new_raw_block_ctxt(fcx, fcx.llloadenv);
     let lltydescs = [mutable];
@@ -1151,7 +1088,7 @@ fn make_generic_glue_inner(cx: @local_ctxt, t: ty::t,
 
     fcx.lltyparams = vec::map_mut(lltydescs, {|d| {desc: d, dicts: none}});
 
-    let bcx = new_top_block_ctxt(fcx);
+    let bcx = new_top_block_ctxt(fcx, none);
     let lltop = bcx.llbb;
     let llrawptr0 = llvm::LLVMGetParam(llfn, 3u as c_uint);
     let llval0 = BitCast(bcx, llrawptr0, llty);
@@ -1160,17 +1097,17 @@ fn make_generic_glue_inner(cx: @local_ctxt, t: ty::t,
     ret llfn;
 }
 
-fn make_generic_glue(cx: @local_ctxt, t: ty::t, llfn: ValueRef,
-                     helper: glue_helper, ty_params: [uint], name: str) ->
-   ValueRef {
-    if !cx.ccx.sess.opts.stats {
-        ret make_generic_glue_inner(cx, t, llfn, helper, ty_params);
+fn make_generic_glue(ccx: @crate_ctxt, t: ty::t, llfn: ValueRef,
+                     helper: glue_helper, ty_params: [uint], name: str)
+    -> ValueRef {
+    if !ccx.sess.opts.stats {
+        ret make_generic_glue_inner(ccx, t, llfn, helper, ty_params);
     }
 
     let start = time::get_time();
-    let llval = make_generic_glue_inner(cx, t, llfn, helper, ty_params);
+    let llval = make_generic_glue_inner(ccx, t, llfn, helper, ty_params);
     let end = time::get_time();
-    log_fn_time(cx.ccx, "glue " + name + " " + ty_to_short_str(cx.ccx.tcx, t),
+    log_fn_time(ccx, "glue " + name + " " + ty_to_short_str(ccx.tcx, t),
                 start, end);
     ret llval;
 }
@@ -1227,8 +1164,7 @@ fn emit_tydescs(ccx: @crate_ctxt) {
         let gvar = ti.tydesc;
         llvm::LLVMSetInitializer(gvar, tydesc);
         llvm::LLVMSetGlobalConstant(gvar, True);
-        llvm::LLVMSetLinkage(gvar,
-                             lib::llvm::LLVMInternalLinkage as llvm::Linkage);
+        lib::llvm::SetLinkage(gvar, lib::llvm::InternalLinkage);
     };
 }
 
@@ -1277,8 +1213,8 @@ fn make_take_glue(cx: @block_ctxt, v: ValueRef, t: ty::t) {
 
 fn incr_refcnt_of_boxed(cx: @block_ctxt, box_ptr: ValueRef) -> @block_ctxt {
     let ccx = bcx_ccx(cx);
-    let rc_ptr =
-        GEPi(cx, box_ptr, [0, abi::box_rc_field_refcnt]);
+    maybe_validate_box(cx, box_ptr);
+    let rc_ptr = GEPi(cx, box_ptr, [0, abi::box_field_refcnt]);
     let rc = Load(cx, rc_ptr);
     rc = Add(cx, rc, C_int(ccx, 1));
     Store(cx, rc, rc_ptr);
@@ -1289,9 +1225,9 @@ fn free_box(bcx: @block_ctxt, v: ValueRef, t: ty::t) -> @block_ctxt {
     ret alt ty::struct(bcx_tcx(bcx), t) {
       ty::ty_box(body_mt) {
         let v = PointerCast(bcx, v, type_of_1(bcx, t));
-        let body = GEPi(bcx, v, [0, abi::box_rc_field_body]);
+        let body = GEPi(bcx, v, [0, abi::box_field_body]);
         let bcx = drop_ty(bcx, body, body_mt.ty);
-        trans_free_if_not_gc(bcx, v)
+        trans_free(bcx, v)
       }
 
       _ { fail "free_box invoked with non-box type"; }
@@ -1320,13 +1256,13 @@ fn make_free_glue(bcx: @block_ctxt, v: ValueRef, t: ty::t) {
         let ccx = bcx_ccx(bcx);
         let llbox_ty = T_opaque_iface_ptr(ccx);
         let b = PointerCast(bcx, v, llbox_ty);
-        let body = GEPi(bcx, b, [0, abi::box_rc_field_body]);
+        let body = GEPi(bcx, b, [0, abi::box_field_body]);
         let tydescptr = GEPi(bcx, body, [0, 0]);
         let tydesc = Load(bcx, tydescptr);
         let ti = none;
         call_tydesc_glue_full(bcx, body, tydesc,
                               abi::tydesc_field_drop_glue, ti);
-        trans_free_if_not_gc(bcx, b)
+        trans_free(bcx, b)
       }
       ty::ty_send_type {
         // sendable type descriptors are basically unique pointers,
@@ -1400,7 +1336,7 @@ fn trans_res_drop(cx: @block_ctxt, rs: ValueRef, did: ast::def_id,
     let dtor_addr = common::get_res_dtor(ccx, did, inner_t);
     let args = [cx.fcx.llretptr, null_env_ptr(cx)];
     for tp: ty::t in tps {
-        let ti: option::t<@tydesc_info> = none;
+        let ti: option<@tydesc_info> = none;
         let td = get_tydesc(cx, tp, false, ti).result;
         args += [td.val];
         cx = td.bcx;
@@ -1421,9 +1357,23 @@ fn trans_res_drop(cx: @block_ctxt, rs: ValueRef, did: ast::def_id,
     ret next_cx;
 }
 
+fn maybe_validate_box(_cx: @block_ctxt, _box_ptr: ValueRef) {
+    // Uncomment this when debugging annoying use-after-free
+    // bugs.  But do not commit with this uncommented!  Big performance hit.
+
+    // let cx = _cx, box_ptr = _box_ptr;
+    // let ccx = bcx_ccx(cx);
+    // warn_not_to_commit(ccx, "validate_box() is uncommented");
+    // let raw_box_ptr = PointerCast(cx, box_ptr, T_ptr(T_i8()));
+    // Call(cx, ccx.upcalls.validate_box, [raw_box_ptr]);
+}
+
 fn decr_refcnt_maybe_free(cx: @block_ctxt, box_ptr: ValueRef, t: ty::t)
     -> @block_ctxt {
     let ccx = bcx_ccx(cx);
+
+    maybe_validate_box(cx, box_ptr);
+
     let rc_adj_cx = new_sub_block_ctxt(cx, "rc--");
     let free_cx = new_sub_block_ctxt(cx, "free");
     let next_cx = new_sub_block_ctxt(cx, "next");
@@ -1431,19 +1381,17 @@ fn decr_refcnt_maybe_free(cx: @block_ctxt, box_ptr: ValueRef, t: ty::t)
     let box_ptr = PointerCast(cx, box_ptr, llbox_ty);
     let null_test = IsNull(cx, box_ptr);
     CondBr(cx, null_test, next_cx.llbb, rc_adj_cx.llbb);
-    let rc_ptr =
-        GEPi(rc_adj_cx, box_ptr, [0, abi::box_rc_field_refcnt]);
+    let rc_ptr = GEPi(rc_adj_cx, box_ptr, [0, abi::box_field_refcnt]);
     let rc = Load(rc_adj_cx, rc_ptr);
     rc = Sub(rc_adj_cx, rc, C_int(ccx, 1));
     Store(rc_adj_cx, rc, rc_ptr);
-    let zero_test = ICmp(rc_adj_cx, lib::llvm::LLVMIntEQ, C_int(ccx, 0), rc);
+    let zero_test = ICmp(rc_adj_cx, lib::llvm::IntEQ, C_int(ccx, 0), rc);
     CondBr(rc_adj_cx, zero_test, free_cx.llbb, next_cx.llbb);
     let free_cx = free_ty(free_cx, box_ptr, t);
     Br(free_cx, next_cx.llbb);
     ret next_cx;
 }
 
-
 // Structural comparison: a rather involved form of glue.
 fn maybe_name_value(cx: @crate_ctxt, v: ValueRef, s: str) {
     if cx.sess.opts.save_temps {
@@ -1471,11 +1419,6 @@ fn compare_scalar_types(cx: @block_ctxt, lhs: ValueRef, rhs: ValueRef,
                             "attempt to compare values of type type"),
                  C_nil());
       }
-      ty::ty_native(_) {
-        let cx = trans_fail(cx, none,
-                            "attempt to compare values of type native");
-        ret rslt(cx, C_nil());
-      }
       _ {
         // Should never get here, because t is scalar.
         bcx_ccx(cx).sess.bug("non-scalar type passed to \
@@ -1488,6 +1431,11 @@ fn compare_scalar_types(cx: @block_ctxt, lhs: ValueRef, rhs: ValueRef,
 // A helper function to do the actual comparison of scalar values.
 fn compare_scalar_values(cx: @block_ctxt, lhs: ValueRef, rhs: ValueRef,
                          nt: scalar_type, op: ast::binop) -> ValueRef {
+    fn die_(cx: @block_ctxt) -> ! {
+        bcx_tcx(cx).sess.bug("compare_scalar_values: must be a\
+          comparison operator");
+    }
+    let die = bind die_(cx);
     alt nt {
       nil_type {
         // We don't need to do actual comparisons for nil.
@@ -1495,38 +1443,43 @@ fn compare_scalar_values(cx: @block_ctxt, lhs: ValueRef, rhs: ValueRef,
         alt op {
           ast::eq | ast::le | ast::ge { ret C_bool(true); }
           ast::ne | ast::lt | ast::gt { ret C_bool(false); }
+          // refinements would be nice
+          _ { die(); }
         }
       }
       floating_point {
         let cmp = alt op {
-          ast::eq { lib::llvm::LLVMRealOEQ }
-          ast::ne { lib::llvm::LLVMRealUNE }
-          ast::lt { lib::llvm::LLVMRealOLT }
-          ast::le { lib::llvm::LLVMRealOLE }
-          ast::gt { lib::llvm::LLVMRealOGT }
-          ast::ge { lib::llvm::LLVMRealOGE }
+          ast::eq { lib::llvm::RealOEQ }
+          ast::ne { lib::llvm::RealUNE }
+          ast::lt { lib::llvm::RealOLT }
+          ast::le { lib::llvm::RealOLE }
+          ast::gt { lib::llvm::RealOGT }
+          ast::ge { lib::llvm::RealOGE }
+          _ { die(); }
         };
         ret FCmp(cx, cmp, lhs, rhs);
       }
       signed_int {
         let cmp = alt op {
-          ast::eq { lib::llvm::LLVMIntEQ }
-          ast::ne { lib::llvm::LLVMIntNE }
-          ast::lt { lib::llvm::LLVMIntSLT }
-          ast::le { lib::llvm::LLVMIntSLE }
-          ast::gt { lib::llvm::LLVMIntSGT }
-          ast::ge { lib::llvm::LLVMIntSGE }
+          ast::eq { lib::llvm::IntEQ }
+          ast::ne { lib::llvm::IntNE }
+          ast::lt { lib::llvm::IntSLT }
+          ast::le { lib::llvm::IntSLE }
+          ast::gt { lib::llvm::IntSGT }
+          ast::ge { lib::llvm::IntSGE }
+          _ { die(); }
         };
         ret ICmp(cx, cmp, lhs, rhs);
       }
       unsigned_int {
         let cmp = alt op {
-          ast::eq { lib::llvm::LLVMIntEQ }
-          ast::ne { lib::llvm::LLVMIntNE }
-          ast::lt { lib::llvm::LLVMIntULT }
-          ast::le { lib::llvm::LLVMIntULE }
-          ast::gt { lib::llvm::LLVMIntUGT }
-          ast::ge { lib::llvm::LLVMIntUGE }
+          ast::eq { lib::llvm::IntEQ }
+          ast::ne { lib::llvm::IntNE }
+          ast::lt { lib::llvm::IntULT }
+          ast::le { lib::llvm::IntULE }
+          ast::gt { lib::llvm::IntUGT }
+          ast::ge { lib::llvm::IntUGE }
+          _ { die(); }
         };
         ret ICmp(cx, cmp, lhs, rhs);
       }
@@ -1583,6 +1536,8 @@ fn iter_variant(cx: @block_ctxt, a_tup: ValueRef,
                 j += 1u;
             }
           }
+          // Precondition?
+          _ { bcx_tcx(cx).sess.bug("iter_variant: not a function type"); }
         }
         ret cx;
     }
@@ -1663,7 +1618,7 @@ fn iter_variant(cx: @block_ctxt, a_tup: ValueRef,
 }
 
 fn lazily_emit_all_tydesc_glue(cx: @block_ctxt,
-                               static_ti: option::t<@tydesc_info>) {
+                               static_ti: option<@tydesc_info>) {
     lazily_emit_tydesc_glue(cx, abi::tydesc_field_take_glue, static_ti);
     lazily_emit_tydesc_glue(cx, abi::tydesc_field_drop_glue, static_ti);
     lazily_emit_tydesc_glue(cx, abi::tydesc_field_free_glue, static_ti);
@@ -1672,13 +1627,14 @@ fn lazily_emit_all_tydesc_glue(cx: @block_ctxt,
 
 fn lazily_emit_all_generic_info_tydesc_glues(cx: @block_ctxt,
                                              gi: generic_info) {
-    for ti: option::t<@tydesc_info> in gi.static_tis {
+    for ti: option<@tydesc_info> in gi.static_tis {
         lazily_emit_all_tydesc_glue(cx, ti);
     }
 }
 
 fn lazily_emit_tydesc_glue(cx: @block_ctxt, field: int,
-                           static_ti: option::t<@tydesc_info>) {
+                           static_ti: option<@tydesc_info>) {
+    let ccx = cx.fcx.ccx;
     alt static_ti {
       none { }
       some(ti) {
@@ -1688,12 +1644,10 @@ fn lazily_emit_tydesc_glue(cx: @block_ctxt, field: int,
               none {
                 #debug("+++ lazily_emit_tydesc_glue TAKE %s",
                        ty_to_str(bcx_tcx(cx), ti.ty));
-                let lcx = cx.fcx.lcx;
-                let glue_fn =
-                    declare_generic_glue(lcx, ti.ty, T_glue_fn(lcx.ccx),
-                                         "take");
-                ti.take_glue = some::<ValueRef>(glue_fn);
-                make_generic_glue(lcx, ti.ty, glue_fn,
+                let glue_fn = declare_generic_glue
+                    (ccx, ti.ty, T_glue_fn(ccx), "take");
+                ti.take_glue = some(glue_fn);
+                make_generic_glue(ccx, ti.ty, glue_fn,
                                   make_take_glue,
                                   ti.ty_params, "take");
                 #debug("--- lazily_emit_tydesc_glue TAKE %s",
@@ -1706,12 +1660,10 @@ fn lazily_emit_tydesc_glue(cx: @block_ctxt, field: int,
               none {
                 #debug("+++ lazily_emit_tydesc_glue DROP %s",
                        ty_to_str(bcx_tcx(cx), ti.ty));
-                let lcx = cx.fcx.lcx;
                 let glue_fn =
-                    declare_generic_glue(lcx, ti.ty, T_glue_fn(lcx.ccx),
-                                         "drop");
-                ti.drop_glue = some::<ValueRef>(glue_fn);
-                make_generic_glue(lcx, ti.ty, glue_fn,
+                    declare_generic_glue(ccx, ti.ty, T_glue_fn(ccx), "drop");
+                ti.drop_glue = some(glue_fn);
+                make_generic_glue(ccx, ti.ty, glue_fn,
                                   make_drop_glue,
                                   ti.ty_params, "drop");
                 #debug("--- lazily_emit_tydesc_glue DROP %s",
@@ -1724,12 +1676,10 @@ fn lazily_emit_tydesc_glue(cx: @block_ctxt, field: int,
               none {
                 #debug("+++ lazily_emit_tydesc_glue FREE %s",
                        ty_to_str(bcx_tcx(cx), ti.ty));
-                let lcx = cx.fcx.lcx;
                 let glue_fn =
-                    declare_generic_glue(lcx, ti.ty, T_glue_fn(lcx.ccx),
-                                         "free");
-                ti.free_glue = some::<ValueRef>(glue_fn);
-                make_generic_glue(lcx, ti.ty, glue_fn,
+                    declare_generic_glue(ccx, ti.ty, T_glue_fn(ccx), "free");
+                ti.free_glue = some(glue_fn);
+                make_generic_glue(ccx, ti.ty, glue_fn,
                                   make_free_glue,
                                   ti.ty_params, "free");
                 #debug("--- lazily_emit_tydesc_glue FREE %s",
@@ -1753,7 +1703,7 @@ fn lazily_emit_tydesc_glue(cx: @block_ctxt, field: int,
 }
 
 fn call_tydesc_glue_full(cx: @block_ctxt, v: ValueRef, tydesc: ValueRef,
-                         field: int, static_ti: option::t<@tydesc_info>) {
+                         field: int, static_ti: option<@tydesc_info>) {
     lazily_emit_tydesc_glue(cx, field, static_ti);
 
     let static_glue_fn = none;
@@ -1790,7 +1740,7 @@ fn call_tydesc_glue_full(cx: @block_ctxt, v: ValueRef, tydesc: ValueRef,
 
 fn call_tydesc_glue(cx: @block_ctxt, v: ValueRef, t: ty::t, field: int) ->
    @block_ctxt {
-    let ti: option::t<@tydesc_info> = none::<@tydesc_info>;
+    let ti: option<@tydesc_info> = none::<@tydesc_info>;
     let {bcx: bcx, val: td} = get_tydesc(cx, t, false, ti).result;
     call_tydesc_glue_full(bcx, v, td, field, ti);
     ret bcx;
@@ -1855,6 +1805,8 @@ fn drop_ty_immediate(bcx: @block_ctxt, v: ValueRef, t: ty::t) -> @block_ctxt {
     alt ty::struct(bcx_tcx(bcx), t) {
       ty::ty_uniq(_) | ty::ty_vec(_) | ty::ty_str { free_ty(bcx, v, t) }
       ty::ty_box(_) | ty::ty_iface(_, _) { decr_refcnt_maybe_free(bcx, v, t) }
+      // Precondition?
+      _ { bcx_tcx(bcx).sess.bug("drop_ty_immediate: non-box ty"); }
     }
 }
 
@@ -1940,7 +1892,7 @@ fn copy_val(cx: @block_ctxt, action: copy_action, dst: ValueRef,
         let next_cx = new_sub_block_ctxt(cx, "next");
         let dstcmp = load_if_immediate(cx, dst, t);
         let self_assigning =
-            ICmp(cx, lib::llvm::LLVMIntNE,
+            ICmp(cx, lib::llvm::IntNE,
                  PointerCast(cx, dstcmp, val_ty(src)), src);
         CondBr(cx, self_assigning, do_copy_cx.llbb, next_cx.llbb);
         do_copy_cx = copy_val_no_check(do_copy_cx, action, dst, src, t);
@@ -1953,7 +1905,7 @@ fn copy_val(cx: @block_ctxt, action: copy_action, dst: ValueRef,
 fn copy_val_no_check(bcx: @block_ctxt, action: copy_action, dst: ValueRef,
                      src: ValueRef, t: ty::t) -> @block_ctxt {
     let ccx = bcx_ccx(bcx), bcx = bcx;
-    if ty::type_is_scalar(ccx.tcx, t) || ty::type_is_native(ccx.tcx, t) {
+    if ty::type_is_scalar(ccx.tcx, t) {
         Store(bcx, src, dst);
         ret bcx;
     }
@@ -1983,7 +1935,7 @@ fn move_val(cx: @block_ctxt, action: copy_action, dst: ValueRef,
             src: lval_result, t: ty::t) -> @block_ctxt {
     let src_val = src.val;
     let tcx = bcx_tcx(cx), cx = cx;
-    if ty::type_is_scalar(tcx, t) || ty::type_is_native(tcx, t) {
+    if ty::type_is_scalar(tcx, t) {
         if src.kind == owned { src_val = Load(cx, src_val); }
         Store(cx, src_val, dst);
         ret cx;
@@ -2015,8 +1967,11 @@ fn store_temp_expr(cx: @block_ctxt, action: copy_action, dst: ValueRef,
     -> @block_ctxt {
     // Lvals in memory are not temporaries. Copy them.
     if src.kind != temporary && !last_use {
-        let v = src.kind == owned ? load_if_immediate(cx, src.val, t)
-                                  : src.val;
+        let v = if src.kind == owned {
+                    load_if_immediate(cx, src.val, t)
+                } else {
+                    src.val
+                };
         ret copy_val(cx, action, dst, v, t);
     }
     ret move_val(cx, action, dst, src, t);
@@ -2045,19 +2000,13 @@ fn trans_lit(cx: @block_ctxt, lit: ast::lit, dest: dest) -> @block_ctxt {
     }
 }
 
-
-// Converts an annotation to a type
-fn node_id_type(cx: @crate_ctxt, id: ast::node_id) -> ty::t {
-    ret ty::node_id_to_monotype(cx.tcx, id);
-}
-
 fn trans_unary(bcx: @block_ctxt, op: ast::unop, e: @ast::expr,
                un_expr: @ast::expr, dest: dest) -> @block_ctxt {
     // Check for user-defined method call
     alt bcx_ccx(bcx).method_map.find(un_expr.id) {
       some(origin) {
         let callee_id = ast_util::op_expr_callee_id(un_expr);
-        let fty = ty::node_id_to_monotype(bcx_tcx(bcx), callee_id);
+        let fty = ty::node_id_to_type(bcx_tcx(bcx), callee_id);
         ret trans_call_inner(bcx, fty, {|bcx|
             impl::trans_method_callee(bcx, callee_id, e, origin)
         }, [], un_expr.id, dest);
@@ -2066,7 +2015,7 @@ fn trans_unary(bcx: @block_ctxt, op: ast::unop, e: @ast::expr,
     }
 
     if dest == ignore { ret trans_expr(bcx, e, ignore); }
-    let e_ty = ty::expr_ty(bcx_tcx(bcx), e);
+    let e_ty = expr_ty(bcx, e);
     alt op {
       ast::not {
         let {bcx, val} = trans_temp_expr(bcx, e);
@@ -2118,6 +2067,9 @@ fn trans_compare(cx: @block_ctxt, op: ast::binop, lhs: ValueRef,
       ast::eq | ast::ne { llop = C_u8(abi::cmp_glue_op_eq); }
       ast::lt | ast::ge { llop = C_u8(abi::cmp_glue_op_lt); }
       ast::le | ast::gt { llop = C_u8(abi::cmp_glue_op_le); }
+      // Precondition?
+      _ { bcx_tcx(cx).sess.bug("trans_compare got\
+              non-comparison-op"); }
     }
 
     let rs = call_cmp_glue(cx, lhs, rhs, rhs_t, llop);
@@ -2128,6 +2080,8 @@ fn trans_compare(cx: @block_ctxt, op: ast::binop, lhs: ValueRef,
       ast::ne | ast::ge | ast::gt {
         ret rslt(rs.bcx, Not(rs.bcx, rs.val));
       }
+      _ { bcx_tcx(cx).sess.bug("trans_compare got\
+              non-comparison-op"); }
     }
 }
 
@@ -2187,7 +2141,7 @@ fn trans_eager_binop(cx: @block_ctxt, op: ast::binop, lhs: ValueRef,
 fn trans_assign_op(bcx: @block_ctxt, ex: @ast::expr, op: ast::binop,
                    dst: @ast::expr, src: @ast::expr) -> @block_ctxt {
     let tcx = bcx_tcx(bcx);
-    let t = ty::expr_ty(tcx, src);
+    let t = expr_ty(bcx, src);
     let lhs_res = trans_lval(bcx, dst);
     assert (lhs_res.kind == owned);
 
@@ -2195,7 +2149,7 @@ fn trans_assign_op(bcx: @block_ctxt, ex: @ast::expr, op: ast::binop,
     alt bcx_ccx(bcx).method_map.find(ex.id) {
       some(origin) {
         let callee_id = ast_util::op_expr_callee_id(ex);
-        let fty = ty::node_id_to_monotype(bcx_tcx(bcx), callee_id);
+        let fty = ty::node_id_to_type(tcx, callee_id);
         ret trans_call_inner(bcx, fty, {|bcx|
             // FIXME provide the already-computed address, not the expr
             impl::trans_method_callee(bcx, callee_id, dst, origin)
@@ -2237,7 +2191,7 @@ fn autoderef(cx: @block_ctxt, v: ValueRef, t: ty::t) -> result_t {
     while true {
         alt ty::struct(ccx.tcx, t1) {
           ty::ty_box(mt) {
-            let body = GEPi(cx, v1, [0, abi::box_rc_field_body]);
+            let body = GEPi(cx, v1, [0, abi::box_field_body]);
             t1 = mt.ty;
 
             // Since we're changing levels of box indirection, we may have
@@ -2278,9 +2232,12 @@ fn autoderef(cx: @block_ctxt, v: ValueRef, t: ty::t) -> result_t {
     ret {bcx: cx, val: v1, ty: t1};
 }
 
-fn trans_lazy_binop(bcx: @block_ctxt, op: ast::binop, a: @ast::expr,
+// refinement types would obviate the need for this
+enum lazy_binop_ty { lazy_and, lazy_or }
+
+fn trans_lazy_binop(bcx: @block_ctxt, op: lazy_binop_ty, a: @ast::expr,
                     b: @ast::expr, dest: dest) -> @block_ctxt {
-    let is_and = alt op { ast::and { true } ast::or { false } };
+    let is_and = alt op { lazy_and { true } lazy_or { false } };
     let lhs_res = trans_temp_expr(bcx, a);
     if lhs_res.bcx.unreachable { ret lhs_res.bcx; }
     let rhs_cx = new_scope_block_ctxt(lhs_res.bcx, "rhs");
@@ -2317,7 +2274,7 @@ fn trans_binary(bcx: @block_ctxt, op: ast::binop, lhs: @ast::expr,
     alt bcx_ccx(bcx).method_map.find(ex.id) {
       some(origin) {
         let callee_id = ast_util::op_expr_callee_id(ex);
-        let fty = ty::node_id_to_monotype(bcx_tcx(bcx), callee_id);
+        let fty = ty::node_id_to_type(bcx_tcx(bcx), callee_id);
         ret trans_call_inner(bcx, fty, {|bcx|
             impl::trans_method_callee(bcx, callee_id, lhs, origin)
         }, [rhs], ex.id, dest);
@@ -2327,16 +2284,19 @@ fn trans_binary(bcx: @block_ctxt, op: ast::binop, lhs: @ast::expr,
 
     // First couple cases are lazy:
     alt op {
-      ast::and | ast::or {
-        ret trans_lazy_binop(bcx, op, lhs, rhs, dest);
+      ast::and {
+        ret trans_lazy_binop(bcx, lazy_and, lhs, rhs, dest);
+      }
+      ast::or {
+        ret trans_lazy_binop(bcx, lazy_or, lhs, rhs, dest);
       }
       _ {
         // Remaining cases are eager:
         let lhs_res = trans_temp_expr(bcx, lhs);
         let rhs_res = trans_temp_expr(lhs_res.bcx, rhs);
         ret trans_eager_binop(rhs_res.bcx, op, lhs_res.val,
-                              ty::expr_ty(bcx_tcx(bcx), lhs), rhs_res.val,
-                              ty::expr_ty(bcx_tcx(bcx), rhs), dest);
+                              expr_ty(bcx, lhs), rhs_res.val,
+                              expr_ty(bcx, rhs), dest);
       }
     }
 }
@@ -2400,18 +2360,25 @@ fn store_in_dest(bcx: @block_ctxt, val: ValueRef, dest: dest) -> @block_ctxt {
 }
 
 fn get_dest_addr(dest: dest) -> ValueRef {
-    alt dest { save_in(a) { a } }
+    alt dest {
+       save_in(a) { a }
+       // Precondition?
+       _ { fail "get_dest_addr: not a save_in"; }
+    }
 }
 
 fn trans_if(cx: @block_ctxt, cond: @ast::expr, thn: ast::blk,
-            els: option::t<@ast::expr>, dest: dest)
+            els: option<@ast::expr>, dest: dest)
     -> @block_ctxt {
     let {bcx, val: cond_val} = trans_temp_expr(cx, cond);
 
     let then_dest = dup_for_join(dest);
     let else_dest = dup_for_join(dest);
-    let then_cx = new_scope_block_ctxt(bcx, "then");
-    let else_cx = new_scope_block_ctxt(bcx, "else");
+    let then_cx = new_real_block_ctxt(bcx, "then", thn.span);
+    let else_cx = new_real_block_ctxt(bcx, "else", alt els {
+        some(e) { e.span }
+        _ { ast_util::dummy_sp() }
+    });
     CondBr(bcx, cond_val, then_cx.llbb, else_cx.llbb);
     then_cx = trans_block_dps(then_cx, thn, then_dest);
     // Calling trans_block directly instead of trans_expr
@@ -2428,6 +2395,9 @@ fn trans_if(cx: @block_ctxt, cond: @ast::expr, thn: ast::blk,
           ast::expr_block(blk) {
             else_cx = trans_block_dps(else_cx, blk, else_dest);
           }
+          // would be nice to have a constraint on ifs
+          _ { bcx_tcx(cx).sess.bug("Strange alternative\
+                in if"); }
         }
       }
       _ {}
@@ -2442,7 +2412,8 @@ fn inner(bcx: @block_ctxt, local: @ast::local, curr: ValueRef, t: ty::t,
         let next_cx = new_sub_block_ctxt(bcx, "next");
         let scope_cx =
             new_loop_scope_block_ctxt(bcx, option::some(next_cx),
-                                      outer_next_cx, "for loop scope");
+                                      outer_next_cx, "for loop scope",
+                                      body.span);
         Br(bcx, scope_cx.llbb);
         let curr = PointerCast(bcx, curr, T_ptr(type_of_or_i8(bcx, t)));
         let bcx = alt::bind_irrefutable_pat(scope_cx, local.node.pat,
@@ -2453,7 +2424,7 @@ fn inner(bcx: @block_ctxt, local: @ast::local, curr: ValueRef, t: ty::t,
     }
     let ccx = bcx_ccx(cx);
     let next_cx = new_sub_block_ctxt(cx, "next");
-    let seq_ty = ty::expr_ty(bcx_tcx(cx), seq);
+    let seq_ty = expr_ty(cx, seq);
     let {bcx: bcx, val: seq} = trans_temp_expr(cx, seq);
     let seq = PointerCast(bcx, seq, T_ptr(ccx.opaque_vec_type));
     let fill = tvec::get_fill(bcx, seq);
@@ -2471,7 +2442,7 @@ fn trans_while(cx: @block_ctxt, cond: @ast::expr, body: ast::blk)
     let next_cx = new_sub_block_ctxt(cx, "while next");
     let cond_cx =
         new_loop_scope_block_ctxt(cx, option::none::<@block_ctxt>, next_cx,
-                                  "while cond");
+                                  "while cond", body.span);
     let body_cx = new_scope_block_ctxt(cond_cx, "while loop body");
     let body_end = trans_block(body_cx, body);
     let cond_res = trans_temp_expr(cond_cx, cond);
@@ -2487,7 +2458,7 @@ fn trans_do_while(cx: @block_ctxt, body: ast::blk, cond: @ast::expr) ->
     let next_cx = new_sub_block_ctxt(cx, "next");
     let body_cx =
         new_loop_scope_block_ctxt(cx, option::none::<@block_ctxt>, next_cx,
-                                  "do-while loop body");
+                                  "do-while loop body", body.span);
     let body_end = trans_block(body_cx, body);
     let cond_cx = new_scope_block_ctxt(body_cx, "do-while cond");
     Br(body_end, cond_cx.llbb);
@@ -2500,10 +2471,10 @@ fn trans_do_while(cx: @block_ctxt, body: ast::blk, cond: @ast::expr) ->
 
 type generic_info = {
     item_type: ty::t,
-    static_tis: [option::t<@tydesc_info>],
+    static_tis: [option<@tydesc_info>],
     tydescs: [ValueRef],
     param_bounds: @[ty::param_bounds],
-    origins: option::t<typeck::dict_res>
+    origins: option<typeck::dict_res>
 };
 
 enum lval_kind {
@@ -2523,10 +2494,10 @@ enum callee_env {
                           val: ValueRef,
                           kind: lval_kind,
                           env: callee_env,
-                          generic: option::t<generic_info>};
+                          generic: option<generic_info>};
 
 fn null_env_ptr(bcx: @block_ctxt) -> ValueRef {
-    C_null(T_opaque_cbox_ptr(bcx_ccx(bcx)))
+    C_null(T_opaque_box_ptr(bcx_ccx(bcx)))
 }
 
 fn lval_from_local_var(bcx: @block_ctxt, r: local_var_result) -> lval_result {
@@ -2547,16 +2518,58 @@ fn lval_no_env(bcx: @block_ctxt, val: ValueRef, kind: lval_kind)
 
 fn trans_external_path(cx: @block_ctxt, did: ast::def_id,
                        tpt: ty::ty_param_bounds_and_ty) -> ValueRef {
-    let lcx = cx.fcx.lcx;
-    let name = csearch::get_symbol(lcx.ccx.sess.cstore, did);
-    ret get_extern_const(lcx.ccx.externs, lcx.ccx.llmod, name,
-                         type_of_ty_param_bounds_and_ty(lcx, tpt));
+    let ccx = cx.fcx.ccx;
+    let name = csearch::get_symbol(ccx.sess.cstore, did);
+    ret get_extern_const(ccx.externs, ccx.llmod, name,
+                         type_of_ty_param_bounds_and_ty(ccx, tpt));
+}
+
+fn monomorphic_fn(ccx: @crate_ctxt, fn_id: ast::def_id, substs: [ty::t],
+                  dicts: option<typeck::dict_res>) -> ValueRef {
+    let hash_id = @{def: fn_id, substs: substs, dicts: alt dicts {
+      some(os) { vec::map(*os, {|o| impl::dict_id(ccx.tcx, o)}) }
+      none { [] }
+    }};
+    alt ccx.monomorphized.find(hash_id) {
+      some(val) { ret val; }
+      none {}
+    }
+    let tpt = ty::lookup_item_type(ccx.tcx, fn_id);
+    let mono_ty = ty::substitute_type_params(ccx.tcx, substs, tpt.ty);
+    let (item, pt) = alt ccx.tcx.items.get(fn_id.node) {
+      ast_map::node_item(i, p) { (i, p) } _ { fail; }
+    };
+    let pt = *pt + [path_name(item.ident)];
+    let result = alt item.node {
+      ast::item_fn(decl, _, body) {
+        let llfty = type_of_fn_from_ty(ccx, mono_ty, []);
+        let s = mangle_exported_name(ccx, pt, mono_ty);
+        let lldecl = decl_cdecl_fn(ccx.llmod, s, llfty);
+        trans_fn(ccx, pt, decl, body, lldecl, no_self, [],
+                 some(substs), fn_id.node);
+        lldecl
+      }
+      _ { fail "FIXME[mono] handle other constructs"; }
+    };
+    ccx.monomorphized.insert(hash_id, result);
+    result
 }
 
 fn lval_static_fn(bcx: @block_ctxt, fn_id: ast::def_id, id: ast::node_id)
     -> lval_maybe_callee {
     let ccx = bcx_ccx(bcx);
+    let tys = ty::node_id_to_type_params(ccx.tcx, id);
     let tpt = ty::lookup_item_type(ccx.tcx, fn_id);
+    if ccx.sess.opts.monomorphize && vec::len(tys) > 0u &&
+       fn_id.crate == ast::local_crate &&
+       !vec::any(tys, {|t| ty::type_contains_params(ccx.tcx, t)}) &&
+       vec::all(*tpt.bounds, {|bs| vec::all(*bs, {|b|
+           alt b { ty::bound_iface(_) { false } _ { true } }
+       })}) {
+        let dicts = ccx.dict_map.find(id);
+        ret {bcx: bcx, val: monomorphic_fn(ccx, fn_id, tys, dicts),
+             kind: owned, env: null_env, generic: none};
+    }
     let val = if fn_id.crate == ast::local_crate {
         // Internal reference.
         assert (ccx.item_ids.contains_key(fn_id.node));
@@ -2565,9 +2578,8 @@ fn lval_static_fn(bcx: @block_ctxt, fn_id: ast::def_id, id: ast::node_id)
         // External reference.
         trans_external_path(bcx, fn_id, tpt)
     };
-    let tys = ty::node_id_to_type_params(ccx.tcx, id);
     let gen = none, bcx = bcx;
-    if vec::len(tys) != 0u {
+    if vec::len(tys) > 0u {
         let tydescs = [], tis = [];
         for t in tys {
             // TODO: Doesn't always escape.
@@ -2586,22 +2598,18 @@ fn lval_static_fn(bcx: @block_ctxt, fn_id: ast::def_id, id: ast::node_id)
     ret {bcx: bcx, val: val, kind: owned, env: null_env, generic: gen};
 }
 
-fn lookup_discriminant(lcx: @local_ctxt, vid: ast::def_id) -> ValueRef {
-    let ccx = lcx.ccx;
+fn lookup_discriminant(ccx: @crate_ctxt, vid: ast::def_id) -> ValueRef {
     alt ccx.discrims.find(vid) {
       none {
         // It's an external discriminant that we haven't seen yet.
         assert (vid.crate != ast::local_crate);
-        let sym = csearch::get_symbol(lcx.ccx.sess.cstore, vid);
-        let gvar =
-            str::as_buf(sym,
-                        {|buf|
-                            llvm::LLVMAddGlobal(ccx.llmod, ccx.int_type, buf)
-                        });
-        llvm::LLVMSetLinkage(gvar,
-                             lib::llvm::LLVMExternalLinkage as llvm::Linkage);
+        let sym = csearch::get_symbol(ccx.sess.cstore, vid);
+        let gvar = str::as_buf(sym, {|buf|
+            llvm::LLVMAddGlobal(ccx.llmod, ccx.int_type, buf)
+        });
+        lib::llvm::SetLinkage(gvar, lib::llvm::ExternalLinkage);
         llvm::LLVMSetGlobalConstant(gvar, True);
-        lcx.ccx.discrims.insert(vid, gvar);
+        ccx.discrims.insert(vid, gvar);
         ret gvar;
       }
       some(llval) { ret llval; }
@@ -2659,14 +2667,14 @@ fn trans_var(cx: @block_ctxt, def: ast::def, id: ast::node_id)
             ret lval_static_fn(cx, vid, id);
         } else {
             // Nullary variant.
-            let enum_ty = node_id_type(ccx, id);
+            let enum_ty = ty::node_id_to_type(ccx.tcx, id);
             let alloc_result = alloc_ty(cx, enum_ty);
             let llenumblob = alloc_result.val;
             let llenumty = type_of_enum(ccx, tid, enum_ty);
             let bcx = alloc_result.bcx;
             let llenumptr = PointerCast(bcx, llenumblob, T_ptr(llenumty));
             let lldiscrimptr = GEPi(bcx, llenumptr, [0, 0]);
-            let lldiscrim_gv = lookup_discriminant(bcx.fcx.lcx, vid);
+            let lldiscrim_gv = lookup_discriminant(bcx.fcx.ccx, vid);
             let lldiscrim = Load(bcx, lldiscrim_gv);
             Store(bcx, lldiscrim, lldiscrimptr);
             ret lval_no_env(bcx, llenumptr, temporary);
@@ -2677,7 +2685,7 @@ fn trans_var(cx: @block_ctxt, def: ast::def, id: ast::node_id)
             assert (ccx.consts.contains_key(did.node));
             ret lval_no_env(cx, ccx.consts.get(did.node), owned);
         } else {
-            let tp = ty::node_id_to_monotype(ccx.tcx, id);
+            let tp = ty::node_id_to_type(ccx.tcx, id);
             let val = trans_external_path(cx, did, {bounds: @[], ty: tp});
             ret lval_no_env(cx, load_if_immediate(cx, val, tp), owned_imm);
         }
@@ -2692,8 +2700,13 @@ fn trans_var(cx: @block_ctxt, def: ast::def, id: ast::node_id)
 fn trans_rec_field(bcx: @block_ctxt, base: @ast::expr,
                    field: ast::ident) -> lval_result {
     let {bcx, val} = trans_temp_expr(bcx, base);
-    let {bcx, val, ty} = autoderef(bcx, val, ty::expr_ty(bcx_tcx(bcx), base));
-    let fields = alt ty::struct(bcx_tcx(bcx), ty) { ty::ty_rec(fs) { fs } };
+    let {bcx, val, ty} = autoderef(bcx, val, expr_ty(bcx, base));
+    let fields = alt ty::struct(bcx_tcx(bcx), ty) {
+            ty::ty_rec(fs) { fs }
+            // Constraint?
+            _ { bcx_tcx(bcx).sess.span_bug(base.span, "trans_rec_field:\
+                 base expr has non-record type"); }
+        };
     let ix = option::get(ty::field_idx(field, fields));
     // Silly check
     check type_is_tup_like(bcx, ty);
@@ -2703,7 +2716,7 @@ fn trans_rec_field(bcx: @block_ctxt, base: @ast::expr,
 
 fn trans_index(cx: @block_ctxt, ex: @ast::expr, base: @ast::expr,
                idx: @ast::expr) -> lval_result {
-    let base_ty = ty::expr_ty(bcx_tcx(cx), base);
+    let base_ty = expr_ty(cx, base);
     let exp = trans_temp_expr(cx, base);
     let lv = autoderef(exp.bcx, exp.val, base_ty);
     let ix = trans_temp_expr(lv.bcx, idx);
@@ -2721,7 +2734,7 @@ fn trans_index(cx: @block_ctxt, ex: @ast::expr, base: @ast::expr,
         ix_val = Trunc(bcx, ix.val, ccx.int_type);
     } else { ix_val = ix.val; }
 
-    let unit_ty = node_id_type(bcx_ccx(cx), ex.id);
+    let unit_ty = node_id_type(cx, ex.id);
     let unit_sz = size_of(bcx, unit_ty);
     bcx = unit_sz.bcx;
     maybe_name_value(bcx_ccx(cx), unit_sz.val, "unit_sz");
@@ -2729,7 +2742,7 @@ fn trans_index(cx: @block_ctxt, ex: @ast::expr, base: @ast::expr,
     maybe_name_value(bcx_ccx(cx), scaled_ix, "scaled_ix");
     let lim = tvec::get_fill(bcx, v);
     let body = tvec::get_dataptr(bcx, v, type_of_or_i8(bcx, unit_ty));
-    let bounds_check = ICmp(bcx, lib::llvm::LLVMIntULT, scaled_ix, lim);
+    let bounds_check = ICmp(bcx, lib::llvm::IntULT, scaled_ix, lim);
     let fail_cx = new_sub_block_ctxt(bcx, "fail");
     let next_cx = new_sub_block_ctxt(bcx, "next");
     let ncx = bcx_ccx(next_cx);
@@ -2765,6 +2778,9 @@ fn trans_callee(bcx: @block_ctxt, e: @ast::expr) -> lval_maybe_callee {
               some(origin) { // An impl method
                 ret impl::trans_method_callee(bcx, e.id, base, origin);
               }
+              // Precondition?
+              _ { bcx_tcx(bcx).sess.span_bug(e.span, "trans_callee: weird\
+                    expr"); }
             }
         }
       }
@@ -2782,7 +2798,7 @@ fn trans_lval(cx: @block_ctxt, e: @ast::expr) -> lval_result {
     alt e.node {
       ast::expr_path(_) {
         let v = trans_path(cx, e.id);
-        ret lval_maybe_callee_to_lval(v, ty::expr_ty(bcx_tcx(cx), e));
+        ret lval_maybe_callee_to_lval(v, expr_ty(cx, e));
       }
       ast::expr_field(base, ident, _) {
         ret trans_rec_field(cx, base, ident);
@@ -2793,17 +2809,17 @@ fn trans_lval(cx: @block_ctxt, e: @ast::expr) -> lval_result {
       ast::expr_unary(ast::deref, base) {
         let ccx = bcx_ccx(cx);
         let sub = trans_temp_expr(cx, base);
-        let t = ty::expr_ty(ccx.tcx, base);
+        let t = expr_ty(cx, base);
         let val =
             alt ty::struct(ccx.tcx, t) {
               ty::ty_box(_) {
-                GEPi(sub.bcx, sub.val, [0, abi::box_rc_field_body])
+                GEPi(sub.bcx, sub.val, [0, abi::box_field_body])
               }
               ty::ty_res(_, _, _) {
                 GEPi(sub.bcx, sub.val, [0, 1])
               }
               ty::ty_enum(_, _) {
-                let ety = ty::expr_ty(ccx.tcx, e);
+                let ety = expr_ty(cx, e);
                 let ellty =
                     if check type_has_static_size(ccx, ety) {
                         T_ptr(type_of(ccx, ety))
@@ -2811,15 +2827,14 @@ fn trans_lval(cx: @block_ctxt, e: @ast::expr) -> lval_result {
                 PointerCast(sub.bcx, sub.val, ellty)
               }
               ty::ty_ptr(_) | ty::ty_uniq(_) { sub.val }
+              // Precondition?
+              _ {
+                  bcx_tcx(cx).sess.span_bug(e.span, "trans_lval:\
+                    Weird argument in deref");
+              }
             };
         ret lval_owned(sub.bcx, val);
       }
-      // This is a by-ref returning call. Regular calls are not lval
-      ast::expr_call(f, args, _) {
-        let cell = empty_dest_cell();
-        let bcx = trans_call(cx, f, args, e.id, by_val(cell));
-        ret lval_owned(bcx, *cell);
-      }
       _ { bcx_ccx(cx).sess.span_bug(e.span, "non-lval in trans_lval"); }
     }
 }
@@ -2884,14 +2899,14 @@ fn float_cast(bcx: @block_ctxt, lldsttype: TypeRef, llsrctype: TypeRef,
 fn trans_cast(cx: @block_ctxt, e: @ast::expr, id: ast::node_id,
               dest: dest) -> @block_ctxt {
     let ccx = bcx_ccx(cx);
-    let t_out = node_id_type(ccx, id);
-    alt ty::struct(ccx.tcx, t_out) {
+    let t_out = node_id_type(cx, id);
+    alt ty::struct(bcx_tcx(cx), t_out) {
       ty::ty_iface(_, _) { ret impl::trans_cast(cx, e, id, dest); }
       _ {}
     }
     let e_res = trans_temp_expr(cx, e);
     let ll_t_in = val_ty(e_res.val);
-    let t_in = ty::expr_ty(ccx.tcx, e);
+    let t_in = expr_ty(cx, e);
     // Check should be avoidable because it's a cast.
     // FIXME: Constrain types so as to avoid this check.
     check (type_has_static_size(ccx, t_out));
@@ -2901,8 +2916,7 @@ enum kind { pointer, integral, float, enum_, other, }
     fn t_kind(tcx: ty::ctxt, t: ty::t) -> kind {
         ret if ty::type_is_fp(tcx, t) {
                 float
-            } else if ty::type_is_native(tcx, t) ||
-                      ty::type_is_unsafe_ptr(tcx, t) {
+            } else if ty::type_is_unsafe_ptr(tcx, t) {
                 pointer
             } else if ty::type_is_integral(tcx, t) {
                 integral
@@ -2951,6 +2965,7 @@ fn t_kind(tcx: ty::ctxt, t: ty::t) -> kind {
               integral {int_cast(e_res.bcx, ll_t_out,
                                   val_ty(lldiscrim_a), lldiscrim_a, true)}
               float {SIToFP(e_res.bcx, lldiscrim_a, ll_t_out)}
+              _ { ccx.sess.bug("Translating unsupported cast.") }
             }
           }
           _ { ccx.sess.bug("Translating unsupported cast.") }
@@ -2963,20 +2978,21 @@ fn trans_arg_expr(cx: @block_ctxt, arg: ty::arg, lldestty: TypeRef,
                   &to_revoke: [{v: ValueRef, t: ty::t}], e: @ast::expr) ->
    result {
     let ccx = bcx_ccx(cx);
-    let e_ty = ty::expr_ty(ccx.tcx, e);
+    let e_ty = expr_ty(cx, e);
     let is_bot = ty::type_is_bot(ccx.tcx, e_ty);
     let lv = trans_temp_lval(cx, e);
     let bcx = lv.bcx;
     let val = lv.val;
+    let arg_mode = ty::resolved_mode(ccx.tcx, arg.mode);
     if is_bot {
         // For values of type _|_, we generate an
         // "undef" value, as such a value should never
         // be inspected. It's important for the value
         // to have type lldestty (the callee's expected type).
         val = llvm::LLVMGetUndef(lldestty);
-    } else if arg.mode == ast::by_ref || arg.mode == ast::by_val {
+    } else if arg_mode == ast::by_ref || arg_mode == ast::by_val {
         let copied = false, imm = ty::type_is_immediate(ccx.tcx, e_ty);
-        if arg.mode == ast::by_ref && lv.kind != owned && imm {
+        if arg_mode == ast::by_ref && lv.kind != owned && imm {
             val = do_spill_noroot(bcx, val);
             copied = true;
         }
@@ -2989,10 +3005,10 @@ fn trans_arg_expr(cx: @block_ctxt, arg: ty::arg, lldestty: TypeRef,
             } else { bcx = take_ty(bcx, val, e_ty); }
             add_clean(bcx, val, e_ty);
         }
-        if arg.mode == ast::by_val && (lv.kind == owned || !imm) {
+        if arg_mode == ast::by_val && (lv.kind == owned || !imm) {
             val = Load(bcx, val);
         }
-    } else if arg.mode == ast::by_copy {
+        } else if arg_mode == ast::by_copy {
         let {bcx: cx, val: alloc} = alloc_ty(bcx, e_ty);
         let last_use = ccx.last_uses.contains_key(e.id);
         bcx = cx;
@@ -3018,7 +3034,7 @@ fn trans_arg_expr(cx: @block_ctxt, arg: ty::arg, lldestty: TypeRef,
     }
 
     // Collect arg for later if it happens to be one we've moving out.
-    if arg.mode == ast::by_move {
+    if arg_mode == ast::by_move {
         if lv.kind == owned {
             // Use actual ty, not declared ty -- anything else doesn't make
             // sense if declared ty is a ty param
@@ -3036,7 +3052,7 @@ fn trans_arg_expr(cx: @block_ctxt, arg: ty::arg, lldestty: TypeRef,
 //  - new_fn_ctxt
 //  - trans_args
 fn trans_args(cx: @block_ctxt, llenv: ValueRef,
-              gen: option::t<generic_info>, es: [@ast::expr], fn_ty: ty::t,
+              gen: option<generic_info>, es: [@ast::expr], fn_ty: ty::t,
               dest: dest)
    -> {bcx: @block_ctxt,
        args: [ValueRef],
@@ -3140,7 +3156,7 @@ fn trans_args(cx: @block_ctxt, llenv: ValueRef,
 fn trans_call(in_cx: @block_ctxt, f: @ast::expr,
               args: [@ast::expr], id: ast::node_id, dest: dest)
     -> @block_ctxt {
-    trans_call_inner(in_cx, ty::expr_ty(bcx_tcx(in_cx), f),
+    trans_call_inner(in_cx, expr_ty(in_cx, f),
                      {|cx| trans_callee(cx, f)}, args, id, dest)
 }
 
@@ -3162,7 +3178,7 @@ fn trans_call_inner(in_cx: @block_ctxt, fn_expr_ty: ty::t,
     let llenv, dict_param = none;
     alt f_res.env {
       null_env {
-        llenv = llvm::LLVMGetUndef(T_opaque_cbox_ptr(bcx_ccx(cx)));
+        llenv = llvm::LLVMGetUndef(T_opaque_box_ptr(bcx_ccx(cx)));
       }
       self_env(e) { llenv = e; }
       dict_env(dict, e) { llenv = e; dict_param = some(dict); }
@@ -3335,7 +3351,7 @@ fn trans_landing_pad(bcx: @block_ctxt,
 
 fn trans_tup(bcx: @block_ctxt, elts: [@ast::expr], id: ast::node_id,
              dest: dest) -> @block_ctxt {
-    let t = node_id_type(bcx.fcx.lcx.ccx, id);
+    let t = node_id_type(bcx, id);
     let bcx = bcx;
     let addr = alt dest {
       ignore {
@@ -3343,11 +3359,12 @@ fn trans_tup(bcx: @block_ctxt, elts: [@ast::expr], id: ast::node_id,
         ret bcx;
       }
       save_in(pos) { pos }
+      _ { bcx_tcx(bcx).sess.bug("trans_tup: weird dest"); }
     };
     let temp_cleanups = [], i = 0;
     for e in elts {
         let dst = GEP_tup_like_1(bcx, t, addr, [0, i]);
-        let e_ty = ty::expr_ty(bcx_tcx(bcx), e);
+        let e_ty = expr_ty(bcx, e);
         bcx = trans_expr_save_in(dst.bcx, e, dst.val);
         add_clean_temp_mem(bcx, dst.val, e_ty);
         temp_cleanups += [dst.val];
@@ -3358,9 +3375,9 @@ fn trans_tup(bcx: @block_ctxt, elts: [@ast::expr], id: ast::node_id,
 }
 
 fn trans_rec(bcx: @block_ctxt, fields: [ast::field],
-             base: option::t<@ast::expr>, id: ast::node_id,
+             base: option<@ast::expr>, id: ast::node_id,
              dest: dest) -> @block_ctxt {
-    let t = node_id_type(bcx_ccx(bcx), id);
+    let t = node_id_type(bcx, id);
     let bcx = bcx;
     let addr = alt dest {
       ignore {
@@ -3370,9 +3387,12 @@ fn trans_rec(bcx: @block_ctxt, fields: [ast::field],
         ret bcx;
       }
       save_in(pos) { pos }
+      _ { bcx_tcx(bcx).sess.bug("trans_rec: weird dest"); }
     };
 
-    let ty_fields = alt ty::struct(bcx_tcx(bcx), t) { ty::ty_rec(f) { f } };
+    let ty_fields = alt ty::struct(bcx_tcx(bcx), t) { ty::ty_rec(f) { f }
+      _ { bcx_tcx(bcx).sess.bug("trans_rec: id doesn't\
+           have a record type") } };
     let temp_cleanups = [];
     for fld in fields {
         let ix = option::get(vec::position(ty_fields, {|ft|
@@ -3411,9 +3431,9 @@ fn trans_rec(bcx: @block_ctxt, fields: [ast::field],
 // that nil or bot expressions get ignore rather than save_in as destination.
 fn trans_expr_save_in(bcx: @block_ctxt, e: @ast::expr, dest: ValueRef)
     -> @block_ctxt {
-    let tcx = bcx_tcx(bcx), t = ty::expr_ty(tcx, e);
+    let tcx = bcx_tcx(bcx), t = expr_ty(bcx, e);
     let do_ignore = ty::type_is_bot(tcx, t) || ty::type_is_nil(tcx, t);
-    ret trans_expr(bcx, e, do_ignore ? ignore : save_in(dest));
+    ret trans_expr(bcx, e, if do_ignore { ignore } else { save_in(dest) });
 }
 
 // Call this to compile an expression that you need as an intermediate value,
@@ -3427,7 +3447,7 @@ fn trans_temp_lval(bcx: @block_ctxt, e: @ast::expr) -> lval_result {
         ret trans_lval(bcx, e);
     } else {
         let tcx = bcx_tcx(bcx);
-        let ty = ty::expr_ty(tcx, e);
+        let ty = expr_ty(bcx, e);
         if ty::type_is_nil(tcx, ty) || ty::type_is_bot(tcx, ty) {
             bcx = trans_expr(bcx, e, ignore);
             ret {bcx: bcx, val: C_nil(), kind: temporary};
@@ -3450,7 +3470,7 @@ fn trans_temp_lval(bcx: @block_ctxt, e: @ast::expr) -> lval_result {
 fn trans_temp_expr(bcx: @block_ctxt, e: @ast::expr) -> result {
     let {bcx, val, kind} = trans_temp_lval(bcx, e);
     if kind == owned {
-        val = load_if_immediate(bcx, val, ty::expr_ty(bcx_tcx(bcx), e));
+        val = load_if_immediate(bcx, val, expr_ty(bcx, e));
     }
     ret {bcx: bcx, val: val};
 }
@@ -3463,6 +3483,8 @@ fn trans_expr(bcx: @block_ctxt, e: @ast::expr, dest: dest) -> @block_ctxt {
     let tcx = bcx_tcx(bcx);
     debuginfo::update_source_pos(bcx, e.span);
 
+    #debug["trans_expr(%s,%?)", expr_to_str(e), dest];
+
     if expr_is_lval(bcx, e) {
         ret lval_to_dps(bcx, e, dest);
     }
@@ -3471,15 +3493,13 @@ fn trans_expr(bcx: @block_ctxt, e: @ast::expr, dest: dest) -> @block_ctxt {
       ast::expr_if(cond, thn, els) | ast::expr_if_check(cond, thn, els) {
         ret trans_if(bcx, cond, thn, els, dest);
       }
-      ast::expr_ternary(_, _, _) {
-        ret trans_expr(bcx, ast_util::ternary_to_if(e), dest);
-      }
       ast::expr_alt(expr, arms) {
           //          tcx.sess.span_note(e.span, "about to call trans_alt");
         ret alt::trans_alt(bcx, expr, arms, dest);
       }
       ast::expr_block(blk) {
-        let sub_cx = new_scope_block_ctxt(bcx, "block-expr body");
+        let sub_cx = new_real_block_ctxt(bcx, "block-expr body",
+                                          blk.span);
         Br(bcx, sub_cx.llbb);
         sub_cx = trans_block_dps(sub_cx, blk, dest);
         let next_cx = new_sub_block_ctxt(bcx, "next");
@@ -3505,10 +3525,10 @@ fn trans_expr(bcx: @block_ctxt, e: @ast::expr, dest: dest) -> @block_ctxt {
             bcx, proto, decl, body, e.span, e.id, *cap_clause, dest);
       }
       ast::expr_fn_block(decl, body) {
-        alt ty::struct(tcx, ty::expr_ty(tcx, e)) {
+        alt ty::struct(tcx, expr_ty(bcx, e)) {
           ty::ty_fn({proto, _}) {
             #debug("translating fn_block %s with type %s",
-                   expr_to_str(e), ty_to_str(tcx, ty::expr_ty(tcx, e)));
+                   expr_to_str(e), ty_to_str(tcx, expr_ty(bcx, e)));
             let cap_clause = { copies: [], moves: [] };
             ret closure::trans_expr_fn(
                 bcx, proto, decl, body, e.span, e.id, cap_clause, dest);
@@ -3539,7 +3559,7 @@ fn trans_expr(bcx: @block_ctxt, e: @ast::expr, dest: dest) -> @block_ctxt {
         // If it is here, it's not an lval, so this is a user-defined index op
         let origin = bcx_ccx(bcx).method_map.get(e.id);
         let callee_id = ast_util::op_expr_callee_id(e);
-        let fty = ty::node_id_to_monotype(tcx, callee_id);
+        let fty = ty::node_id_to_type(tcx, callee_id);
         ret trans_call_inner(bcx, fty, {|bcx|
             impl::trans_method_callee(bcx, callee_id, base, origin)
         }, [idx], e.id, dest);
@@ -3620,7 +3640,7 @@ fn trans_expr(bcx: @block_ctxt, e: @ast::expr, dest: dest) -> @block_ctxt {
         let {bcx, val: addr, kind} = trans_lval(src_r.bcx, dst);
         assert kind == owned;
         ret store_temp_expr(bcx, DROP_EXISTING, addr, src_r,
-                            ty::expr_ty(bcx_tcx(bcx), src),
+                            expr_ty(bcx, src),
                             bcx_ccx(bcx).last_uses.contains_key(src.id));
       }
       ast::expr_move(dst, src) {
@@ -3630,14 +3650,14 @@ fn trans_expr(bcx: @block_ctxt, e: @ast::expr, dest: dest) -> @block_ctxt {
         let {bcx, val: addr, kind} = trans_lval(src_r.bcx, dst);
         assert kind == owned;
         ret move_val(bcx, DROP_EXISTING, addr, src_r,
-                     ty::expr_ty(bcx_tcx(bcx), src));
+                     expr_ty(bcx, src));
       }
       ast::expr_swap(dst, src) {
         assert dest == ignore;
         let lhs_res = trans_lval(bcx, dst);
         assert lhs_res.kind == owned;
         let rhs_res = trans_lval(lhs_res.bcx, src);
-        let t = ty::expr_ty(tcx, src);
+        let t = expr_ty(bcx, src);
         let {bcx: bcx, val: tmp_alloc} = alloc_ty(rhs_res.bcx, t);
         // Swap through a temporary.
         bcx = move_val(bcx, INIT, tmp_alloc, lhs_res, t);
@@ -3648,6 +3668,9 @@ fn trans_expr(bcx: @block_ctxt, e: @ast::expr, dest: dest) -> @block_ctxt {
         assert dest == ignore;
         ret trans_assign_op(bcx, e, op, dst, src);
       }
+      _ { bcx_tcx(bcx).sess.span_bug(e.span, "trans_expr reached\
+             fall-through case"); }
+
     }
 }
 
@@ -3655,7 +3678,7 @@ fn lval_to_dps(bcx: @block_ctxt, e: @ast::expr, dest: dest) -> @block_ctxt {
     let lv = trans_lval(bcx, e), ccx = bcx_ccx(bcx);
     let {bcx, val, kind} = lv;
     let last_use = kind == owned && ccx.last_uses.contains_key(e.id);
-    let ty = ty::expr_ty(ccx.tcx, e);
+    let ty = expr_ty(bcx, e);
     alt dest {
       by_val(cell) {
         if kind == temporary {
@@ -3717,28 +3740,29 @@ fn load_if_immediate(cx: @block_ctxt, v: ValueRef, t: ty::t) -> ValueRef {
 }
 
 fn trans_log(lvl: @ast::expr, cx: @block_ctxt, e: @ast::expr) -> @block_ctxt {
-    let ccx = bcx_ccx(cx);
-    let lcx = cx.fcx.lcx;
-    let tcx = ccx.tcx;
-    let modname = str::connect(lcx.module_path, "::");
-
-    if ty::type_is_bot(tcx, ty::expr_ty(tcx, lvl)) {
+    let ccx = bcx_ccx(cx), tcx = ccx.tcx;
+    if ty::type_is_bot(tcx, expr_ty(cx, lvl)) {
        ret trans_expr(cx, lvl, ignore);
     }
 
-    let global = if lcx.ccx.module_data.contains_key(modname) {
-        lcx.ccx.module_data.get(modname)
+    let modpath = [path_mod(ccx.link_meta.name)] +
+        vec::filter(cx.fcx.path, {|e|
+            alt e { path_mod(_) { true } _ { false } }
+        });
+    let modname = path_str(modpath);
+
+    let global = if ccx.module_data.contains_key(modname) {
+        ccx.module_data.get(modname)
     } else {
         let s = link::mangle_internal_name_by_path_and_seq(
-            lcx.ccx, lcx.module_path, "loglevel");
+            ccx, modpath, "loglevel");
         let global = str::as_buf(s, {|buf|
-            llvm::LLVMAddGlobal(lcx.ccx.llmod, T_i32(), buf)
+            llvm::LLVMAddGlobal(ccx.llmod, T_i32(), buf)
         });
         llvm::LLVMSetGlobalConstant(global, False);
         llvm::LLVMSetInitializer(global, C_null(T_i32()));
-        llvm::LLVMSetLinkage(global,
-                             lib::llvm::LLVMInternalLinkage as llvm::Linkage);
-        lcx.ccx.module_data.insert(modname, global);
+        lib::llvm::SetLinkage(global, lib::llvm::InternalLinkage);
+        ccx.module_data.insert(modname, global);
         global
     };
     let level_cx = new_scope_block_ctxt(cx, "level");
@@ -3748,12 +3772,12 @@ fn trans_log(lvl: @ast::expr, cx: @block_ctxt, e: @ast::expr) -> @block_ctxt {
 
     Br(cx, level_cx.llbb);
     let level_res = trans_temp_expr(level_cx, lvl);
-    let test = ICmp(level_res.bcx, lib::llvm::LLVMIntUGE,
+    let test = ICmp(level_res.bcx, lib::llvm::IntUGE,
                     load, level_res.val);
 
     CondBr(level_res.bcx, test, log_cx.llbb, after_cx.llbb);
     let sub = trans_temp_expr(log_cx, e);
-    let e_ty = ty::expr_ty(bcx_tcx(cx), e);
+    let e_ty = expr_ty(cx, e);
     let log_bcx = sub.bcx;
 
     let ti = none::<@tydesc_info>;
@@ -3785,14 +3809,14 @@ fn trans_check_expr(cx: @block_ctxt, e: @ast::expr, s: str) -> @block_ctxt {
     ret next_cx;
 }
 
-fn trans_fail_expr(bcx: @block_ctxt, sp_opt: option::t<span>,
-                   fail_expr: option::t<@ast::expr>) -> @block_ctxt {
+fn trans_fail_expr(bcx: @block_ctxt, sp_opt: option<span>,
+                   fail_expr: option<@ast::expr>) -> @block_ctxt {
     let bcx = bcx;
     alt fail_expr {
       some(expr) {
         let tcx = bcx_tcx(bcx);
         let expr_res = trans_temp_expr(bcx, expr);
-        let e_ty = ty::expr_ty(tcx, expr);
+        let e_ty = expr_ty(bcx, expr);
         bcx = expr_res.bcx;
 
         if ty::type_is_str(tcx, e_ty) {
@@ -3812,13 +3836,13 @@ fn trans_fail_expr(bcx: @block_ctxt, sp_opt: option::t<span>,
     }
 }
 
-fn trans_fail(bcx: @block_ctxt, sp_opt: option::t<span>, fail_str: str) ->
+fn trans_fail(bcx: @block_ctxt, sp_opt: option<span>, fail_str: str) ->
     @block_ctxt {
     let V_fail_str = C_cstr(bcx_ccx(bcx), fail_str);
     ret trans_fail_value(bcx, sp_opt, V_fail_str);
 }
 
-fn trans_fail_value(bcx: @block_ctxt, sp_opt: option::t<span>,
+fn trans_fail_value(bcx: @block_ctxt, sp_opt: option<span>,
                     V_fail_str: ValueRef) -> @block_ctxt {
     let ccx = bcx_ccx(bcx);
     let V_filename;
@@ -3827,7 +3851,7 @@ fn trans_fail_value(bcx: @block_ctxt, sp_opt: option::t<span>,
       some(sp) {
         let sess = bcx_ccx(bcx).sess;
         let loc = codemap::lookup_char_pos(sess.parse_sess.cm, sp.lo);
-        V_filename = C_cstr(bcx_ccx(bcx), loc.filename);
+        V_filename = C_cstr(bcx_ccx(bcx), loc.file.name);
         V_line = loc.line as int;
       }
       none { V_filename = C_cstr(bcx_ccx(bcx), "<runtime>"); V_line = 0; }
@@ -3883,7 +3907,7 @@ fn trans_cont(cx: @block_ctxt) -> @block_ctxt {
     ret trans_break_cont(cx, false);
 }
 
-fn trans_ret(bcx: @block_ctxt, e: option::t<@ast::expr>) -> @block_ctxt {
+fn trans_ret(bcx: @block_ctxt, e: option<@ast::expr>) -> @block_ctxt {
     let cleanup_cx = bcx, bcx = bcx;
     alt e {
       some(x) { bcx = trans_expr_save_in(bcx, x, bcx.fcx.llretptr); }
@@ -3915,12 +3939,21 @@ fn trans_be(cx: @block_ctxt, e: @ast::expr) : ast_util::is_call_expr(e) ->
 }
 
 fn init_local(bcx: @block_ctxt, local: @ast::local) -> @block_ctxt {
-    let ty = node_id_type(bcx_ccx(bcx), local.node.id);
+    let ty = node_id_type(bcx, local.node.id);
     let llptr = alt bcx.fcx.lllocals.find(local.node.id) {
       some(local_mem(v)) { v }
+      some(_) { bcx_tcx(bcx).sess.span_bug(local.span,
+                        "init_local: Someone forgot to document why it's\
+                         safe to assume local.node.init must be local_mem!");
+      }
       // This is a local that is kept immediate
       none {
-        let initexpr = alt local.node.init { some({expr, _}) { expr } };
+        let initexpr = alt local.node.init {
+                some({expr, _}) { expr }
+                none { bcx_tcx(bcx).sess.span_bug(local.span,
+                        "init_local: Someone forgot to document why it's\
+                         safe to assume local.node.init isn't none!"); }
+            };
         let {bcx, val, kind} = trans_temp_lval(bcx, initexpr);
         if kind != temporary {
             if kind == owned { val = Load(bcx, val); }
@@ -3956,6 +3989,8 @@ fn init_ref_local(bcx: @block_ctxt, local: @ast::local) -> @block_ctxt {
     alt kind {
       owned_imm { val = do_spill_noroot(bcx, val); }
       owned {}
+      _ { bcx_tcx(bcx).sess.span_bug(local.span,
+           "Someone forgot to document an invariant in init_ref_local!"); }
     }
     ret alt::bind_irrefutable_pat(bcx, local.node.pat, val, false);
 }
@@ -3985,6 +4020,8 @@ fn zero_alloca(cx: @block_ctxt, llptr: ValueRef, t: ty::t)
 }
 
 fn trans_stmt(cx: @block_ctxt, s: ast::stmt) -> @block_ctxt {
+    #debug["trans_expr(%s)", stmt_to_str(s)];
+
     if (!bcx_ccx(cx).sess.opts.no_asm_comments) {
         add_span_comment(cx, s.span, stmt_to_str(s));
     }
@@ -4010,7 +4047,7 @@ fn trans_stmt(cx: @block_ctxt, s: ast::stmt) -> @block_ctxt {
                 }
             }
           }
-          ast::decl_item(i) { trans_item(cx.fcx.lcx, *i); }
+          ast::decl_item(i) { trans_item(cx.fcx.ccx, *i); }
         }
       }
       _ { bcx_ccx(cx).sess.unimpl("stmt variant"); }
@@ -4022,11 +4059,10 @@ fn trans_stmt(cx: @block_ctxt, s: ast::stmt) -> @block_ctxt {
 // You probably don't want to use this one. See the
 // next three functions instead.
 fn new_block_ctxt(cx: @fn_ctxt, parent: block_parent, kind: block_kind,
-                  name: str) -> @block_ctxt {
+                  name: str, block_span: option<span>) -> @block_ctxt {
     let s = "";
-    if cx.lcx.ccx.sess.opts.save_temps ||
-           cx.lcx.ccx.sess.opts.debuginfo {
-        s = cx.lcx.ccx.names(name);
+    if cx.ccx.sess.opts.save_temps || cx.ccx.sess.opts.debuginfo {
+        s = cx.ccx.names(name);
     }
     let llbb: BasicBlockRef =
         str::as_buf(s, {|buf| llvm::LLVMAppendBasicBlock(cx.llfn, buf) });
@@ -4037,7 +4073,8 @@ fn new_block_ctxt(cx: @fn_ctxt, parent: block_parent, kind: block_kind,
                 kind: kind,
                 mutable cleanups: [],
                 mutable lpad_dirty: true,
-                mutable lpad: option::none,
+                mutable lpad: none,
+                block_span: block_span,
                 fcx: cx};
     alt parent {
       parent_some(cx) {
@@ -4050,26 +4087,32 @@ fn new_block_ctxt(cx: @fn_ctxt, parent: block_parent, kind: block_kind,
 
 
 // Use this when you're at the top block of a function or the like.
-fn new_top_block_ctxt(fcx: @fn_ctxt) -> @block_ctxt {
-    ret new_block_ctxt(fcx, parent_none, SCOPE_BLOCK, "function top level");
+fn new_top_block_ctxt(fcx: @fn_ctxt, sp: option<span>) -> @block_ctxt {
+    ret new_block_ctxt(fcx, parent_none, SCOPE_BLOCK, "function top level",
+                       sp);
 }
 
 
 // Use this when you're at a curly-brace or similar lexical scope.
 fn new_scope_block_ctxt(bcx: @block_ctxt, n: str) -> @block_ctxt {
-    ret new_block_ctxt(bcx.fcx, parent_some(bcx), SCOPE_BLOCK, n);
+    ret new_block_ctxt(bcx.fcx, parent_some(bcx), SCOPE_BLOCK, n, none);
+}
+
+fn new_real_block_ctxt(bcx: @block_ctxt, n: str, sp: span) -> @block_ctxt {
+    ret new_block_ctxt(bcx.fcx, parent_some(bcx), SCOPE_BLOCK, n, some(sp));
 }
 
-fn new_loop_scope_block_ctxt(bcx: @block_ctxt, _cont: option::t<@block_ctxt>,
-                             _break: @block_ctxt, n: str) -> @block_ctxt {
+fn new_loop_scope_block_ctxt(bcx: @block_ctxt, _cont: option<@block_ctxt>,
+                             _break: @block_ctxt, n: str, sp: span)
+    -> @block_ctxt {
     ret new_block_ctxt(bcx.fcx, parent_some(bcx),
-                       LOOP_SCOPE_BLOCK(_cont, _break), n);
+                       LOOP_SCOPE_BLOCK(_cont, _break), n, some(sp));
 }
 
 
 // Use this when you're making a general CFG BB within a scope.
 fn new_sub_block_ctxt(bcx: @block_ctxt, n: str) -> @block_ctxt {
-    ret new_block_ctxt(bcx.fcx, parent_some(bcx), NON_SCOPE_BLOCK, n);
+    ret new_block_ctxt(bcx.fcx, parent_some(bcx), NON_SCOPE_BLOCK, n, none);
 }
 
 fn new_raw_block_ctxt(fcx: @fn_ctxt, llbb: BasicBlockRef) -> @block_ctxt {
@@ -4080,7 +4123,8 @@ fn new_raw_block_ctxt(fcx: @fn_ctxt, llbb: BasicBlockRef) -> @block_ctxt {
           kind: NON_SCOPE_BLOCK,
           mutable cleanups: [],
           mutable lpad_dirty: true,
-          mutable lpad: option::none,
+          mutable lpad: none,
+          block_span: none,
           fcx: fcx};
 }
 
@@ -4146,7 +4190,8 @@ fn llstaticallocas_block_ctxt(fcx: @fn_ctxt) -> @block_ctxt {
           kind: SCOPE_BLOCK,
           mutable cleanups: [],
           mutable lpad_dirty: true,
-          mutable lpad: option::none,
+          mutable lpad: none,
+          block_span: none,
           fcx: fcx};
 }
 
@@ -4158,7 +4203,8 @@ fn llderivedtydescs_block_ctxt(fcx: @fn_ctxt) -> @block_ctxt {
           kind: SCOPE_BLOCK,
           mutable cleanups: [],
           mutable lpad_dirty: true,
-          mutable lpad: option::none,
+          mutable lpad: none,
+          block_span: none,
           fcx: fcx};
 }
 
@@ -4187,15 +4233,11 @@ fn alloc_ty(cx: @block_ctxt, t: ty::t) -> result {
     // past caller conventions and may well make sense again,
     // so we leave it as-is.
 
-    if bcx_tcx(cx).sess.opts.do_gc {
-        bcx = gc::add_gc_root(bcx, val, t);
-    }
-
     ret rslt(cx, val);
 }
 
 fn alloc_local(cx: @block_ctxt, local: @ast::local) -> @block_ctxt {
-    let t = node_id_type(bcx_ccx(cx), local.node.id);
+    let t = node_id_type(cx, local.node.id);
     let p = normalize_pat(bcx_tcx(cx), local.node.pat);
     let is_simple = alt p.node {
       ast::pat_ident(_, none) { true } _ { false }
@@ -4239,9 +4281,9 @@ fn trans_block_dps(bcx: @block_ctxt, b: ast::blk, dest: dest)
     }
     alt b.node.expr {
       some(e) {
-        let bt = ty::type_is_bot(bcx_tcx(bcx), ty::expr_ty(bcx_tcx(bcx), e));
+        let bt = ty::type_is_bot(bcx_tcx(bcx), expr_ty(bcx, e));
         debuginfo::update_source_pos(bcx, e.span);
-        bcx = trans_expr(bcx, e, bt ? ignore : dest);
+        bcx = trans_expr(bcx, e, if bt { ignore } else { dest });
       }
       _ { assert dest == ignore || bcx.unreachable; }
     }
@@ -4249,14 +4291,6 @@ fn trans_block_dps(bcx: @block_ctxt, b: ast::blk, dest: dest)
     ret rv;
 }
 
-fn new_local_ctxt(ccx: @crate_ctxt) -> @local_ctxt {
-    let pth: [str] = [];
-    ret @{path: pth,
-          module_path: [ccx.link_meta.name],
-          ccx: ccx};
-}
-
-
 // Creates the standard quartet of basic blocks: static allocas, copy args,
 // derived tydescs, and dynamic allocas.
 fn mk_standard_basic_blocks(llfn: ValueRef) ->
@@ -4289,9 +4323,10 @@ fn mk_standard_basic_blocks(llfn: ValueRef) ->
 //  - create_llargs_for_fn_args.
 //  - new_fn_ctxt
 //  - trans_args
-fn new_fn_ctxt_w_id(cx: @local_ctxt, llfndecl: ValueRef,
-                    id: ast::node_id, rstyle: ast::ret_style)
-    -> @fn_ctxt {
+fn new_fn_ctxt_w_id(ccx: @crate_ctxt, path: path,
+                    llfndecl: ValueRef, id: ast::node_id,
+                    param_substs: option<[ty::t]>,
+                    sp: option<span>) -> @fn_ctxt {
     let llbbs = mk_standard_basic_blocks(llfndecl);
     ret @{llfn: llfndecl,
           llenv: llvm::LLVMGetParam(llfndecl, 1u as c_uint),
@@ -4310,12 +4345,15 @@ fn new_fn_ctxt_w_id(cx: @local_ctxt, llfndecl: ValueRef,
           mutable lltyparams: [],
           derived_tydescs: ty::new_ty_hash(),
           id: id,
-          ret_style: rstyle,
-          lcx: cx};
+          param_substs: param_substs,
+          span: sp,
+          path: path,
+          ccx: ccx};
 }
 
-fn new_fn_ctxt(cx: @local_ctxt, llfndecl: ValueRef) -> @fn_ctxt {
-    ret new_fn_ctxt_w_id(cx, llfndecl, -1, ast::return_val);
+fn new_fn_ctxt(ccx: @crate_ctxt, path: path, llfndecl: ValueRef,
+               sp: option<span>) -> @fn_ctxt {
+    ret new_fn_ctxt_w_id(ccx, path, llfndecl, -1, none, sp);
 }
 
 // NB: must keep 4 fns in sync:
@@ -4379,11 +4417,17 @@ fn create_llargs_for_fn_args(cx: @fn_ctxt, ty_self: self_arg,
 
 fn copy_args_to_allocas(fcx: @fn_ctxt, bcx: @block_ctxt, args: [ast::arg],
                         arg_tys: [ty::arg]) -> @block_ctxt {
+    let tcx = bcx_tcx(bcx);
     let arg_n: uint = 0u, bcx = bcx;
+    let epic_fail = fn@() -> ! {
+        tcx.sess.bug("Someone forgot\
+                to document an invariant in copy_args_to_allocas!");
+    };
     for arg in arg_tys {
         let id = args[arg_n].id;
-        let argval = alt fcx.llargs.get(id) { local_mem(v) { v } };
-        alt arg.mode {
+        let argval = alt fcx.llargs.get(id) { local_mem(v) { v }
+                                              _ { epic_fail() } };
+        alt ty::resolved_mode(tcx, arg.mode) {
           ast::by_mut_ref { }
           ast::by_move | ast::by_copy { add_clean(bcx, argval, arg.ty); }
           ast::by_val {
@@ -4406,9 +4450,13 @@ fn copy_args_to_allocas(fcx: @fn_ctxt, bcx: @block_ctxt, args: [ast::arg],
     ret bcx;
 }
 
+// cries out for a precondition
 fn arg_tys_of_fn(ccx: @crate_ctxt, id: ast::node_id) -> [ty::arg] {
-    alt ty::struct(ccx.tcx, ty::node_id_to_type(ccx.tcx, id)) {
+    let tt = ty::node_id_to_type(ccx.tcx, id);
+    alt ty::struct(ccx.tcx, tt) {
       ty::ty_fn({inputs, _}) { inputs }
+      _ { ccx.sess.bug(#fmt("arg_tys_of_fn called on non-function\
+            type %s", ty_to_str(ccx.tcx, tt)));}
     }
 }
 
@@ -4430,23 +4478,25 @@ enum self_arg { impl_self(ty::t), no_self, }
 // trans_closure: Builds an LLVM function out of a source function.
 // If the function closes over its environment a closure will be
 // returned.
-fn trans_closure(cx: @local_ctxt, decl: ast::fn_decl,
+fn trans_closure(ccx: @crate_ctxt, path: path, decl: ast::fn_decl,
                  body: ast::blk, llfndecl: ValueRef,
                  ty_self: self_arg, ty_params: [ast::ty_param],
+                 param_substs: option<[ty::t]>,
                  id: ast::node_id, maybe_load_env: fn(@fn_ctxt)) {
     set_uwtable(llfndecl);
 
     // Set up arguments to the function.
-    let fcx = new_fn_ctxt_w_id(cx, llfndecl, id, decl.cf);
+    let fcx = new_fn_ctxt_w_id(ccx, path, llfndecl, id, param_substs,
+                               some(body.span));
     create_llargs_for_fn_args(fcx, ty_self, decl.inputs, ty_params);
 
     // Create the first basic block in the function and keep a handle on it to
     //  pass to finish_fn later.
-    let bcx = new_top_block_ctxt(fcx);
+    let bcx = new_top_block_ctxt(fcx, some(body.span));
     let lltop = bcx.llbb;
-    let block_ty = node_id_type(cx.ccx, body.node.id);
+    let block_ty = node_id_type(bcx, body.node.id);
 
-    let arg_tys = arg_tys_of_fn(fcx.lcx.ccx, id);
+    let arg_tys = arg_tys_of_fn(fcx.ccx, id);
     bcx = copy_args_to_allocas(fcx, bcx, decl.inputs, arg_tys);
 
     maybe_load_env(fcx);
@@ -4456,15 +4506,13 @@ fn trans_closure(cx: @local_ctxt, decl: ast::fn_decl,
     // trans_mod, trans_item, et cetera) and those that do
     // (trans_block, trans_expr, et cetera).
     if option::is_none(body.node.expr) ||
-       ty::type_is_bot(cx.ccx.tcx, block_ty) ||
-       ty::type_is_nil(cx.ccx.tcx, block_ty) {
+       ty::type_is_bot(ccx.tcx, block_ty) ||
+       ty::type_is_nil(ccx.tcx, block_ty) {
         bcx = trans_block(bcx, body);
     } else {
         bcx = trans_block_dps(bcx, body, save_in(fcx.llretptr));
     }
 
-    // FIXME: until LLVM has a unit type, we are moving around
-    // C_nil values rather than their void type.
     if !bcx.unreachable { build_return(bcx); }
     // Insert the mandatory first few basic blocks before lltop.
     finish_fn(fcx, lltop);
@@ -4472,38 +4520,40 @@ fn trans_closure(cx: @local_ctxt, decl: ast::fn_decl,
 
 // trans_fn: creates an LLVM function corresponding to a source language
 // function.
-fn trans_fn(cx: @local_ctxt, sp: span, decl: ast::fn_decl, body: ast::blk,
-            llfndecl: ValueRef, ty_self: self_arg, ty_params: [ast::ty_param],
+fn trans_fn(ccx: @crate_ctxt, path: path, decl: ast::fn_decl,
+            body: ast::blk, llfndecl: ValueRef, ty_self: self_arg,
+            ty_params: [ast::ty_param], param_substs: option<[ty::t]>,
             id: ast::node_id) {
-    let do_time = cx.ccx.sess.opts.stats;
-    let start = do_time ? time::get_time() : {sec: 0u32, usec: 0u32};
-    let fcx = option::none;
-    trans_closure(cx, decl, body, llfndecl, ty_self, ty_params, id,
-                  {|new_fcx| fcx = option::some(new_fcx);});
-    if cx.ccx.sess.opts.extra_debuginfo {
-        debuginfo::create_function(option::get(fcx), sp);
-    }
+    let do_time = ccx.sess.opts.stats;
+    let start = if do_time { time::get_time() }
+                else { {sec: 0u32, usec: 0u32} };
+    trans_closure(ccx, path, decl, body, llfndecl, ty_self,
+                  ty_params, param_substs, id, {|fcx|
+        if ccx.sess.opts.extra_debuginfo {
+            debuginfo::create_function(fcx);
+        }
+    });
     if do_time {
         let end = time::get_time();
-        log_fn_time(cx.ccx, str::connect(cx.path, "::"), start, end);
+        log_fn_time(ccx, path_str(path), start, end);
     }
 }
 
-fn trans_res_ctor(cx: @local_ctxt, dtor: ast::fn_decl,
+fn trans_res_ctor(ccx: @crate_ctxt, path: path, dtor: ast::fn_decl,
                   ctor_id: ast::node_id, ty_params: [ast::ty_param]) {
-    let ccx = cx.ccx;
-
     // Create a function for the constructor
     let llctor_decl = ccx.item_ids.get(ctor_id);
-    let fcx = new_fn_ctxt(cx, llctor_decl);
-    let ret_t = ty::ret_ty_of_fn(cx.ccx.tcx, ctor_id);
+    let fcx = new_fn_ctxt_w_id(ccx, path, llctor_decl, ctor_id, none, none);
+    let ret_t = ty::ret_ty_of_fn(ccx.tcx, ctor_id);
     create_llargs_for_fn_args(fcx, no_self, dtor.inputs, ty_params);
-    let bcx = new_top_block_ctxt(fcx);
+    let bcx = new_top_block_ctxt(fcx, none);
     let lltop = bcx.llbb;
     let arg_t = arg_tys_of_fn(ccx, ctor_id)[0].ty;
     let tup_t = ty::mk_tup(ccx.tcx, [ty::mk_int(ccx.tcx), arg_t]);
     let arg = alt fcx.llargs.find(dtor.inputs[0].id) {
       some(local_mem(x)) { x }
+      _ { ccx.sess.bug("Someone forgot to document an invariant \
+            in trans_res_ctor"); }
     };
     let llretptr = fcx.llretptr;
     if ty::type_has_dynamic_size(ccx.tcx, ret_t) {
@@ -4526,25 +4576,21 @@ fn trans_res_ctor(cx: @local_ctxt, dtor: ast::fn_decl,
 }
 
 
-fn trans_enum_variant(cx: @local_ctxt, enum_id: ast::node_id,
-                     variant: ast::variant, disr: int, is_degen: bool,
-                     ty_params: [ast::ty_param]) {
-    let ccx = cx.ccx;
-
-    if vec::len::<ast::variant_arg>(variant.node.args) == 0u {
+fn trans_enum_variant(ccx: @crate_ctxt,
+                      enum_id: ast::node_id,
+                      variant: ast::variant, disr: int, is_degen: bool,
+                      ty_params: [ast::ty_param]) {
+    if vec::len(variant.node.args) == 0u {
         ret; // nullary constructors are just constants
-
     }
-    // Translate variant arguments to function arguments.
 
-    let fn_args: [ast::arg] = [];
-    let i = 0u;
-    for varg: ast::variant_arg in variant.node.args {
-        fn_args +=
-            [{mode: ast::by_copy,
-              ty: varg.ty,
-              ident: "arg" + uint::to_str(i, 10u),
-              id: varg.id}];
+    // Translate variant arguments to function arguments.
+    let fn_args = [], i = 0u;
+    for varg in variant.node.args {
+        fn_args += [{mode: ast::expl(ast::by_copy),
+                     ty: varg.ty,
+                     ident: "arg" + uint::to_str(i, 10u),
+                     id: varg.id}];
     }
     assert (ccx.item_ids.contains_key(variant.node.id));
     let llfndecl: ValueRef;
@@ -4552,37 +4598,36 @@ fn trans_enum_variant(cx: @local_ctxt, enum_id: ast::node_id,
       some(x) { llfndecl = x; }
       _ {
         ccx.sess.span_fatal(variant.span,
-                               "unbound variant id in trans_enum_variant");
+                            "unbound variant id in trans_enum_variant");
       }
     }
-    let fcx = new_fn_ctxt(cx, llfndecl);
+    let fcx = new_fn_ctxt_w_id(ccx, [], llfndecl, variant.node.id, none,
+                               none);
     create_llargs_for_fn_args(fcx, no_self, fn_args, ty_params);
-    let ty_param_substs: [ty::t] = [];
-    i = 0u;
+    let ty_param_substs = [], i = 0u;
     for tp: ast::ty_param in ty_params {
         ty_param_substs += [ty::mk_param(ccx.tcx, i,
-                                         ast_util::local_def(tp.id))];
+                                         local_def(tp.id))];
         i += 1u;
     }
     let arg_tys = arg_tys_of_fn(ccx, variant.node.id);
-    let bcx = new_top_block_ctxt(fcx);
+    let bcx = new_top_block_ctxt(fcx, none);
     let lltop = bcx.llbb;
     bcx = copy_args_to_allocas(fcx, bcx, fn_args, arg_tys);
 
     // Cast the enum to a type we can GEP into.
-    let llblobptr =
-        if is_degen {
-            fcx.llretptr
-        } else {
-            let llenumptr =
-                PointerCast(bcx, fcx.llretptr, T_opaque_enum_ptr(ccx));
-            let lldiscrimptr = GEPi(bcx, llenumptr, [0, 0]);
-            Store(bcx, C_int(ccx, disr), lldiscrimptr);
-            GEPi(bcx, llenumptr, [0, 1])
-        };
-    i = 0u;
-    let t_id = ast_util::local_def(enum_id);
-    let v_id = ast_util::local_def(variant.node.id);
+    let llblobptr = if is_degen {
+        fcx.llretptr
+    } else {
+        let llenumptr =
+            PointerCast(bcx, fcx.llretptr, T_opaque_enum_ptr(ccx));
+        let lldiscrimptr = GEPi(bcx, llenumptr, [0, 0]);
+        Store(bcx, C_int(ccx, disr), lldiscrimptr);
+        GEPi(bcx, llenumptr, [0, 1])
+    };
+    let i = 0u;
+    let t_id = local_def(enum_id);
+    let v_id = local_def(variant.node.id);
     for va: ast::variant_arg in variant.node.args {
         check (valid_variant_index(i, bcx, t_id, v_id));
         let rslt = GEP_enum(bcx, llblobptr, t_id, v_id, ty_param_substs, i);
@@ -4591,7 +4636,9 @@ fn trans_enum_variant(cx: @local_ctxt, enum_id: ast::node_id,
         // If this argument to this function is a enum, it'll have come in to
         // 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 = alt fcx.llargs.find(va.id) { some(local_mem(x)) { x } };
+        let llarg = alt fcx.llargs.find(va.id) { some(local_mem(x)) { x }
+          _ { bcx_tcx(bcx).sess.span_fatal(variant.span, "Someone forgot\
+                to document an invariant in trans_tag_variant"); } };
         let arg_ty = arg_tys[i].ty;
         if ty::type_contains_params(bcx_tcx(bcx), arg_ty) {
             lldestptr = PointerCast(bcx, lldestptr, val_ty(llarg));
@@ -4615,7 +4662,7 @@ fn trans_const_expr(cx: @crate_ctxt, e: @ast::expr) -> ValueRef {
         let te2 = trans_const_expr(cx, e2);
         /* Neither type is bottom, and we expect them to be unified already,
          * so the following is safe. */
-        let ty = ty::expr_ty(ccx_tcx(cx), e1);
+        let ty = ty::expr_ty(cx.tcx, e1);
         let is_float = ty::type_is_fp(ccx_tcx(cx), ty);
         let signed = ty::type_is_signed(ccx_tcx(cx), ty);
         ret alt b {
@@ -4659,7 +4706,7 @@ fn trans_const_expr(cx: @crate_ctxt, e: @ast::expr) -> ValueRef {
       }
       ast::expr_unary(u, e) {
         let te = trans_const_expr(cx, e);
-        let ty = ty::expr_ty(ccx_tcx(cx), e);
+        let ty = ty::expr_ty(cx.tcx, e);
         let is_float = ty::type_is_fp(ccx_tcx(cx), ty);
         ret alt u {
           ast::box(_)  |
@@ -4721,6 +4768,10 @@ fn c_stack_tys(ccx: @crate_ctxt,
             shim_fn_ty: T_fn([T_ptr(bundle_ty)], T_void())
         };
       }
+      _ {
+          // Precondition?
+          ccx.tcx.sess.bug("c_stack_tys called on non-function type");
+      }
     }
 }
 
@@ -4759,14 +4810,13 @@ fn c_stack_tys(ccx: @crate_ctxt,
 // stack pointer appropriately to avoid a round of copies.  (In fact, the shim
 // function itself is unnecessary). We used to do this, in fact, and will
 // perhaps do so in the future.
-fn trans_native_mod(lcx: @local_ctxt, native_mod: ast::native_mod,
-                    abi: ast::native_abi) {
-    fn build_shim_fn(lcx: @local_ctxt,
+fn trans_native_mod(ccx: @crate_ctxt,
+                    native_mod: ast::native_mod, abi: ast::native_abi) {
+    fn build_shim_fn(ccx: @crate_ctxt,
                      native_item: @ast::native_item,
                      tys: @c_stack_tys,
-                     cc: uint) -> ValueRef {
+                     cc: lib::llvm::CallConv) -> ValueRef {
         let lname = link_name(native_item);
-        let ccx = lcx_ccx(lcx);
 
         // Declare the "prototype" for the base function F:
         let llbasefn = decl_fn(ccx.llmod, lname, cc, tys.base_fn_ty);
@@ -4777,8 +4827,8 @@ fn build_shim_fn(lcx: @local_ctxt,
             ccx.llmod, shim_name, tys.shim_fn_ty);
 
         // Declare the body of the shim function:
-        let fcx = new_fn_ctxt(lcx, llshimfn);
-        let bcx = new_top_block_ctxt(fcx);
+        let fcx = new_fn_ctxt(ccx, [], llshimfn, none);
+        let bcx = new_top_block_ctxt(fcx, none);
         let lltop = bcx.llbb;
         let llargbundle = llvm::LLVMGetParam(llshimfn, 0 as c_uint);
         let i = 0u, n = vec::len(tys.arg_tys);
@@ -4791,7 +4841,7 @@ fn build_shim_fn(lcx: @local_ctxt,
 
         // Create the call itself and store the return value:
         let llretval = CallWithConv(bcx, llbasefn,
-                                    llargvals, cc as c_uint); // r
+                                    llargvals, cc); // r
         if tys.ret_def {
             // R** llretptr = &args->r;
             let llretptr = GEPi(bcx, llargbundle, [0, n as int]);
@@ -4808,14 +4858,13 @@ fn build_shim_fn(lcx: @local_ctxt,
         ret llshimfn;
     }
 
-    fn build_wrap_fn(lcx: @local_ctxt,
+    fn build_wrap_fn(ccx: @crate_ctxt,
                      tys: @c_stack_tys,
                      num_tps: uint,
                      llshimfn: ValueRef,
                      llwrapfn: ValueRef) {
-        let ccx = lcx_ccx(lcx);
-        let fcx = new_fn_ctxt(lcx, llwrapfn);
-        let bcx = new_top_block_ctxt(fcx);
+        let fcx = new_fn_ctxt(ccx, [], llwrapfn, none);
+        let bcx = new_top_block_ctxt(fcx, none);
         let lltop = bcx.llbb;
 
         // Allocate the struct and write the arguments into it.
@@ -4840,26 +4889,23 @@ fn build_wrap_fn(lcx: @local_ctxt,
         finish_fn(fcx, lltop);
     }
 
-    let ccx = lcx_ccx(lcx);
-    let cc = lib::llvm::LLVMCCallConv;
+    let cc = lib::llvm::CCallConv;
     alt abi {
       ast::native_abi_rust_intrinsic { ret; }
-      ast::native_abi_cdecl { cc = lib::llvm::LLVMCCallConv; }
-      ast::native_abi_stdcall { cc = lib::llvm::LLVMX86StdcallCallConv; }
+      ast::native_abi_cdecl { cc = lib::llvm::CCallConv; }
+      ast::native_abi_stdcall { cc = lib::llvm::X86StdcallCallConv; }
     }
 
     for native_item in native_mod.items {
       alt native_item.node {
-        ast::native_item_ty {}
         ast::native_item_fn(fn_decl, tps) {
           let id = native_item.id;
           let tys = c_stack_tys(ccx, id);
           alt ccx.item_ids.find(id) {
             some(llwrapfn) {
-              let llshimfn = build_shim_fn(lcx, native_item, tys, cc);
-              build_wrap_fn(lcx, tys, vec::len(tps), llshimfn, llwrapfn);
+              let llshimfn = build_shim_fn(ccx, native_item, tys, cc);
+              build_wrap_fn(ccx, tys, vec::len(tps), llshimfn, llwrapfn);
             }
-
             none {
               ccx.sess.span_fatal(
                   native_item.span,
@@ -4871,63 +4917,61 @@ fn build_wrap_fn(lcx: @local_ctxt,
     }
 }
 
-fn trans_item(cx: @local_ctxt, item: ast::item) {
+fn trans_item(ccx: @crate_ctxt, item: ast::item) {
+    let path = alt ccx.tcx.items.get(item.id) {
+      ast_map::node_item(_, p) { p }
+      _ { fail; }
+    };
     alt item.node {
       ast::item_fn(decl, tps, body) {
-        let sub_cx = extend_path(cx, item.ident);
-        alt cx.ccx.item_ids.find(item.id) {
+        alt ccx.item_ids.find(item.id) {
           some(llfndecl) {
-            trans_fn(sub_cx, item.span, decl, body, llfndecl, no_self, tps,
-                     item.id);
+            trans_fn(ccx, *path + [path_name(item.ident)], decl, body,
+                     llfndecl, no_self, tps, none, item.id);
           }
           _ {
-            cx.ccx.sess.span_fatal(item.span,
-                                   "unbound function item in trans_item");
+            ccx.sess.span_fatal(item.span,
+                                "unbound function item in trans_item");
           }
         }
       }
       ast::item_impl(tps, _, _, ms) {
-        impl::trans_impl(cx, item.ident, ms, item.id, tps);
+        impl::trans_impl(ccx, *path, item.ident, ms, item.id, tps);
       }
       ast::item_res(decl, tps, body, dtor_id, ctor_id) {
-        trans_res_ctor(cx, decl, ctor_id, tps);
+        trans_res_ctor(ccx, *path, decl, ctor_id, tps);
 
         // Create a function for the destructor
-        alt cx.ccx.item_ids.find(item.id) {
+        alt ccx.item_ids.find(item.id) {
           some(lldtor_decl) {
-            trans_fn(cx, item.span, decl, body, lldtor_decl, no_self,
-                     tps, dtor_id);
+            trans_fn(ccx, *path + [path_name(item.ident)], decl, body,
+                     lldtor_decl, no_self, tps, none, dtor_id);
           }
           _ {
-            cx.ccx.sess.span_fatal(item.span, "unbound dtor in trans_item");
+            ccx.sess.span_fatal(item.span, "unbound dtor in trans_item");
           }
         }
       }
       ast::item_mod(m) {
-        let sub_cx =
-            @{path: cx.path + [item.ident],
-              module_path: cx.module_path + [item.ident] with *cx};
-        trans_mod(sub_cx, m);
+        trans_mod(ccx, m);
       }
       ast::item_enum(variants, tps) {
-        let sub_cx = extend_path(cx, item.ident);
         let degen = vec::len(variants) == 1u;
-        let vi = ty::enum_variants(cx.ccx.tcx, {crate: ast::local_crate,
-                                               node: item.id});
+        let vi = ty::enum_variants(ccx.tcx, local_def(item.id));
         let i = 0;
         for variant: ast::variant in variants {
-            trans_enum_variant(sub_cx, item.id, variant,
-                              vi[i].disr_val, degen, tps);
+            trans_enum_variant(ccx, item.id, variant,
+                               vi[i].disr_val, degen, tps);
             i += 1;
         }
       }
-      ast::item_const(_, expr) { trans_const(cx.ccx, expr, item.id); }
+      ast::item_const(_, expr) { trans_const(ccx, expr, item.id); }
       ast::item_native_mod(native_mod) {
         let abi = alt attr::native_abi(item.attrs) {
           either::right(abi_) { abi_ }
-          either::left(msg) { cx.ccx.sess.span_fatal(item.span, msg) }
+          either::left(msg) { ccx.sess.span_fatal(item.span, msg) }
         };
-        trans_native_mod(cx, native_mod, abi);
+        trans_native_mod(ccx, native_mod, abi);
       }
       _ {/* fall through */ }
     }
@@ -4938,8 +4982,8 @@ fn trans_item(cx: @local_ctxt, item: ast::item) {
 // separate modules in the compiled program.  That's because modules exist
 // only as a convenience for humans working with the code, to organize names
 // and control visibility.
-fn trans_mod(cx: @local_ctxt, m: ast::_mod) {
-    for item: @ast::item in m.items { trans_item(cx, *item); }
+fn trans_mod(ccx: @crate_ctxt, m: ast::_mod) {
+    for item in m.items { trans_item(ccx, *item); }
 }
 
 fn get_pair_fn_ty(llpairty: TypeRef) -> TypeRef {
@@ -4948,11 +4992,10 @@ fn get_pair_fn_ty(llpairty: TypeRef) -> TypeRef {
     ret struct_elt(llpairty, 0u);
 }
 
-fn register_fn(ccx: @crate_ctxt, sp: span, path: [str], flav: str,
+fn register_fn(ccx: @crate_ctxt, sp: span, path: path, flav: str,
                ty_params: [ast::ty_param], node_id: ast::node_id) {
     // FIXME: pull this out
-    let t = node_id_type(ccx, node_id);
-    check returns_non_ty_var(ccx, t);
+    let t = ty::node_id_to_type(ccx.tcx, node_id);
     register_fn_full(ccx, sp, path, flav, ty_params, node_id, t);
 }
 
@@ -4960,11 +5003,9 @@ fn param_bounds(ccx: @crate_ctxt, tp: ast::ty_param) -> ty::param_bounds {
     ccx.tcx.ty_param_bounds.get(tp.id)
 }
 
-fn register_fn_full(ccx: @crate_ctxt, sp: span, path: [str], _flav: str,
+fn register_fn_full(ccx: @crate_ctxt, sp: span, path: path, _flav: str,
                     tps: [ast::ty_param], node_id: ast::node_id,
-                    node_type: ty::t)
-    : returns_non_ty_var(ccx, node_type) {
-    let path = path;
+                    node_type: ty::t) {
     let llfty = type_of_fn_from_ty(ccx, node_type,
                                    vec::map(tps, {|p| param_bounds(ccx, p)}));
     let ps: str = mangle_exported_name(ccx, path, node_type);
@@ -4972,7 +5013,7 @@ fn register_fn_full(ccx: @crate_ctxt, sp: span, path: [str], _flav: str,
     ccx.item_ids.insert(node_id, llfn);
     ccx.item_symbols.insert(node_id, ps);
 
-    let is_main: bool = is_main_name(path) && !ccx.sess.building_library;
+    let is_main = is_main_name(path) && !ccx.sess.building_library;
     if is_main { create_main_wrapper(ccx, sp, llfn, node_type); }
 }
 
@@ -4986,8 +5027,10 @@ fn create_main_wrapper(ccx: @crate_ctxt, sp: span, main_llfn: ValueRef,
     }
 
     let main_takes_argv =
+        // invariant!
         alt ty::struct(ccx.tcx, main_node_type) {
           ty::ty_fn({inputs, _}) { vec::len(inputs) != 0u }
+          _ { ccx.sess.span_fatal(sp, "main has a non-function type"); }
         };
 
     let llfn = create_main(ccx, main_llfn, main_takes_argv);
@@ -4998,17 +5041,17 @@ fn create_main(ccx: @crate_ctxt, main_llfn: ValueRef,
                    takes_argv: bool) -> ValueRef {
         let unit_ty = ty::mk_str(ccx.tcx);
         let vecarg_ty: ty::arg =
-            {mode: ast::by_val,
+            {mode: ast::expl(ast::by_val),
              ty: ty::mk_vec(ccx.tcx, {ty: unit_ty, mut: ast::imm})};
         // FIXME: mk_nil should have a postcondition
         let nt = ty::mk_nil(ccx.tcx);
         let llfty = type_of_fn(ccx, [vecarg_ty], nt, []);
         let llfdecl = decl_fn(ccx.llmod, "_rust_main",
-                              lib::llvm::LLVMCCallConv, llfty);
+                              lib::llvm::CCallConv, llfty);
 
-        let fcx = new_fn_ctxt(new_local_ctxt(ccx), llfdecl);
+        let fcx = new_fn_ctxt(ccx, [], llfdecl, none);
 
-        let bcx = new_top_block_ctxt(fcx);
+        let bcx = new_top_block_ctxt(fcx, none);
         let lltop = bcx.llbb;
 
         let lloutputarg = llvm::LLVMGetParam(llfdecl, 0 as c_uint);
@@ -5060,9 +5103,7 @@ fn create_entry_fn(ccx: @crate_ctxt, rust_main: ValueRef) {
 // on the stack).
 fn create_real_fn_pair(cx: @block_ctxt, llfnty: TypeRef, llfn: ValueRef,
                        llenvptr: ValueRef) -> ValueRef {
-    let lcx = cx.fcx.lcx;
-
-    let pair = alloca(cx, T_fn_pair(lcx.ccx, llfnty));
+    let pair = alloca(cx, T_fn_pair(bcx_ccx(cx), llfnty));
     fill_fn_pair(cx, pair, llfn, llenvptr);
     ret pair;
 }
@@ -5073,8 +5114,7 @@ fn fill_fn_pair(bcx: @block_ctxt, pair: ValueRef, llfn: ValueRef,
     let code_cell = GEPi(bcx, pair, [0, abi::fn_field_code]);
     Store(bcx, llfn, code_cell);
     let env_cell = GEPi(bcx, pair, [0, abi::fn_field_box]);
-    let llenvblobptr =
-        PointerCast(bcx, llenvptr, T_opaque_cbox_ptr(ccx));
+    let llenvblobptr = PointerCast(bcx, llenvptr, T_opaque_box_ptr(ccx));
     Store(bcx, llenvblobptr, env_cell);
 }
 
@@ -5082,12 +5122,12 @@ fn fill_fn_pair(bcx: @block_ctxt, pair: ValueRef, llfn: ValueRef,
 fn native_fn_ty_param_count(cx: @crate_ctxt, id: ast::node_id) -> uint {
     let count;
     let native_item =
-        alt cx.ast_map.find(id) { some(ast_map::node_native_item(i)) { i } };
+        // invariant?!
+        alt cx.ast_map.find(id) {
+          some(ast_map::node_native_item(i, _)) { i }
+         _ { cx.sess.bug("native_fn_ty_param_count \
+                          given a non-native item"); } };
     alt native_item.node {
-      ast::native_item_ty {
-        cx.sess.bug("register_native_fn(): native fn isn't \
-                        actually a fn");
-      }
       ast::native_item_fn(_, tps) {
         count = vec::len::<ast::ty_param>(tps);
       }
@@ -5095,13 +5135,17 @@ fn native_fn_ty_param_count(cx: @crate_ctxt, id: ast::node_id) -> uint {
     ret count;
 }
 
-fn native_fn_wrapper_type(cx: @crate_ctxt,
+
+// TODO: precondition
+fn native_fn_wrapper_type(cx: @crate_ctxt, sp: span,
                           param_bounds: [ty::param_bounds],
                           x: ty::t) -> TypeRef {
     alt ty::struct(cx.tcx, x) {
       ty::ty_fn({inputs: args, output: out, _}) {
         ret type_of_fn(cx, args, out, param_bounds);
       }
+      _ { cx.sess.span_bug(sp, "native_fn_wrapper_type got ill-typed\
+              thing"); }
     }
 }
 
@@ -5119,14 +5163,12 @@ fn link_name(i: @ast::native_item) -> str {
 }
 
 fn collect_native_item(ccx: @crate_ctxt,
-                       abi: @mutable option::t<ast::native_abi>,
-                       i: @ast::native_item,
-                       &&pt: [str],
-                       _v: vt<[str]>) {
+                       abi: @mutable option<ast::native_abi>,
+                       i: @ast::native_item) {
     alt i.node {
       ast::native_item_fn(_, tps) {
         let id = i.id;
-        let node_type = node_id_type(ccx, id);
+        let node_type = ty::node_id_to_type(ccx.tcx, id);
         let fn_abi =
             alt attr::get_meta_item_value_str_by_name(i.attrs, "abi") {
             option::none {
@@ -5151,7 +5193,7 @@ fn collect_native_item(ccx: @crate_ctxt,
             let ri_name = "rust_intrinsic_" + link_name(i);
             let llnativefn = get_extern_fn(
                 ccx.externs, ccx.llmod, ri_name,
-                lib::llvm::LLVMCCallConv, fn_type);
+                lib::llvm::CCallConv, fn_type);
             ccx.item_ids.insert(id, llnativefn);
             ccx.item_symbols.insert(id, ri_name);
           }
@@ -5160,8 +5202,10 @@ fn collect_native_item(ccx: @crate_ctxt,
             // For true external functions: create a rust wrapper
             // and link to that.  The rust wrapper will handle
             // switching to the C stack.
-            let new_pt = pt + [i.ident];
-            register_fn(ccx, i.span, new_pt, "native fn", tps, i.id);
+            let path = *alt ccx.tcx.items.get(i.id) {
+              ast_map::node_native_item(_, p) { p } _ { fail; }
+            } + [path_name(i.ident)];
+            register_fn(ccx, i.span, path, "native fn", tps, i.id);
           }
         }
       }
@@ -5169,15 +5213,19 @@ fn collect_native_item(ccx: @crate_ctxt,
     }
 }
 
-fn collect_item(ccx: @crate_ctxt, abi: @mutable option::t<ast::native_abi>,
-                i: @ast::item, &&pt: [str], v: vt<[str]>) {
-    let new_pt = pt + [i.ident];
+fn item_path(ccx: @crate_ctxt, i: @ast::item) -> path {
+    *alt ccx.tcx.items.get(i.id) {
+      ast_map::node_item(_, p) { p } _ { fail; }
+    } + [path_name(i.ident)]
+}
+
+fn collect_item(ccx: @crate_ctxt, abi: @mutable option<ast::native_abi>,
+                i: @ast::item) {
+    let my_path = item_path(ccx, i);
     alt i.node {
       ast::item_const(_, _) {
-        let typ = node_id_type(ccx, i.id);
-        let s =
-            mangle_exported_name(ccx, pt + [i.ident],
-                                 node_id_type(ccx, i.id));
+        let typ = ty::node_id_to_type(ccx.tcx, i.id);
+        let s = mangle_exported_name(ccx, my_path, typ);
         // FIXME: Could follow from a constraint on types of const
         // items
         let g = str::as_buf(s, {|buf|
@@ -5191,66 +5239,64 @@ fn collect_item(ccx: @crate_ctxt, abi: @mutable option::t<ast::native_abi>,
         // Propagate the native ABI down to collect_native_item(),
         alt attr::native_abi(i.attrs) {
           either::left(msg) { ccx.sess.span_fatal(i.span, msg); }
-          either::right(abi_) {
-            *abi = option::some(abi_);
-          }
+          either::right(abi_) { *abi = option::some(abi_); }
         }
       }
       ast::item_fn(_, tps, _) {
-        register_fn(ccx, i.span, new_pt, "fn", tps, i.id);
+        register_fn(ccx, i.span, my_path, "fn", tps,
+                    i.id);
       }
       ast::item_impl(tps, _, _, methods) {
-        let name = i.ident + int::str(i.id);
+        let path = my_path + [path_name(int::str(i.id))];
         for m in methods {
-            register_fn(ccx, i.span, pt + [name, m.ident],
+            register_fn(ccx, i.span,
+                        path + [path_name(m.ident)],
                         "impl_method", tps + m.tps, m.id);
         }
       }
       ast::item_res(_, tps, _, dtor_id, ctor_id) {
-        register_fn(ccx, i.span, new_pt, "res_ctor", tps, ctor_id);
+        register_fn(ccx, i.span, my_path, "res_ctor", tps, ctor_id);
         // Note that the destructor is associated with the item's id, not
         // the dtor_id. This is a bit counter-intuitive, but simplifies
         // ty_res, which would have to carry around two def_ids otherwise
         // -- one to identify the type, and one to find the dtor symbol.
-        let t = node_id_type(ccx, dtor_id);
+        let t = ty::node_id_to_type(ccx.tcx, dtor_id);
         // FIXME: how to get rid of this check?
-        check returns_non_ty_var(ccx, t);
-        register_fn_full(ccx, i.span, new_pt, "res_dtor", tps, i.id, t);
+        register_fn_full(ccx, i.span, my_path + [path_name("dtor")],
+                         "res_dtor", tps, i.id, t);
       }
       ast::item_enum(variants, tps) {
         for variant in variants {
             if vec::len(variant.node.args) != 0u {
-                register_fn(ccx, i.span, new_pt + [variant.node.name],
+                register_fn(ccx, i.span,
+                            my_path + [path_name(variant.node.name)],
                             "enum", tps, variant.node.id);
             }
         }
       }
       _ { }
     }
-    visit::visit_item(i, new_pt, v);
 }
 
 fn collect_items(ccx: @crate_ctxt, crate: @ast::crate) {
     let abi = @mutable none::<ast::native_abi>;
-    visit::visit_crate(*crate, [], visit::mk_vt(@{
-        visit_native_item: bind collect_native_item(ccx, abi, _, _, _),
-        visit_item: bind collect_item(ccx, abi, _, _, _)
-        with *visit::default_visitor()
+    visit::visit_crate(*crate, (), visit::mk_simple_visitor(@{
+        visit_native_item: bind collect_native_item(ccx, abi, _),
+        visit_item: bind collect_item(ccx, abi, _)
+        with *visit::default_simple_visitor()
     }));
 }
 
 // The constant translation pass.
-fn trans_constant(ccx: @crate_ctxt, it: @ast::item, &&pt: [str],
-                  v: vt<[str]>) {
-    let new_pt = pt + [it.ident];
-    visit::visit_item(it, new_pt, v);
+fn trans_constant(ccx: @crate_ctxt, it: @ast::item) {
     alt it.node {
       ast::item_enum(variants, _) {
         let vi = ty::enum_variants(ccx.tcx, {crate: ast::local_crate,
-                                            node: it.id});
-        let i = 0;
+                                             node: it.id});
+        let i = 0, path = item_path(ccx, it);
         for variant in variants {
-            let p = new_pt + [variant.node.name, "discrim"];
+            let p = path + [path_name(variant.node.name),
+                            path_name("discrim")];
             let s = mangle_exported_name(ccx, p, ty::mk_int(ccx.tcx));
             let disr_val = vi[i].disr_val;
             let discrim_gvar = str::as_buf(s, {|buf|
@@ -5259,27 +5305,27 @@ fn trans_constant(ccx: @crate_ctxt, it: @ast::item, &&pt: [str],
             llvm::LLVMSetInitializer(discrim_gvar, C_int(ccx, disr_val));
             llvm::LLVMSetGlobalConstant(discrim_gvar, True);
             ccx.discrims.insert(
-                ast_util::local_def(variant.node.id), discrim_gvar);
+                local_def(variant.node.id), discrim_gvar);
             ccx.discrim_symbols.insert(variant.node.id, s);
             i += 1;
         }
       }
       ast::item_impl(tps, some(@{node: ast::ty_path(_, id), _}), _, ms) {
         let i_did = ast_util::def_id_of_def(ccx.tcx.def_map.get(id));
-        impl::trans_impl_vtable(ccx, pt, i_did, ms, tps, it);
+        impl::trans_impl_vtable(ccx, item_path(ccx, it), i_did, ms, tps, it);
       }
       ast::item_iface(_, _) {
-        impl::trans_iface_vtable(ccx, pt, it);
+        impl::trans_iface_vtable(ccx, item_path(ccx, it), it);
       }
       _ { }
     }
 }
 
 fn trans_constants(ccx: @crate_ctxt, crate: @ast::crate) {
-    let visitor =
-        @{visit_item: bind trans_constant(ccx, _, _, _)
-             with *visit::default_visitor()};
-    visit::visit_crate(*crate, [], visit::mk_vt(visitor));
+    visit::visit_crate(*crate, (), visit::mk_simple_visitor(@{
+        visit_item: bind trans_constant(ccx, _)
+        with *visit::default_simple_visitor()
+    }));
 }
 
 fn vp2i(cx: @block_ctxt, v: ValueRef) -> ValueRef {
@@ -5354,11 +5400,10 @@ fn trap(bcx: @block_ctxt) {
 fn create_module_map(ccx: @crate_ctxt) -> ValueRef {
     let elttype = T_struct([ccx.int_type, ccx.int_type]);
     let maptype = T_array(elttype, ccx.module_data.size() + 1u);
-    let map =
-        str::as_buf("_rust_mod_map",
-                    {|buf| llvm::LLVMAddGlobal(ccx.llmod, maptype, buf) });
-    llvm::LLVMSetLinkage(map,
-                         lib::llvm::LLVMInternalLinkage as llvm::Linkage);
+    let map = str::as_buf("_rust_mod_map", {|buf|
+        llvm::LLVMAddGlobal(ccx.llmod, maptype, buf)
+    });
+    lib::llvm::SetLinkage(map, lib::llvm::InternalLinkage);
     let elts: [ValueRef] = [];
     ccx.module_data.items {|key, val|
         let elt = C_struct([p2i(ccx, C_cstr(ccx, key)),
@@ -5379,15 +5424,14 @@ fn decl_crate_map(sess: session::session, mapname: str,
     let n_subcrates = 1;
     let cstore = sess.cstore;
     while cstore::have_crate_data(cstore, n_subcrates) { n_subcrates += 1; }
-    let mapname = sess.building_library ? mapname : "toplevel";
+    let mapname = if sess.building_library { mapname } else { "toplevel" };
     let sym_name = "_rust_crate_map_" + mapname;
     let arrtype = T_array(int_type, n_subcrates as uint);
     let maptype = T_struct([int_type, arrtype]);
     let map = str::as_buf(sym_name, {|buf|
         llvm::LLVMAddGlobal(llmod, maptype, buf)
     });
-    llvm::LLVMSetLinkage(map, lib::llvm::LLVMExternalLinkage
-                         as llvm::Linkage);
+    lib::llvm::SetLinkage(map, lib::llvm::ExternalLinkage);
     ret map;
 }
 
@@ -5421,19 +5465,14 @@ fn write_metadata(cx: @crate_ctxt, crate: @ast::crate) {
     str::as_buf(cx.sess.targ_cfg.target_strs.meta_sect_name, {|buf|
         llvm::LLVMSetSection(llglobal, buf)
     });
-    llvm::LLVMSetLinkage(llglobal,
-                         lib::llvm::LLVMInternalLinkage as llvm::Linkage);
+    lib::llvm::SetLinkage(llglobal, lib::llvm::InternalLinkage);
 
     let t_ptr_i8 = T_ptr(T_i8());
     llglobal = llvm::LLVMConstBitCast(llglobal, t_ptr_i8);
-    let llvm_used =
-        str::as_buf("llvm.used",
-                    {|buf|
-                        llvm::LLVMAddGlobal(cx.llmod, T_array(t_ptr_i8, 1u),
-                                            buf)
-                    });
-    llvm::LLVMSetLinkage(llvm_used,
-                         lib::llvm::LLVMAppendingLinkage as llvm::Linkage);
+    let llvm_used = str::as_buf("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]));
 }
 
@@ -5514,6 +5553,7 @@ fn trans_crate(sess: session::session, crate: @ast::crate, tcx: ty::ctxt,
           consts: new_int_hash::<ValueRef>(),
           tydescs: ty::new_ty_hash(),
           dicts: map::mk_hashmap(hash_dict_id, {|a, b| a == b}),
+          monomorphized: map::mk_hashmap(hash_mono_id, {|a, b| a == b}),
           module_data: new_str_hash::<ValueRef>(),
           lltypes: ty::new_ty_hash(),
           names: new_namegen(),
@@ -5544,20 +5584,19 @@ fn trans_crate(sess: session::session, crate: @ast::crate, tcx: ty::ctxt,
           opaque_vec_type: T_opaque_vec(targ_cfg),
           builder: BuilderRef_res(llvm::LLVMCreateBuilder()),
           shape_cx: shape::mk_ctxt(llmod),
-          gc_cx: gc::mk_ctxt(),
           crate_map: crate_map,
-          dbg_cx: dbg_cx};
-    let cx = new_local_ctxt(ccx);
+          dbg_cx: dbg_cx,
+          mutable do_not_commit_warning_issued: false};
     collect_items(ccx, crate);
     trans_constants(ccx, crate);
-    trans_mod(cx, crate.node.module);
+    trans_mod(ccx, crate.node.module);
     fill_crate_map(ccx, crate_map);
     emit_tydescs(ccx);
     shape::gen_shape_tables(ccx);
     write_abi_version(ccx);
 
     // Translate the metadata.
-    write_metadata(cx.ccx, crate);
+    write_metadata(ccx, crate);
     if ccx.sess.opts.stats {
         #error("--- trans stats ---");
         #error("n_static_tydescs: %u", ccx.stats.n_static_tydescs);
index 981c3d7d19ee7caf653dddc467c6addc00cf9812..dd3bf78f46d5bc5d883f3b13e5e914aea4549840 100644 (file)
@@ -4,13 +4,14 @@
 import lib::llvm::llvm;
 import syntax::codemap;
 import codemap::span;
-import llvm::{ValueRef, TypeRef, BasicBlockRef, BuilderRef, Opcode,
-              ModuleRef};
+import lib::llvm::{ValueRef, TypeRef, BasicBlockRef, BuilderRef, ModuleRef};
+import lib::llvm::{Opcode, IntPredicate, RealPredicate, True, False,
+                   CallConv};
 import common::{block_ctxt, T_ptr, T_nil, T_i8, T_i1, T_void,
-                T_fn, val_ty, bcx_ccx, C_i32};
+                T_fn, val_ty, bcx_ccx, C_i32, val_str};
 
 fn B(cx: @block_ctxt) -> BuilderRef {
-    let b = *cx.fcx.lcx.ccx.builder;
+    let b = *cx.fcx.ccx.builder;
     llvm::LLVMPositionBuilderAtEnd(b, cx.llbb);
     ret b;
 }
@@ -94,6 +95,10 @@ fn Invoke(cx: @block_ctxt, Fn: ValueRef, Args: [ValueRef],
     if cx.unreachable { ret; }
     assert (!cx.terminated);
     cx.terminated = true;
+    #debug["Invoke(%s with arguments (%s))",
+           val_str(bcx_ccx(cx).tn, Fn),
+           str::connect(vec::map(Args, {|a|val_str(bcx_ccx(cx).tn, a)}),
+                        ", ")];
     unsafe {
         llvm::LLVMBuildInvoke(B(cx), Fn, vec::to_ptr(Args),
                               vec::len(Args) as c_uint, Then, Catch,
@@ -110,8 +115,7 @@ fn FastInvoke(cx: @block_ctxt, Fn: ValueRef, Args: [ValueRef],
         let v = llvm::LLVMBuildInvoke(B(cx), Fn, vec::to_ptr(Args),
                                       vec::len(Args) as c_uint,
                                       Then, Catch, noname());
-        llvm::LLVMSetInstructionCallConv(
-            v, lib::llvm::LLVMFastCallConv as c_uint);
+        lib::llvm::SetInstructionCallConv(v, lib::llvm::FastCallConv);
     }
 }
 
@@ -308,7 +312,7 @@ fn Free(cx: @block_ctxt, PointerVal: ValueRef) {
 }
 
 fn Load(cx: @block_ctxt, PointerVal: ValueRef) -> ValueRef {
-    let ccx = cx.fcx.lcx.ccx;
+    let ccx = cx.fcx.ccx;
     if cx.unreachable {
         let ty = val_ty(PointerVal);
         let eltty = if llvm::LLVMGetTypeKind(ty) == 11 as c_int {
@@ -467,12 +471,14 @@ fn FPCast(cx: @block_ctxt, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
 
 
 /* Comparisons */
-fn ICmp(cx: @block_ctxt, Op: uint, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
+fn ICmp(cx: @block_ctxt, Op: IntPredicate, LHS: ValueRef, RHS: ValueRef)
+    -> ValueRef {
     if cx.unreachable { ret llvm::LLVMGetUndef(T_i1()); }
     ret llvm::LLVMBuildICmp(B(cx), Op as c_uint, LHS, RHS, noname());
 }
 
-fn FCmp(cx: @block_ctxt, Op: uint, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
+fn FCmp(cx: @block_ctxt, Op: RealPredicate, LHS: ValueRef, RHS: ValueRef)
+    -> ValueRef {
     if cx.unreachable { ret llvm::LLVMGetUndef(T_i1()); }
     ret llvm::LLVMBuildFCmp(B(cx), Op as c_uint, LHS, RHS, noname());
 }
@@ -505,7 +511,7 @@ fn AddIncomingToPhi(phi: ValueRef, val: ValueRef, bb: BasicBlockRef) {
 }
 
 fn _UndefReturn(cx: @block_ctxt, Fn: ValueRef) -> ValueRef {
-    let ccx = cx.fcx.lcx.ccx;
+    let ccx = cx.fcx.ccx;
     let ty = val_ty(Fn);
     let retty = if llvm::LLVMGetTypeKind(ty) == 8 as c_int {
         llvm::LLVMGetReturnType(ty) } else { ccx.int_type };
@@ -528,9 +534,12 @@ fn add_comment(bcx: @block_ctxt, text: str) {
         check str::is_not_empty("$");
         let sanitized = str::replace(text, "$", "");
         let comment_text = "; " + sanitized;
-        let asm = str::as_buf(comment_text, { |c|
-            str::as_buf("", { |e|
-                llvm::LLVMConstInlineAsm(T_fn([], T_void()), c, e, 0, 0)})});
+        let asm = str::as_buf(comment_text, {|c|
+            str::as_buf("", {|e|
+                llvm::LLVMConstInlineAsm(T_fn([], T_void()), c, e,
+                                         False, False)
+            })
+        });
         Call(bcx, asm, []);
     }
 }
@@ -548,19 +557,18 @@ fn FastCall(cx: @block_ctxt, Fn: ValueRef, Args: [ValueRef]) -> ValueRef {
     unsafe {
         let v = llvm::LLVMBuildCall(B(cx), Fn, vec::to_ptr(Args),
                                     vec::len(Args) as c_uint, noname());
-        llvm::LLVMSetInstructionCallConv(
-            v, lib::llvm::LLVMFastCallConv as c_uint);
+        lib::llvm::SetInstructionCallConv(v, lib::llvm::FastCallConv);
         ret v;
     }
 }
 
 fn CallWithConv(cx: @block_ctxt, Fn: ValueRef, Args: [ValueRef],
-                Conv: c_uint) -> ValueRef {
+                Conv: CallConv) -> ValueRef {
     if cx.unreachable { ret _UndefReturn(cx, Fn); }
     unsafe {
         let v = llvm::LLVMBuildCall(B(cx), Fn, vec::to_ptr(Args),
                                     vec::len(Args) as c_uint, noname());
-        llvm::LLVMSetInstructionCallConv(v, Conv);
+        lib::llvm::SetInstructionCallConv(v, Conv);
         ret v;
     }
 }
@@ -617,7 +625,7 @@ fn IsNotNull(cx: @block_ctxt, Val: ValueRef) -> ValueRef {
 }
 
 fn PtrDiff(cx: @block_ctxt, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
-    let ccx = cx.fcx.lcx.ccx;
+    let ccx = cx.fcx.ccx;
     if cx.unreachable { ret llvm::LLVMGetUndef(ccx.int_type); }
     ret llvm::LLVMBuildPtrDiff(B(cx), LHS, RHS, noname());
 }
index 710f0ecc54a5e5804fd706d8e368053c5b448a75..12997f0e5393b0de95ef217989ff900ef5018ab7 100644 (file)
@@ -2,7 +2,7 @@
 import syntax::ast;
 import syntax::ast_util;
 import lib::llvm::llvm;
-import llvm::{ValueRef, TypeRef};
+import lib::llvm::{ValueRef, TypeRef};
 import common::*;
 import build::*;
 import base::*;
     mangle_internal_name_by_path,
     mangle_internal_name_by_path_and_seq};
 import util::ppaux::ty_to_str;
-import base::{
-    trans_shared_malloc,
-    type_of_inner,
-    node_id_type,
-    INIT,
-    trans_shared_free,
-    drop_ty,
-    new_sub_block_ctxt,
-    load_if_immediate,
-    dest
-};
 import shape::{size_of};
+import ast_map::{path, path_mod, path_name};
 
 // ___Good to know (tm)__________________________________________________
 //
 // The layout of a closure environment in memory is
 // roughly as follows:
 //
-// struct closure_box {
-//   unsigned ref_count; // only used for shared environments
-//   type_desc *tydesc;  // descriptor for the "struct closure_box" type
-//   type_desc *bound_tdescs[]; // bound descriptors
-//   struct {
-//     upvar1_t upvar1;
-//     ...
-//     upvarN_t upvarN;
-//   } bound_data;
+// struct rust_opaque_box {         // see rust_internal.h
+//   unsigned ref_count;            // only used for fn@()
+//   type_desc *tydesc;             // describes closure_data struct
+//   rust_opaque_box *prev;         // (used internally by memory alloc)
+//   rust_opaque_box *next;         // (used internally by memory alloc)
+//   struct closure_data {
+//       type_desc *bound_tdescs[]; // bound descriptors
+//       struct {
+//         upvar1_t upvar1;
+//         ...
+//         upvarN_t upvarN;
+//       } bound_data;
+//    }
 // };
 //
-// Note that the closure carries a type descriptor that describes the
-// closure itself.  Trippy.  This is needed because the precise types
-// of the closed over data are lost in the closure type (`fn(T)->U`),
-// so if we need to take/drop, we must know what data is in the upvars
-// and so forth.  This struct is defined in the code in mk_closure_tys()
-// below.
-//
-// The allocation strategy for this closure depends on the closure
-// type.  For a sendfn, the closure (and the referenced type
-// descriptors) will be allocated in the exchange heap.  For a fn, the
-// closure is allocated in the task heap and is reference counted.
-// For a block, the closure is allocated on the stack.  Note that in
-// all cases we allocate space for a ref count just to make our lives
-// easier when upcasting to fn(T)->U, in the shape code, and so
-// forth.
+// Note that the closure is itself a rust_opaque_box.  This is true
+// even for fn~ and fn&, because we wish to keep binary compatibility
+// between all kinds of closures.  The allocation strategy for this
+// closure depends on the closure type.  For a sendfn, the closure
+// (and the referenced type descriptors) will be allocated in the
+// exchange heap.  For a fn, the closure is allocated in the task heap
+// and is reference counted.  For a block, the closure is allocated on
+// the stack.
 //
-// ## Opaque Closures ##
+// ## Opaque closures and the embedded type descriptor ##
 //
 // One interesting part of closures is that they encapsulate the data
 // that they close over.  So when I have a ptr to a closure, I do not
 // nor where its fields are located.  This is called an "opaque
 // closure".
 //
-// Typically an opaque closure suffices because I only manipulate it
-// by ptr.  The routine common::T_opaque_cbox_ptr() returns an
-// appropriate type for such an opaque closure; it allows access to the
-// first two fields, but not the others.
+// Typically an opaque closure suffices because we only manipulate it
+// by ptr.  The routine common::T_opaque_box_ptr() returns an
+// appropriate type for such an opaque closure; it allows access to
+// the box fields, but not the closure_data itself.
 //
 // But sometimes, such as when cloning or freeing a closure, we need
 // to know the full information.  That is where the type descriptor
 //
 // ## Subtleties concerning alignment ##
 //
-// You'll note that the closure_box structure is a flat structure with
-// four fields.  In some ways, it would be more convenient to use a nested
-// structure like so:
-//
-// struct {
-//   int;
-//   struct {
-//     type_desc*;
-//     type_desc*[];
-//     bound_data;
-// } }
+// It is important that we be able to locate the closure data *without
+// knowing the kind of data that is being bound*.  This can be tricky
+// because the alignment requirements of the bound data affects the
+// alignment requires of the closure_data struct as a whole.  However,
+// right now this is a non-issue in any case, because the size of the
+// rust_opaque_box header is always a mutiple of 16-bytes, which is
+// the maximum alignment requirement we ever have to worry about.
 //
-// This would be more convenient because it would allow us to use more
-// of the existing infrastructure: we could treat the inner struct as
-// a type and then hvae a boxed variant (which would add the int) etc.
-// However, there is one subtle problem with this: grouping the latter
-// 3 fields into an inner struct causes the alignment of the entire
-// struct to be the max alignment of the bound_data.  This will
-// therefore vary from closure to closure.  That would mean that we
-// cannot reliably locate the initial type_desc* in an opaque closure!
-// That's definitely a bad thing.  Therefore, I have elected to create
-// a flat structure, even though it means some mild amount of code
-// duplication (however, we used to do it the other way, and we were
-// jumping through about as many hoops just trying to wedge a ref
-// count into a unique pointer, so it's kind of a wash in the end).
+// The only reason alignment matters is that, in order to learn what data
+// is bound, we would normally first load the type descriptors: but their
+// location is ultimately depend on their content!  There is, however, a
+// workaround.  We can load the tydesc from the rust_opaque_box, which
+// describes the closure_data struct and has self-contained derived type
+// descriptors, and read the alignment from there.   It's just annoying to
+// do.  Hopefully should this ever become an issue we'll have monomorphized
+// and type descriptors will all be a bad dream.
 //
 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 enum environment_value {
     // Evaluate expr and store result in env (used for bind).
-    env_expr(@ast::expr),
+    env_expr(@ast::expr, ty::t),
 
     // Copy the value from this llvm ValueRef into the environment.
     env_copy(ValueRef, ty::t, lval_kind),
@@ -125,7 +103,7 @@ enum environment_value {
 
 fn ev_to_str(ccx: @crate_ctxt, ev: environment_value) -> str {
     alt ev {
-      env_expr(ex) { expr_to_str(ex) }
+      env_expr(ex, _) { expr_to_str(ex) }
       env_copy(v, t, lk) { #fmt("copy(%s,%s)", val_str(ccx.tn, v),
                                 ty_to_str(ccx.tcx, t)) }
       env_move(v, t, lk) { #fmt("move(%s,%s)", val_str(ccx.tn, v),
@@ -142,16 +120,21 @@ fn mk_tydesc_ty(tcx: ty::ctxt, ck: ty::closure_kind) -> ty::t {
     };
 }
 
+fn mk_tuplified_uniq_cbox_ty(tcx: ty::ctxt, cdata_ty: ty::t) -> ty::t {
+    let tydesc_ty = mk_tydesc_ty(tcx, ty::ck_uniq);
+    let cbox_ty = tuplify_cbox_ty(tcx, cdata_ty, tydesc_ty);
+    ret ty::mk_imm_uniq(tcx, cbox_ty);
+}
+
 // Given a closure ty, emits a corresponding tuple ty
 fn mk_closure_tys(tcx: ty::ctxt,
                   ck: ty::closure_kind,
                   ty_params: [fn_ty_param],
                   bound_values: [environment_value])
-    -> (ty::t, ty::t, [ty::t]) {
+    -> (ty::t, [ty::t]) {
     let bound_tys = [];
 
-    let tydesc_ty =
-        mk_tydesc_ty(tcx, ck);
+    let tydesc_ty = mk_tydesc_ty(tcx, ck);
 
     // Compute the closed over tydescs
     let param_ptrs = [];
@@ -168,100 +151,81 @@ fn mk_closure_tys(tcx: ty::ctxt,
             env_copy(_, t, _) { t }
             env_move(_, t, _) { t }
             env_ref(_, t, _) { t }
-            env_expr(e) { ty::expr_ty(tcx, e) }
+            env_expr(_, t) { t }
         }];
     }
     let bound_data_ty = ty::mk_tup(tcx, bound_tys);
 
-    let norc_tys = [tydesc_ty, ty::mk_tup(tcx, param_ptrs), bound_data_ty];
-
-    // closure_norc_ty == everything but ref count
-    //
-    // This is a hack to integrate with the cycle coll.  When you
-    // allocate memory in the task-local space, you are expected to
-    // provide a descriptor for that memory which excludes the ref
-    // count. That's what this represents.  However, this really
-    // assumes a type setup like [uint, data] where data can be a
-    // struct.  We don't use that structure here because we don't want
-    // to alignment of the first few fields being bound up in the
-    // alignment of the bound data, as would happen if we laid out
-    // that way.  For now this should be fine but ultimately we need
-    // to modify CC code or else modify box allocation interface to be
-    // a bit more flexible, perhaps taking a vec of tys in the box
-    // (which for normal rust code is always of length 1).
-    let closure_norc_ty = ty::mk_tup(tcx, norc_tys);
-
-    #debug["closure_norc_ty=%s", ty_to_str(tcx, closure_norc_ty)];
-
-    // closure_ty == ref count, data tydesc, typarams, bound data
-    let closure_ty = ty::mk_tup(tcx, [ty::mk_int(tcx)] + norc_tys);
-
-    #debug["closure_ty=%s", ty_to_str(tcx, closure_norc_ty)];
-
-    ret (closure_ty, closure_norc_ty, bound_tys);
+    let cdata_ty = ty::mk_tup(tcx, [ty::mk_tup(tcx, param_ptrs),
+                                    bound_data_ty]);
+    #debug["cdata_ty=%s", ty_to_str(tcx, cdata_ty)];
+    ret (cdata_ty, bound_tys);
 }
 
 fn allocate_cbox(bcx: @block_ctxt,
                  ck: ty::closure_kind,
-                 cbox_ty: ty::t,
-                 cbox_norc_ty: ty::t)
+                 cdata_ty: ty::t)
     -> (@block_ctxt, ValueRef, [ValueRef]) {
 
-    let ccx = bcx_ccx(bcx);
-
-    let alloc_in_heap = fn@(bcx: @block_ctxt,
-                            xchgheap: bool,
-                            &temp_cleanups: [ValueRef])
-        -> (@block_ctxt, ValueRef) {
+    // let ccx = bcx_ccx(bcx);
+    let tcx = bcx_tcx(bcx);
 
-        // n.b. If you are wondering why we don't use
-        // trans_malloc_boxed() or alloc_uniq(), see the section about
-        // "Subtleties concerning alignment" in the big comment at the
-        // top of the file.
+    fn nuke_ref_count(bcx: @block_ctxt, box: ValueRef) {
+        // Initialize ref count to arbitrary value for debugging:
+        let ccx = bcx_ccx(bcx);
+        let box = PointerCast(bcx, box, T_opaque_box_ptr(ccx));
+        let ref_cnt = GEPi(bcx, box, [0, abi::box_field_refcnt]);
+        let rc = C_int(ccx, 0x12345678);
+        Store(bcx, rc, ref_cnt);
+    }
 
-        let {bcx, val:llsz} = size_of(bcx, cbox_ty);
-        let ti = none;
-        let tydesc_ty = if xchgheap { cbox_ty } else { cbox_norc_ty };
-        let {bcx, val:lltydesc} =
-            get_tydesc(bcx, tydesc_ty, true, ti).result;
-        let malloc = {
-            if xchgheap { ccx.upcalls.shared_malloc}
-            else { ccx.upcalls.malloc }
-        };
-        let box = Call(bcx, malloc, [llsz, lltydesc]);
-        add_clean_free(bcx, box, xchgheap);
-        temp_cleanups += [box];
-        (bcx, box)
-    };
+    fn store_uniq_tydesc(bcx: @block_ctxt,
+                         cdata_ty: ty::t,
+                         box: ValueRef,
+                         &ti: option::t<@tydesc_info>) -> @block_ctxt {
+        let ccx = bcx_ccx(bcx);
+        let bound_tydesc = GEPi(bcx, box, [0, abi::box_field_tydesc]);
+        let {bcx, val: td} =
+            base::get_tydesc(bcx, cdata_ty, true, ti).result;
+        let td = Call(bcx, ccx.upcalls.create_shared_type_desc, [td]);
+        Store(bcx, td, bound_tydesc);
+        bcx
+    }
 
-    // Allocate the box:
+    // Allocate and initialize the box:
+    let ti = none;
     let temp_cleanups = [];
-    let (bcx, box, rc) = alt ck {
+    let (bcx, box) = alt ck {
       ty::ck_box {
-        let (bcx, box) = alloc_in_heap(bcx, false, temp_cleanups);
-        (bcx, box, 1)
+        let {bcx, val: box} = trans_malloc_boxed_raw(bcx, cdata_ty, ti);
+        (bcx, box)
       }
       ty::ck_uniq {
-        let (bcx, box) = alloc_in_heap(bcx, true, temp_cleanups);
-        (bcx, box, 0x12345678) // use arbitrary value for debugging
+        let uniq_cbox_ty = mk_tuplified_uniq_cbox_ty(tcx, cdata_ty);
+        check uniq::type_is_unique_box(bcx, uniq_cbox_ty);
+        let {bcx, val: box} = uniq::alloc_uniq(bcx, uniq_cbox_ty);
+        nuke_ref_count(bcx, box);
+        let bcx = store_uniq_tydesc(bcx, cdata_ty, box, ti);
+        (bcx, box)
       }
       ty::ck_block {
+        let cbox_ty = tuplify_box_ty(tcx, cdata_ty);
         let {bcx, val: box} = base::alloc_ty(bcx, cbox_ty);
-        (bcx, box, 0x12345678) // use arbitrary value for debugging
+        nuke_ref_count(bcx, box);
+        (bcx, box)
       }
     };
 
-    // Initialize ref count
-    let box = PointerCast(bcx, box, T_opaque_cbox_ptr(ccx));
-    let ref_cnt = GEPi(bcx, box, [0, abi::box_rc_field_refcnt]);
-    Store(bcx, C_int(ccx, rc), ref_cnt);
+    base::lazily_emit_tydesc_glue(bcx, abi::tydesc_field_take_glue, ti);
+    base::lazily_emit_tydesc_glue(bcx, abi::tydesc_field_drop_glue, ti);
+    base::lazily_emit_tydesc_glue(bcx, abi::tydesc_field_free_glue, ti);
 
     ret (bcx, box, temp_cleanups);
 }
 
 type closure_result = {
     llbox: ValueRef,     // llvalue of ptr to closure
-    cbox_ty: ty::t,      // type of the closure data
+    cdata_ty: ty::t,      // type of the closure data
     bcx: @block_ctxt     // final bcx
 };
 
@@ -302,34 +266,17 @@ fn maybe_clone_tydesc(bcx: @block_ctxt,
     let tcx = bcx_tcx(bcx);
 
     // compute the shape of the closure
-    let (cbox_ty, cbox_norc_ty, bound_tys) =
+    let (cdata_ty, bound_tys) =
         mk_closure_tys(tcx, ck, lltyparams, bound_values);
 
     // allocate closure in the heap
     let (bcx, llbox, temp_cleanups) =
-        allocate_cbox(bcx, ck, cbox_ty, cbox_norc_ty);
-
-    // store data tydesc.
-    alt ck {
-      ty::ck_box | ty::ck_uniq {
-        let bound_tydesc = GEPi(bcx, llbox, [0, abi::cbox_elt_tydesc]);
-        let ti = none;
-
-        let {result:closure_td, _} =
-            base::get_tydesc(bcx, cbox_ty, true, ti);
-        base::lazily_emit_tydesc_glue(bcx, abi::tydesc_field_take_glue, ti);
-        base::lazily_emit_tydesc_glue(bcx, abi::tydesc_field_drop_glue, ti);
-        base::lazily_emit_tydesc_glue(bcx, abi::tydesc_field_free_glue, ti);
-        bcx = closure_td.bcx;
-        let td = maybe_clone_tydesc(bcx, ck, closure_td.val);
-        Store(bcx, td, bound_tydesc);
-      }
-      ty::ck_block { /* skip this for blocks, not really relevant */ }
-    }
+        allocate_cbox(bcx, ck, cdata_ty);
 
     // cbox_ty has the form of a tuple: (a, b, c) we want a ptr to a
     // tuple.  This could be a ptr in uniq or a box or on stack,
     // whatever.
+    let cbox_ty = tuplify_box_ty(tcx, cdata_ty);
     let cboxptr_ty = ty::mk_ptr(tcx, {ty:cbox_ty, mut:ast::imm});
     let llbox = cast_if_we_can(bcx, llbox, cboxptr_ty);
     check type_is_tup_like(bcx, cbox_ty);
@@ -337,7 +284,8 @@ fn maybe_clone_tydesc(bcx: @block_ctxt,
     // If necessary, copy tydescs describing type parameters into the
     // appropriate slot in the closure.
     let {bcx:bcx, val:ty_params_slot} =
-        GEP_tup_like(bcx, cbox_ty, llbox, [0, abi::cbox_elt_ty_params]);
+        GEP_tup_like(bcx, cbox_ty, llbox,
+                     [0, abi::box_field_body, abi::closure_body_ty_params]);
     let off = 0;
     for tp in lltyparams {
         let cloned_td = maybe_clone_tydesc(bcx, ck, tp.desc);
@@ -361,12 +309,14 @@ fn maybe_clone_tydesc(bcx: @block_ctxt,
         }
 
         let bound_data = GEP_tup_like_1(bcx, cbox_ty, llbox,
-                                        [0, abi::cbox_elt_bindings,
+                                        [0,
+                                         abi::box_field_body,
+                                         abi::closure_body_bindings,
                                          i as int]);
         bcx = bound_data.bcx;
         let bound_data = bound_data.val;
         alt bv {
-          env_expr(e) {
+          env_expr(e, _) {
             bcx = base::trans_expr_save_in(bcx, e, bound_data);
             add_clean_temp_mem(bcx, bound_data, bound_tys[i]);
             temp_cleanups += [bound_data];
@@ -399,7 +349,7 @@ fn maybe_clone_tydesc(bcx: @block_ctxt,
     }
     for cleanup in temp_cleanups { revoke_clean(bcx, cleanup); }
 
-    ret {llbox: llbox, cbox_ty: cbox_ty, bcx: bcx};
+    ret {llbox: llbox, cdata_ty: cdata_ty, bcx: bcx};
 }
 
 // Given a context and a list of upvars, build a closure. This just
@@ -417,7 +367,7 @@ fn build_closure(bcx0: @block_ctxt,
     vec::iter(cap_vars) { |cap_var|
         let lv = trans_local_var(bcx, cap_var.def);
         let nid = ast_util::def_id_of_def(cap_var.def).node;
-        let ty = ty::node_id_to_monotype(tcx, nid);
+        let ty = ty::node_id_to_type(tcx, nid);
         alt cap_var.mode {
           capture::cap_ref {
             assert ck == ty::ck_block;
@@ -443,22 +393,20 @@ fn build_closure(bcx0: @block_ctxt,
 // with the upvars and type descriptors.
 fn load_environment(enclosing_cx: @block_ctxt,
                     fcx: @fn_ctxt,
-                    cbox_ty: ty::t,
+                    cdata_ty: ty::t,
                     cap_vars: [capture::capture_var],
                     ck: ty::closure_kind) {
     let bcx = new_raw_block_ctxt(fcx, fcx.llloadenv);
-    let ccx = bcx_ccx(bcx);
-    let tcx = bcx_tcx(bcx);
 
-    let cboxptr_ty = ty::mk_ptr(tcx, {ty:cbox_ty, mut:ast::imm});
-    check (type_has_static_size(ccx, cboxptr_ty));
-    let llty = type_of(ccx, cboxptr_ty);
-    let llclosure = PointerCast(bcx, fcx.llenv, llty);
+    // Load a pointer to the closure data, skipping over the box header:
+    let llcdata = base::opaque_box_body(bcx, cdata_ty, fcx.llenv);
 
     // Populate the type parameters from the environment. We need to
     // do this first because the tydescs are needed to index into
     // the bindings if they are dynamically sized.
-    let lltydescs = GEPi(bcx, llclosure, [0, abi::cbox_elt_ty_params]);
+    check type_is_tup_like(bcx, cdata_ty);
+    let {bcx, val: lltydescs} = GEP_tup_like(bcx, cdata_ty, llcdata,
+                                            [0, abi::closure_body_ty_params]);
     let off = 0;
     for tp in copy enclosing_cx.fcx.lltyparams {
         let tydesc = Load(bcx, GEPi(bcx, lltydescs, [0, off]));
@@ -476,15 +424,15 @@ fn load_environment(enclosing_cx: @block_ctxt,
     }
 
     // Populate the upvars from the environment.
-    let path = [0, abi::cbox_elt_bindings];
     let i = 0u;
     vec::iter(cap_vars) { |cap_var|
         alt cap_var.mode {
           capture::cap_drop { /* ignore */ }
           _ {
-            check type_is_tup_like(bcx, cbox_ty);
-            let upvarptr = GEP_tup_like(
-                bcx, cbox_ty, llclosure, path + [i as int]);
+            check type_is_tup_like(bcx, cdata_ty);
+            let upvarptr =
+                GEP_tup_like(bcx, cdata_ty, llcdata,
+                             [0, abi::closure_body_bindings, i as int]);
             bcx = upvarptr.bcx;
             let llupvarptr = upvarptr.val;
             alt ck {
@@ -509,19 +457,20 @@ fn trans_expr_fn(bcx: @block_ctxt,
                  dest: dest) -> @block_ctxt {
     if dest == ignore { ret bcx; }
     let ccx = bcx_ccx(bcx), bcx = bcx;
-    let fty = node_id_type(ccx, id);
+    let fty = node_id_type(bcx, id);
     let llfnty = type_of_fn_from_ty(ccx, fty, []);
-    let sub_cx = extend_path(bcx.fcx.lcx, ccx.names("anon"));
-    let s = mangle_internal_name_by_path(ccx, sub_cx.path);
+    let sub_path = bcx.fcx.path + [path_name("anon")];
+    let s = mangle_internal_name_by_path(ccx, sub_path);
     let llfn = decl_internal_cdecl_fn(ccx.llmod, s, llfnty);
-    register_fn(ccx, sp, sub_cx.path, "anon fn", [], id);
+    register_fn(ccx, sp, sub_path, "anon fn", [], id);
 
     let trans_closure_env = fn@(ck: ty::closure_kind) -> ValueRef {
         let cap_vars = capture::compute_capture_vars(
             ccx.tcx, id, proto, cap_clause);
-        let {llbox, cbox_ty, bcx} = build_closure(bcx, cap_vars, ck);
-        trans_closure(sub_cx, decl, body, llfn, no_self, [], id, {|fcx|
-            load_environment(bcx, fcx, cbox_ty, cap_vars, ck);
+        let {llbox, cdata_ty, bcx} = build_closure(bcx, cap_vars, ck);
+        trans_closure(ccx, sub_path, decl, body, llfn, no_self, [],
+                      bcx.fcx.param_substs, id, {|fcx|
+            load_environment(bcx, fcx, cdata_ty, cap_vars, ck);
         });
         llbox
     };
@@ -531,29 +480,28 @@ fn trans_expr_fn(bcx: @block_ctxt,
       ast::proto_box { trans_closure_env(ty::ck_box) }
       ast::proto_uniq { trans_closure_env(ty::ck_uniq) }
       ast::proto_bare {
-        let closure = C_null(T_opaque_cbox_ptr(ccx));
-        trans_closure(sub_cx, decl, body, llfn, no_self, [],
+        trans_closure(ccx, sub_path, decl, body, llfn, no_self, [], none,
                       id, {|_fcx|});
-        closure
+        C_null(T_opaque_box_ptr(ccx))
       }
     };
     fill_fn_pair(bcx, get_dest_addr(dest), llfn, closure);
     ret bcx;
 }
 
-fn trans_bind(cx: @block_ctxt, f: @ast::expr, args: [option::t<@ast::expr>],
+fn trans_bind(cx: @block_ctxt, f: @ast::expr, args: [option<@ast::expr>],
               id: ast::node_id, dest: dest) -> @block_ctxt {
     let f_res = trans_callee(cx, f);
-    ret trans_bind_1(cx, ty::expr_ty(bcx_tcx(cx), f), f_res, args,
+    ret trans_bind_1(cx, expr_ty(cx, f), f_res, args,
                      ty::node_id_to_type(bcx_tcx(cx), id), dest);
 }
 
 fn trans_bind_1(cx: @block_ctxt, outgoing_fty: ty::t,
                 f_res: lval_maybe_callee,
-                args: [option::t<@ast::expr>], pair_ty: ty::t,
+                args: [option<@ast::expr>], pair_ty: ty::t,
                 dest: dest) -> @block_ctxt {
     let bound: [@ast::expr] = [];
-    for argopt: option::t<@ast::expr> in args {
+    for argopt: option<@ast::expr> in args {
         alt argopt { none { } some(e) { bound += [e]; } }
     }
     let bcx = f_res.bcx;
@@ -617,15 +565,15 @@ fn trans_bind_1(cx: @block_ctxt, outgoing_fty: ty::t,
     };
 
     // Actually construct the closure
-    let {llbox, cbox_ty, bcx} = store_environment(
+    let {llbox, cdata_ty, bcx} = store_environment(
         bcx, vec::map(lltydescs, {|d| {desc: d, dicts: none}}),
-        env_vals + vec::map(bound, {|x| env_expr(x)}),
+        env_vals + vec::map(bound, {|x| env_expr(x, expr_ty(bcx, x))}),
         ty::ck_box);
 
     // Make thunk
-    let llthunk =
-        trans_bind_thunk(cx.fcx.lcx, pair_ty, outgoing_fty_real, args,
-                         cbox_ty, *param_bounds, target_res);
+    let llthunk = trans_bind_thunk(
+        cx.fcx.ccx, cx.fcx.path, pair_ty, outgoing_fty_real, args,
+        cdata_ty, *param_bounds, target_res);
 
     // Fill the function pair
     fill_fn_pair(bcx, get_dest_addr(dest), llthunk.val, llbox);
@@ -688,16 +636,20 @@ fn make_opaque_cbox_take_glue(
 
     // Hard case, a deep copy:
     let ccx = bcx_ccx(bcx);
-    let llopaquecboxty = T_opaque_cbox_ptr(ccx);
+    let tcx = bcx_tcx(bcx);
+    let llopaquecboxty = T_opaque_box_ptr(ccx);
     let cbox_in = Load(bcx, cboxptr);
     make_null_test(bcx, cbox_in) {|bcx|
         // Load the size from the type descr found in the cbox
         let cbox_in = PointerCast(bcx, cbox_in, llopaquecboxty);
-        let tydescptr = GEPi(bcx, cbox_in, [0, abi::cbox_elt_tydesc]);
+        let tydescptr = GEPi(bcx, cbox_in, [0, abi::box_field_tydesc]);
         let tydesc = Load(bcx, tydescptr);
         let tydesc = PointerCast(bcx, tydesc, T_ptr(ccx.tydesc_type));
         let sz = Load(bcx, GEPi(bcx, tydesc, [0, abi::tydesc_field_size]));
 
+        // Adjust sz to account for the rust_opaque_box header fields
+        let sz = Add(bcx, sz, base::llsize_of(ccx, T_box_header(ccx)));
+
         // Allocate memory, update original ptr, and copy existing data
         let malloc = ccx.upcalls.shared_malloc;
         let cbox_out = Call(bcx, malloc, [sz, tydesc]);
@@ -705,9 +657,14 @@ fn make_opaque_cbox_take_glue(
         let {bcx, val: _} = call_memmove(bcx, cbox_out, cbox_in, sz);
         Store(bcx, cbox_out, cboxptr);
 
+        // Take the (deeply cloned) type descriptor
+        let tydesc_out = GEPi(bcx, cbox_out, [0, abi::box_field_tydesc]);
+        let bcx = take_ty(bcx, tydesc_out, mk_tydesc_ty(tcx, ty::ck_uniq));
+
         // Take the data in the tuple
         let ti = none;
-        call_tydesc_glue_full(bcx, cbox_out, tydesc,
+        let cdata_out = GEPi(bcx, cbox_out, [0, abi::box_field_body]);
+        call_tydesc_glue_full(bcx, cdata_out, tydesc,
                               abi::tydesc_field_take_glue, ti);
         bcx
     }
@@ -747,27 +704,21 @@ fn make_opaque_cbox_free_glue(
         // Load the type descr found in the cbox
         let lltydescty = T_ptr(ccx.tydesc_type);
         let cbox = PointerCast(bcx, cbox, T_opaque_cbox_ptr(ccx));
-        let tydescptr = GEPi(bcx, cbox, [0, abi::cbox_elt_tydesc]);
+        let tydescptr = GEPi(bcx, cbox, [0, abi::box_field_tydesc]);
         let tydesc = Load(bcx, tydescptr);
         let tydesc = PointerCast(bcx, tydesc, lltydescty);
 
-        // Null out the type descr in the cbox.  This is subtle:
-        // we will be freeing the data in the cbox, and we may need the
-        // information in the type descr to guide the GEP_tup_like process
-        // etc if generic types are involved.  So we null it out at first
-        // then free it manually below.
-        Store(bcx, C_null(lltydescty), tydescptr);
-
         // Drop the tuple data then free the descriptor
         let ti = none;
-        call_tydesc_glue_full(bcx, cbox, tydesc,
+        let cdata = GEPi(bcx, cbox, [0, abi::box_field_body]);
+        call_tydesc_glue_full(bcx, cdata, tydesc,
                               abi::tydesc_field_drop_glue, ti);
 
         // Free the ty descr (if necc) and the box itself
         alt ck {
           ty::ck_block { fail "Impossible"; }
           ty::ck_box {
-            trans_free_if_not_gc(bcx, cbox)
+            trans_free(bcx, cbox)
           }
           ty::ck_uniq {
             let bcx = free_ty(bcx, tydesc, mk_tydesc_ty(tcx, ck));
@@ -778,14 +729,16 @@ fn make_opaque_cbox_free_glue(
 }
 
 // pth is cx.path
-fn trans_bind_thunk(cx: @local_ctxt,
+fn trans_bind_thunk(ccx: @crate_ctxt,
+                    path: path,
                     incoming_fty: ty::t,
                     outgoing_fty: ty::t,
-                    args: [option::t<@ast::expr>],
-                    cbox_ty: ty::t,
+                    args: [option<@ast::expr>],
+                    cdata_ty: ty::t,
                     param_bounds: [ty::param_bounds],
-                    target_fn: option::t<ValueRef>)
+                    target_fn: option<ValueRef>)
     -> {val: ValueRef, ty: TypeRef} {
+
     // If we supported constraints on record fields, we could make the
     // constraints for this function:
     /*
@@ -793,10 +746,16 @@ fn trans_bind_thunk(cx: @local_ctxt,
       type_has_static_size(ccx, incoming_fty) ->
     */
     // but since we don't, we have to do the checks at the beginning.
-    let ccx = cx.ccx;
-    let tcx = ccx_tcx(ccx);
+    let tcx = ccx.tcx;
     check type_has_static_size(ccx, incoming_fty);
 
+    #debug["trans_bind_thunk[incoming_fty=%s,outgoing_fty=%s,\
+            cdata_ty=%s,param_bounds=%?]",
+           ty_to_str(tcx, incoming_fty),
+           ty_to_str(tcx, outgoing_fty),
+           ty_to_str(tcx, cdata_ty),
+           param_bounds];
+
     // Here we're not necessarily constructing a thunk in the sense of
     // "function with no arguments".  The result of compiling 'bind f(foo,
     // bar, baz)' would be a thunk that, when called, applies f to those
@@ -819,14 +778,14 @@ fn trans_bind_thunk(cx: @local_ctxt,
     // construct and return that thunk.
 
     // Give the thunk a name, type, and value.
-    let s: str = mangle_internal_name_by_path_and_seq(ccx, cx.path, "thunk");
-    let llthunk_ty: TypeRef = get_pair_fn_ty(type_of(ccx, incoming_fty));
-    let llthunk: ValueRef = decl_internal_cdecl_fn(ccx.llmod, s, llthunk_ty);
+    let s = mangle_internal_name_by_path_and_seq(ccx, path, "thunk");
+    let llthunk_ty = get_pair_fn_ty(type_of(ccx, incoming_fty));
+    let llthunk = decl_internal_cdecl_fn(ccx.llmod, s, llthunk_ty);
 
     // Create a new function context and block context for the thunk, and hold
     // onto a pointer to the first block in the function for later use.
-    let fcx = new_fn_ctxt(cx, llthunk);
-    let bcx = new_top_block_ctxt(fcx);
+    let fcx = new_fn_ctxt(ccx, path, llthunk, none);
+    let bcx = new_top_block_ctxt(fcx, none);
     let lltop = bcx.llbb;
     // Since we might need to construct derived tydescs that depend on
     // our bound tydescs, we need to load tydescs out of the environment
@@ -835,15 +794,12 @@ fn trans_bind_thunk(cx: @local_ctxt,
     let l_bcx = new_raw_block_ctxt(fcx, fcx.llloadenv);
 
     // The 'llenv' that will arrive in the thunk we're creating is an
-    // environment that will contain the values of its arguments and a pointer
-    // to the original function.  So, let's create one of those:
-
-    // The llenv pointer needs to be the correct size.  That size is
-    // 'cbox_ty', which was determined by trans_bind.
-    let cboxptr_ty = ty::mk_ptr(tcx, {ty:cbox_ty, mut:ast::imm});
-    check type_has_static_size(ccx, cboxptr_ty);
-    let llclosure_ptr_ty = type_of(ccx, cboxptr_ty);
-    let llclosure = PointerCast(l_bcx, fcx.llenv, llclosure_ptr_ty);
+    // environment that will contain the values of its arguments and a
+    // pointer to the original function.  This environment is always
+    // stored like an opaque box (see big comment at the header of the
+    // file), so we load the body body, which contains the type descr
+    // and cached data.
+    let llcdata = base::opaque_box_body(l_bcx, cdata_ty, fcx.llenv);
 
     // "target", in this context, means the function that's having some of its
     // arguments bound and that will be called inside the thunk we're
@@ -856,10 +812,10 @@ fn trans_bind_thunk(cx: @local_ctxt,
       }
       none {
         // Silly check
-        check type_is_tup_like(bcx, cbox_ty);
+        check type_is_tup_like(bcx, cdata_ty);
         let {bcx: cx, val: pair} =
-            GEP_tup_like(bcx, cbox_ty, llclosure,
-                         [0, abi::cbox_elt_bindings, 0]);
+            GEP_tup_like(bcx, cdata_ty, llcdata,
+                         [0, abi::closure_body_bindings, 0]);
         let lltargetenv =
             Load(cx, GEPi(cx, pair, [0, abi::fn_field_box]));
         let lltargetfn = Load
@@ -874,15 +830,14 @@ fn trans_bind_thunk(cx: @local_ctxt,
 
     // Get f's return type, which will also be the return type of the entire
     // bind expression.
-    let outgoing_ret_ty = ty::ty_fn_ret(cx.ccx.tcx, outgoing_fty);
+    let outgoing_ret_ty = ty::ty_fn_ret(ccx.tcx, outgoing_fty);
 
     // Get the types of the arguments to f.
-    let outgoing_args = ty::ty_fn_args(cx.ccx.tcx, outgoing_fty);
+    let outgoing_args = ty::ty_fn_args(ccx.tcx, outgoing_fty);
 
     // The 'llretptr' that will arrive in the thunk we're creating also needs
     // to be the correct type.  Cast it to f's return type, if necessary.
     let llretptr = fcx.llretptr;
-    let ccx = cx.ccx;
     if ty::type_contains_params(ccx.tcx, outgoing_ret_ty) {
         check non_ty_var(ccx, outgoing_ret_ty);
         let llretty = type_of_inner(ccx, outgoing_ret_ty);
@@ -893,10 +848,10 @@ fn trans_bind_thunk(cx: @local_ctxt,
     let llargs: [ValueRef] = [llretptr, lltargetenv];
 
     // Copy in the type parameters.
-    check type_is_tup_like(l_bcx, cbox_ty);
+    check type_is_tup_like(l_bcx, cdata_ty);
     let {bcx: l_bcx, val: param_record} =
-        GEP_tup_like(l_bcx, cbox_ty, llclosure,
-                     [0, abi::cbox_elt_ty_params]);
+        GEP_tup_like(l_bcx, cdata_ty, llcdata,
+                     [0, abi::closure_body_ty_params]);
     let off = 0;
     for param in param_bounds {
         let dsc = Load(l_bcx, GEPi(l_bcx, param_record, [0, off])),
@@ -925,8 +880,8 @@ fn trans_bind_thunk(cx: @local_ctxt,
     let b: int = starting_idx;
     let outgoing_arg_index: uint = 0u;
     let llout_arg_tys: [TypeRef] =
-        type_of_explicit_args(cx.ccx, outgoing_args);
-    for arg: option::t<@ast::expr> in args {
+        type_of_explicit_args(ccx, outgoing_args);
+    for arg: option<@ast::expr> in args {
         let out_arg = outgoing_args[outgoing_arg_index];
         let llout_arg_ty = llout_arg_tys[outgoing_arg_index];
         alt arg {
@@ -934,22 +889,29 @@ fn trans_bind_thunk(cx: @local_ctxt,
           // closure.
           some(e) {
             // Silly check
-            check type_is_tup_like(bcx, cbox_ty);
+            check type_is_tup_like(bcx, cdata_ty);
             let bound_arg =
-                GEP_tup_like(bcx, cbox_ty, llclosure,
-                             [0, abi::cbox_elt_bindings, b]);
+                GEP_tup_like(bcx, cdata_ty, llcdata,
+                             [0, abi::closure_body_bindings, b]);
             bcx = bound_arg.bcx;
             let val = bound_arg.val;
-            if out_arg.mode == ast::by_val { val = Load(bcx, val); }
-            if out_arg.mode == ast::by_copy {
+
+            alt ty::resolved_mode(tcx, out_arg.mode) {
+              ast::by_val {
+                val = Load(bcx, val);
+              }
+              ast::by_copy {
                 let {bcx: cx, val: alloc} = alloc_ty(bcx, out_arg.ty);
                 bcx = memmove_ty(cx, alloc, val, out_arg.ty);
                 bcx = take_ty(bcx, alloc, out_arg.ty);
                 val = alloc;
+              }
+              ast::by_ref | ast::by_mut_ref | ast::by_move { }
             }
+
             // If the type is parameterized, then we need to cast the
             // type we actually have to the parameterized out type.
-            if ty::type_contains_params(cx.ccx.tcx, out_arg.ty) {
+            if ty::type_contains_params(ccx.tcx, out_arg.ty) {
                 val = PointerCast(bcx, val, llout_arg_ty);
             }
             llargs += [val];
@@ -959,7 +921,7 @@ fn trans_bind_thunk(cx: @local_ctxt,
           // Arg will be provided when the thunk is invoked.
           none {
             let arg: ValueRef = llvm::LLVMGetParam(llthunk, a as c_uint);
-            if ty::type_contains_params(cx.ccx.tcx, out_arg.ty) {
+            if ty::type_contains_params(ccx.tcx, out_arg.ty) {
                 arg = PointerCast(bcx, arg, llout_arg_ty);
             }
             llargs += [arg];
@@ -973,8 +935,6 @@ fn trans_bind_thunk(cx: @local_ctxt,
     // This is necessary because the type of the function that we have
     // in the closure does not know how many type descriptors the function
     // needs to take.
-    let ccx = bcx_ccx(bcx);
-
     let lltargetty =
         type_of_fn_from_ty(ccx, outgoing_fty, param_bounds);
     lltargetfn = PointerCast(bcx, lltargetfn, T_ptr(lltargetty));
index 38b10d26b555ae7c7f06c5f2fc1c8c45d8ec366b..4f8a6402da375e5cc93768f4e033f5b4e20d6c3b 100644 (file)
 import syntax::codemap::span;
 import lib::llvm::{llvm, target_data, type_names, associate_type,
                    name_has_type};
-import lib::llvm::llvm::{ModuleRef, ValueRef, TypeRef, BasicBlockRef};
+import lib::llvm::{ModuleRef, ValueRef, TypeRef, BasicBlockRef, BuilderRef};
 import lib::llvm::{True, False, Bool};
-import metadata::{csearch};
+import metadata::csearch;
+import ast_map::path;
 
 // FIXME: These should probably be pulled in here too.
 import base::{type_of_fn, drop_ty};
@@ -43,10 +44,10 @@ enum tydesc_kind {
      tydesc: ValueRef,
      size: ValueRef,
      align: ValueRef,
-     mutable take_glue: option::t<ValueRef>,
-     mutable drop_glue: option::t<ValueRef>,
-     mutable free_glue: option::t<ValueRef>,
-     mutable cmp_glue: option::t<ValueRef>,
+     mutable take_glue: option<ValueRef>,
+     mutable drop_glue: option<ValueRef>,
+     mutable free_glue: option<ValueRef>,
+     mutable cmp_glue: option<ValueRef>,
      ty_params: [uint]};
 
 /*
@@ -72,7 +73,7 @@ enum tydesc_kind {
      mutable n_real_glues: uint,
      fn_times: @mutable [{ident: str, time: int}]};
 
-resource BuilderRef_res(B: llvm::BuilderRef) { llvm::LLVMDisposeBuilder(B); }
+resource BuilderRef_res(B: BuilderRef) { llvm::LLVMDisposeBuilder(B); }
 
 // Crate context.  Every crate we compile has one of these.
 type crate_ctxt =
@@ -90,7 +91,7 @@ enum tydesc_kind {
      ast_map: ast_map::map,
      exp_map: resolve::exp_map,
      item_symbols: hashmap<ast::node_id, str>,
-     mutable main_fn: option::t<ValueRef>,
+     mutable main_fn: option<ValueRef>,
      link_meta: link::link_meta,
      enum_sizes: hashmap<ty::t, uint>,
      discrims: hashmap<ast::def_id, ValueRef>,
@@ -98,6 +99,7 @@ enum tydesc_kind {
      consts: hashmap<ast::node_id, ValueRef>,
      tydescs: hashmap<ty::t, @tydesc_info>,
      dicts: hashmap<dict_id, ValueRef>,
+     monomorphized: hashmap<mono_id, ValueRef>,
      module_data: hashmap<str, ValueRef>,
      lltypes: hashmap<ty::t, TypeRef>,
      names: namegen,
@@ -120,90 +122,67 @@ enum tydesc_kind {
      opaque_vec_type: TypeRef,
      builder: BuilderRef_res,
      shape_cx: shape::ctxt,
-     gc_cx: gc::ctxt,
      crate_map: ValueRef,
-     dbg_cx: option::t<@debuginfo::debug_ctxt>};
-
-type local_ctxt =
-    {path: [str],
-     module_path: [str],
-     ccx: @crate_ctxt};
+     dbg_cx: option<@debuginfo::debug_ctxt>,
+     mutable do_not_commit_warning_issued: bool};
 
 // Types used for llself.
 type val_self_pair = {v: ValueRef, t: ty::t};
 
 enum local_val { local_mem(ValueRef), local_imm(ValueRef), }
 
-type fn_ty_param = {desc: ValueRef, dicts: option::t<[ValueRef]>};
+type fn_ty_param = {desc: ValueRef, dicts: option<[ValueRef]>};
 
 // Function context.  Every LLVM function we create will have one of
 // these.
-type fn_ctxt =
+type fn_ctxt = {
     // The ValueRef returned from a call to llvm::LLVMAddFunction; the
     // address of the first instruction in the sequence of
     // instructions for this function that will go in the .text
     // section of the executable we're generating.
+    llfn: ValueRef,
 
-    // The three implicit arguments that arrive in the function we're
-    // creating.  For instance, foo(int, int) is really foo(ret*,
-    // task*, env*, int, int).  These are also available via
-    // llvm::LLVMGetParam(llfn, uint) where uint = 1, 2, 0
-    // respectively, but we unpack them into these fields for
-    // convenience.
-
-    // Points to the current task.
-
-    // Points to the current environment (bindings of variables to
-    // values), if this is a regular function
-
-    // Points to where the return value of this function should end
-    // up.
+    // The two implicit arguments that arrive in the function we're creating.
+    // For instance, foo(int, int) is really foo(ret*, env*, int, int).
+    llenv: ValueRef,
+    llretptr: ValueRef,
 
-    // The next three elements: "hoisted basic blocks" containing
+    // These elements: "hoisted basic blocks" containing
     // administrative activities that have to happen in only one place in
     // the function, due to LLVM's quirks.
-
     // A block for all the function's static allocas, so that LLVM
     // will coalesce them into a single alloca call.
-
+    mutable llstaticallocas: BasicBlockRef,
     // A block containing code that copies incoming arguments to space
     // already allocated by code in one of the llallocas blocks.
     // (LLVM requires that arguments be copied to local allocas before
     // allowing most any operation to be performed on them.)
-
-    // The first block containing derived tydescs received from the
-    // runtime.  See description of derived_tydescs, below.
-
-    // The last block of the llderivedtydescs group.
-
+    mutable llloadenv: BasicBlockRef,
+    // The first and last block containing derived tydescs received from the
+    // runtime. See description of derived_tydescs, below.
+    mutable llderivedtydescs_first: BasicBlockRef,
+    mutable llderivedtydescs: BasicBlockRef,
     // A block for all of the dynamically sized allocas.  This must be
     // after llderivedtydescs, because these sometimes depend on
     // information computed from derived tydescs.
-
+    mutable lldynamicallocas: BasicBlockRef,
+    mutable llreturn: BasicBlockRef,
     // The token used to clear the dynamic allocas at the end of this frame.
-
+    mutable llobstacktoken: option<ValueRef>,
     // The 'self' value currently in use in this function, if there
     // is one.
-
-    // If this function is actually a iter, a block containing the
-    // code called whenever the iter calls 'put'.
-
-    // The next four items: hash tables mapping from AST def_ids to
-    // LLVM-stuff-in-the-frame.
+    mutable llself: option<val_self_pair>,
 
     // Maps arguments to allocas created for them in llallocas.
-
+    llargs: hashmap<ast::node_id, local_val>,
     // Maps the def_ids for local variables to the allocas created for
     // them in llallocas.
+    lllocals: hashmap<ast::node_id, local_val>,
+    // Same as above, but for closure upvars
+    llupvars: hashmap<ast::node_id, ValueRef>,
 
-    // The same as above, but for variables accessed via the frame
-    // pointer we pass into an iter, for access to the static
-    // environment of the iter-calling frame.
-
-    // For convenience, a vector of the incoming tydescs for each of
-    // this functions type parameters, fetched via llvm::LLVMGetParam.
-    // For example, for a function foo::<A, B, C>(), lltydescs contains
-    // the ValueRefs for the tydescs for A, B, and C.
+    // A vector of incoming type descriptors and their associated iface dicts.
+    mutable lltyparams: [fn_ty_param],
 
     // Derived tydescs are tydescs created at runtime, for types that
     // involve type parameters inside type constructors.  For example,
@@ -214,33 +193,31 @@ enum local_val { local_mem(ValueRef), local_imm(ValueRef), }
     // when information about both "[T]" and "T" are available.  When
     // such a tydesc is created, we cache it in the derived_tydescs
     // table for the next time that such a tydesc is needed.
+    derived_tydescs: hashmap<ty::t, derived_tydesc_info>,
 
     // The node_id of the function, or -1 if it doesn't correspond to
     // a user-defined function.
+    id: ast::node_id,
+
+    // If this function is being monomorphized, this contains the type
+    // substitutions used.
+    param_substs: option<[ty::t]>,
 
-    // The source span where this function comes from, for error
-    // reporting.
-
-    // This function's enclosing local context.
-    {llfn: ValueRef,
-     llenv: ValueRef,
-     llretptr: ValueRef,
-     mutable llstaticallocas: BasicBlockRef,
-     mutable llloadenv: BasicBlockRef,
-     mutable llderivedtydescs_first: BasicBlockRef,
-     mutable llderivedtydescs: BasicBlockRef,
-     mutable lldynamicallocas: BasicBlockRef,
-     mutable llreturn: BasicBlockRef,
-     mutable llobstacktoken: option::t<ValueRef>,
-     mutable llself: option::t<val_self_pair>,
-     llargs: hashmap<ast::node_id, local_val>,
-     lllocals: hashmap<ast::node_id, local_val>,
-     llupvars: hashmap<ast::node_id, ValueRef>,
-     mutable lltyparams: [fn_ty_param],
-     derived_tydescs: hashmap<ty::t, derived_tydesc_info>,
-     id: ast::node_id,
-     ret_style: ast::ret_style,
-     lcx: @local_ctxt};
+    // The source span and nesting context where this function comes from, for
+    // error reporting and symbol generation.
+    span: option<span>,
+    path: path,
+
+    // This function's enclosing crate context.
+    ccx: @crate_ctxt
+};
+
+fn warn_not_to_commit(ccx: @crate_ctxt, msg: str) {
+    if !ccx.do_not_commit_warning_issued {
+        ccx.do_not_commit_warning_issued = true;
+        ccx.sess.warn(msg + " -- do not commit like this!");
+    }
+}
 
 enum cleanup {
     clean(fn@(@block_ctxt) -> @block_ctxt),
@@ -277,7 +254,7 @@ fn add_clean_temp_mem(cx: @block_ctxt, val: ValueRef, ty: ty::t) {
 fn add_clean_free(cx: @block_ctxt, ptr: ValueRef, shared: bool) {
     let scope_cx = find_scope_cx(cx);
     let free_fn = if shared { bind base::trans_shared_free(_, ptr) }
-                  else { bind base::trans_free_if_not_gc(_, ptr) };
+                  else { bind base::trans_free(_, ptr) };
     scope_cx.cleanups += [clean_temp(ptr, free_fn)];
     scope_cx.lpad_dirty = true;
 }
@@ -323,7 +300,8 @@ fn get_res_dtor(ccx: @crate_ctxt, did: ast::def_id, inner_t: ty::t)
     let nil_res = ty::mk_nil(ccx.tcx);
     // FIXME: Silly check -- mk_nil should have a postcondition
     check non_ty_var(ccx, nil_res);
-    let f_t = type_of_fn(ccx, [{mode: ast::by_ref, ty: inner_t}],
+    let fn_mode = ast::expl(ast::by_ref);
+    let f_t = type_of_fn(ccx, [{mode: fn_mode, ty: inner_t}],
                          nil_res, *param_bounds);
     ret base::get_extern_const(ccx.externs, ccx.llmod,
                                 csearch::get_symbol(ccx.sess.cstore,
@@ -331,22 +309,14 @@ fn get_res_dtor(ccx: @crate_ctxt, did: ast::def_id, inner_t: ty::t)
 }
 
 enum block_kind {
-
-
-    // A scope block is a basic block created by translating a block { ... }
-    // in the source language.  Since these blocks create variable scope, any
-    // variables created in them that are still live at the end of the block
-    // must be dropped and cleaned up when the block ends.
+    // A scope at the end of which temporary values created inside of it are
+    // cleaned up. May correspond to an actual block in the language, but also
+    // to an implicit scope, for example, calls introduce an implicit scope in
+    // which the arguments are evaluated and cleaned up.
     SCOPE_BLOCK,
-
-
     // A basic block created from the body of a loop.  Contains pointers to
-    // which block to jump to in the case of "continue" or "break", with the
-    // "continue" block optional, because "while" and "do while" don't support
-    // "continue" (TODO: is this intentional?)
-    LOOP_SCOPE_BLOCK(option::t<@block_ctxt>, @block_ctxt),
-
-
+    // which block to jump to in the case of "continue" or "break".
+    LOOP_SCOPE_BLOCK(option<@block_ctxt>, @block_ctxt),
     // A non-scope block is a basic block created as a translation artifact
     // from translating code that expresses conditional logic rather than by
     // explicit { ... } block structure in the source language.  It's called a
@@ -381,20 +351,17 @@ enum block_kind {
      kind: block_kind,
      mutable cleanups: [cleanup],
      mutable lpad_dirty: bool,
-     mutable lpad: option::t<BasicBlockRef>,
+     mutable lpad: option<BasicBlockRef>,
+     block_span: option<span>,
      fcx: @fn_ctxt};
 
-// FIXME: we should be able to use option::t<@block_parent> here but
+// FIXME: we should be able to use option<@block_parent> here but
 // the infinite-enum check in rustboot gets upset.
 enum block_parent { parent_none, parent_some(@block_ctxt), }
 
 type result = {bcx: @block_ctxt, val: ValueRef};
 type result_t = {bcx: @block_ctxt, val: ValueRef, ty: ty::t};
 
-fn extend_path(cx: @local_ctxt, name: str) -> @local_ctxt {
-    ret @{path: cx.path + [name] with *cx};
-}
-
 fn rslt(bcx: @block_ctxt, val: ValueRef) -> result {
     {bcx: bcx, val: val}
 }
@@ -420,19 +387,20 @@ fn find_scope_cx(cx: @block_ctxt) -> @block_ctxt {
     if cx.kind != NON_SCOPE_BLOCK { ret cx; }
     alt cx.parent {
       parent_some(b) { ret find_scope_cx(b); }
+      _ {
+          bcx_tcx(cx).sess.bug("find_scope_cx: empty scope");
+      }
     }
 }
 
 // Accessors
 // TODO: When we have overloading, simplify these names!
 
-pure fn bcx_tcx(bcx: @block_ctxt) -> ty::ctxt { ret bcx.fcx.lcx.ccx.tcx; }
-pure fn bcx_ccx(bcx: @block_ctxt) -> @crate_ctxt { ret bcx.fcx.lcx.ccx; }
-pure fn bcx_lcx(bcx: @block_ctxt) -> @local_ctxt { ret bcx.fcx.lcx; }
+pure fn bcx_tcx(bcx: @block_ctxt) -> ty::ctxt { ret bcx.fcx.ccx.tcx; }
+pure fn bcx_ccx(bcx: @block_ctxt) -> @crate_ctxt { ret bcx.fcx.ccx; }
 pure fn bcx_fcx(bcx: @block_ctxt) -> @fn_ctxt { ret bcx.fcx; }
-pure fn fcx_ccx(fcx: @fn_ctxt) -> @crate_ctxt { ret fcx.lcx.ccx; }
-pure fn fcx_tcx(fcx: @fn_ctxt) -> ty::ctxt { ret fcx.lcx.ccx.tcx; }
-pure fn lcx_ccx(lcx: @local_ctxt) -> @crate_ctxt { ret lcx.ccx; }
+pure fn fcx_ccx(fcx: @fn_ctxt) -> @crate_ctxt { ret fcx.ccx; }
+pure fn fcx_tcx(fcx: @fn_ctxt) -> ty::ctxt { ret fcx.ccx.tcx; }
 pure fn ccx_tcx(ccx: @crate_ctxt) -> ty::ctxt { ret ccx.tcx; }
 
 // LLVM type constructors.
@@ -655,8 +623,42 @@ fn T_opaque_vec(targ_cfg: @session::config) -> TypeRef {
     ret T_vec2(targ_cfg, T_i8());
 }
 
+// Let T be the content of a box @T.  tuplify_box_ty(t) returns the
+// representation of @T as a tuple (i.e., the ty::t version of what T_box()
+// returns).
+fn tuplify_box_ty(tcx: ty::ctxt, t: ty::t) -> ty::t {
+    ret tuplify_cbox_ty(tcx, t, ty::mk_type(tcx));
+}
+
+// As tuplify_box_ty(), but allows the caller to specify what type of type
+// descr is embedded in the box (ty::type vs ty::send_type).  This is useful
+// for unique closure boxes, hence the name "cbox_ty" (closure box type).
+fn tuplify_cbox_ty(tcx: ty::ctxt, t: ty::t, tydesc_t: ty::t) -> ty::t {
+    let ptr = ty::mk_ptr(tcx, {ty: ty::mk_nil(tcx), mut: ast::imm});
+    ret ty::mk_tup(tcx, [ty::mk_uint(tcx), tydesc_t,
+                         ptr, ptr,
+                         t]);
+}
+
+fn T_box_header_fields(cx: @crate_ctxt) -> [TypeRef] {
+    let ptr = T_ptr(T_i8());
+    ret [cx.int_type, T_ptr(cx.tydesc_type), ptr, ptr];
+}
+
+fn T_box_header(cx: @crate_ctxt) -> TypeRef {
+    ret T_struct(T_box_header_fields(cx));
+}
+
 fn T_box(cx: @crate_ctxt, t: TypeRef) -> TypeRef {
-    ret T_struct([cx.int_type, t]);
+    ret T_struct(T_box_header_fields(cx) + [t]);
+}
+
+fn T_opaque_box(cx: @crate_ctxt) -> TypeRef {
+    ret T_box(cx, T_i8());
+}
+
+fn T_opaque_box_ptr(cx: @crate_ctxt) -> TypeRef {
+    ret T_ptr(T_opaque_box(cx));
 }
 
 fn T_port(cx: @crate_ctxt, _t: TypeRef) -> TypeRef {
@@ -684,15 +686,9 @@ fn T_typaram(tn: type_names) -> TypeRef {
 fn T_typaram_ptr(tn: type_names) -> TypeRef { ret T_ptr(T_typaram(tn)); }
 
 fn T_opaque_cbox_ptr(cx: @crate_ctxt) -> TypeRef {
-    let s = "*cbox";
-    alt name_has_type(cx.tn, s) { some(t) { ret t; } _ {} }
-    let t = T_ptr(T_struct([cx.int_type,
-                            T_ptr(cx.tydesc_type),
-                            T_i8() /* represents closed over tydescs
-                            and data go here; see trans_closure.rs*/
-                           ]));
-    associate_type(cx.tn, s, t);
-    ret t;
+    // closures look like boxes (even when they are fn~ or fn&)
+    // see trans_closure.rs
+    ret T_opaque_box_ptr(cx);
 }
 
 fn T_enum_variant(cx: @crate_ctxt) -> TypeRef {
@@ -791,7 +787,7 @@ fn C_cstr(cx: @crate_ctxt, s: str) -> ValueRef {
                     {|buf| llvm::LLVMAddGlobal(cx.llmod, val_ty(sc), buf) });
     llvm::LLVMSetInitializer(g, sc);
     llvm::LLVMSetGlobalConstant(g, True);
-    llvm::LLVMSetLinkage(g, lib::llvm::LLVMInternalLinkage as llvm::Linkage);
+    lib::llvm::SetLinkage(g, lib::llvm::InternalLinkage);
     ret g;
 }
 
@@ -838,8 +834,7 @@ fn C_shape(ccx: @crate_ctxt, bytes: [u8]) -> ValueRef {
     });
     llvm::LLVMSetInitializer(llglobal, llshape);
     llvm::LLVMSetGlobalConstant(llglobal, True);
-    llvm::LLVMSetLinkage(llglobal,
-                         lib::llvm::LLVMInternalLinkage as llvm::Linkage);
+    lib::llvm::SetLinkage(llglobal, lib::llvm::InternalLinkage);
     ret llvm::LLVMConstPointerCast(llglobal, T_ptr(T_i8()));
 }
 
@@ -896,13 +891,23 @@ fn hash_dict_id(&&dp: dict_id) -> uint {
     h
 }
 
+// Used to identify cached monomorphized functions
+// FIXME[mono] don't count different boxes as different types
+type mono_id = @{def: ast::def_id, substs: [ty::t], dicts: [dict_id]};
+fn hash_mono_id(&&mi: mono_id) -> uint {
+    let h = syntax::ast_util::hash_def_id(mi.def);
+    for ty in mi.substs { h = (h << 2u) + ty; }
+    for dict in mi.dicts { h = (h << 2u) + hash_dict_id(dict); }
+    h
+}
+
 fn umax(cx: @block_ctxt, a: ValueRef, b: ValueRef) -> ValueRef {
-    let cond = build::ICmp(cx, lib::llvm::LLVMIntULT, a, b);
+    let cond = build::ICmp(cx, lib::llvm::IntULT, a, b);
     ret build::Select(cx, cond, b, a);
 }
 
 fn umin(cx: @block_ctxt, a: ValueRef, b: ValueRef) -> ValueRef {
-    let cond = build::ICmp(cx, lib::llvm::LLVMIntULT, a, b);
+    let cond = build::ICmp(cx, lib::llvm::IntULT, a, b);
     ret build::Select(cx, cond, a, b);
 }
 
@@ -912,6 +917,30 @@ fn align_to(cx: @block_ctxt, off: ValueRef, align: ValueRef) -> ValueRef {
     ret build::And(cx, bumped, build::Not(cx, mask));
 }
 
+fn path_str(p: path) -> str {
+    let r = "", first = true;
+    for e in p {
+        alt e { ast_map::path_name(s) | ast_map::path_mod(s) {
+          if first { first = false; }
+          else { r += "::"; }
+          r += s;
+        } }
+    }
+    r
+}
+
+fn node_id_type(bcx: @block_ctxt, id: ast::node_id) -> ty::t {
+    let tcx = bcx_tcx(bcx);
+    let t = ty::node_id_to_type(tcx, id);
+    alt bcx.fcx.param_substs {
+      some(s) { ty::substitute_type_params(tcx, s, t) }
+      _ { t }
+    }
+}
+fn expr_ty(bcx: @block_ctxt, ex: @ast::expr) -> ty::t {
+    node_id_type(bcx, ex.id)
+}
+
 //
 // Local Variables:
 // mode: rust
index bbac0172f9695716835fcb4a0dd890b9d8924f35..18ee215b2dcdb3bf36db1bc4417beb81a02cda54 100644 (file)
@@ -2,12 +2,15 @@
 import base::*;
 import common::*;
 import build::*;
+import driver::session::session;
 import option::{some, none};
 import syntax::{ast, ast_util};
 import metadata::csearch;
 import back::{link, abi};
 import lib::llvm::llvm;
-import llvm::{ValueRef, TypeRef, LLVMGetParam};
+import lib::llvm::{ValueRef, TypeRef};
+import lib::llvm::llvm::LLVMGetParam;
+import ast_map::{path, path_mod, path_name};
 
 // Translation functionality related to impls and ifaces
 //
 // annotates notes with information about the methods and dicts that
 // are referenced (ccx.method_map and ccx.dict_map).
 
-fn trans_impl(cx: @local_ctxt, name: ast::ident, methods: [@ast::method],
-              id: ast::node_id, tps: [ast::ty_param]) {
-    let sub_cx = extend_path(cx, name);
+fn trans_impl(ccx: @crate_ctxt, path: path, name: ast::ident,
+              methods: [@ast::method], id: ast::node_id,
+              tps: [ast::ty_param]) {
+    let sub_path = path + [path_name(name)];
     for m in methods {
-        alt cx.ccx.item_ids.find(m.id) {
+        alt ccx.item_ids.find(m.id) {
           some(llfn) {
-            trans_fn(extend_path(sub_cx, m.ident), m.span, m.decl, m.body,
-                     llfn, impl_self(ty::node_id_to_monotype(cx.ccx.tcx, id)),
-                     tps + m.tps, m.id);
+            trans_fn(ccx, sub_path + [path_name(m.ident)], m.decl, m.body,
+                     llfn, impl_self(ty::node_id_to_type(ccx.tcx, id)),
+                     tps + m.tps, none, m.id);
+          }
+          _ {
+            ccx.tcx.sess.bug("Unbound id in trans_impl");
           }
         }
     }
@@ -55,8 +62,9 @@ fn trans_impl(cx: @local_ctxt, name: ast::ident, methods: [@ast::method],
 
 fn trans_self_arg(bcx: @block_ctxt, base: @ast::expr) -> result {
     let tz = [], tr = [];
-    let basety = ty::expr_ty(bcx_tcx(bcx), base);
-    let {bcx, val} = trans_arg_expr(bcx, {mode: ast::by_ref, ty: basety},
+    let basety = expr_ty(bcx, base);
+    let m_by_ref = ast::expl(ast::by_ref);
+    let {bcx, val} = trans_arg_expr(bcx, {mode: m_by_ref, ty: basety},
                                     T_ptr(type_of_or_i8(bcx, basety)), tz,
                                     tr, base);
     rslt(bcx, PointerCast(bcx, val, T_opaque_cbox_ptr(bcx_ccx(bcx))))
@@ -140,14 +148,17 @@ fn trans_iface_callee(bcx: @block_ctxt, callee_id: ast::node_id,
     -> lval_maybe_callee {
     let tcx = bcx_tcx(bcx);
     let {bcx, val} = trans_temp_expr(bcx, base);
-    let box_body = GEPi(bcx, val, [0, abi::box_rc_field_body]);
+    let box_body = GEPi(bcx, val, [0, abi::box_field_body]);
     let dict = Load(bcx, PointerCast(bcx, GEPi(bcx, box_body, [0, 1]),
                                      T_ptr(T_ptr(T_dict()))));
     // FIXME[impl] I doubt this is alignment-safe
     let self = PointerCast(bcx, GEPi(bcx, box_body, [0, 2]),
                            T_opaque_cbox_ptr(bcx_ccx(bcx)));
-    let iface_id = alt ty::struct(tcx, ty::expr_ty(tcx, base)) {
+    let iface_id = alt ty::struct(tcx, expr_ty(bcx, base)) {
         ty::ty_iface(did, _) { did }
+        // precondition
+        _ { bcx_tcx(bcx).sess.span_bug(base.span, "base has non-iface type \
+             in trans_iface_callee"); }
     };
     trans_vtable_callee(bcx, self, dict, callee_id, iface_id, n_method)
 }
@@ -172,21 +183,20 @@ fn trans_vtable(ccx: @crate_ctxt, id: ast::node_id, name: str,
     ccx.item_symbols.insert(id, name);
 }
 
-fn trans_wrapper(ccx: @crate_ctxt, pt: [ast::ident], llfty: TypeRef,
+fn trans_wrapper(ccx: @crate_ctxt, pt: path, llfty: TypeRef,
                  fill: fn(ValueRef, @block_ctxt) -> @block_ctxt)
     -> ValueRef {
-    let lcx = @{path: pt, module_path: [], ccx: ccx};
     let name = link::mangle_internal_name_by_path(ccx, pt);
     let llfn = decl_internal_cdecl_fn(ccx.llmod, name, llfty);
-    let fcx = new_fn_ctxt(lcx, llfn);
-    let bcx = new_top_block_ctxt(fcx), lltop = bcx.llbb;
+    let fcx = new_fn_ctxt(ccx, [], llfn, none);
+    let bcx = new_top_block_ctxt(fcx, none), lltop = bcx.llbb;
     let bcx = fill(llfn, bcx);
     build_return(bcx);
     finish_fn(fcx, lltop);
     ret llfn;
 }
 
-fn trans_impl_wrapper(ccx: @crate_ctxt, pt: [ast::ident],
+fn trans_impl_wrapper(ccx: @crate_ctxt, pt: path,
                       extra_tps: [ty::param_bounds], real_fn: ValueRef)
     -> ValueRef {
     let {inputs: real_args, output: real_ret} =
@@ -230,31 +240,38 @@ fn trans_impl_wrapper(ccx: @crate_ctxt, pt: [ast::ident],
     })
 }
 
-fn trans_impl_vtable(ccx: @crate_ctxt, pt: [ast::ident],
+fn trans_impl_vtable(ccx: @crate_ctxt, pt: path,
                      iface_id: ast::def_id, ms: [@ast::method],
                      tps: [ast::ty_param], it: @ast::item) {
-    let new_pt = pt + [it.ident + int::str(it.id), "wrap"];
+    let new_pt = pt + [path_name(it.ident), path_name(int::str(it.id)),
+                       path_name("wrap")];
     let extra_tps = vec::map(tps, {|p| param_bounds(ccx, p)});
     let ptrs = vec::map(*ty::iface_methods(ccx.tcx, iface_id), {|im|
         alt vec::find(ms, {|m| m.ident == im.ident}) {
           some(m) {
             let target = ccx.item_ids.get(m.id);
-            trans_impl_wrapper(ccx, new_pt + [m.ident], extra_tps, target)
+            trans_impl_wrapper(ccx, new_pt + [path_name(m.ident)], extra_tps,
+                               target)
+          }
+          _ {
+            ccx.tcx.sess.span_bug(it.span, "No matching method \
+               in trans_impl_vtable");
           }
         }
     });
-    let s = link::mangle_internal_name_by_path(ccx, new_pt + ["!vtable"]);
+    let s = link::mangle_internal_name_by_path(
+        ccx, new_pt + [path_name("!vtable")]);
     trans_vtable(ccx, it.id, s, ptrs);
 }
 
-fn trans_iface_wrapper(ccx: @crate_ctxt, pt: [ast::ident], m: ty::method,
+fn trans_iface_wrapper(ccx: @crate_ctxt, pt: path, m: ty::method,
                        n: uint) -> ValueRef {
     let {llty: llfty, _} = wrapper_fn_ty(ccx, T_ptr(T_i8()), m);
     trans_wrapper(ccx, pt, llfty, {|llfn, bcx|
         let self = Load(bcx, PointerCast(bcx,
                                          LLVMGetParam(llfn, 2u as c_uint),
                                          T_ptr(T_opaque_iface_ptr(ccx))));
-        let boxed = GEPi(bcx, self, [0, abi::box_rc_field_body]);
+        let boxed = GEPi(bcx, self, [0, abi::box_field_body]);
         let dict = Load(bcx, PointerCast(bcx, GEPi(bcx, boxed, [0, 1]),
                                          T_ptr(T_ptr(T_dict()))));
         let vtable = PointerCast(bcx, Load(bcx, GEPi(bcx, dict, [0, 0])),
@@ -275,15 +292,16 @@ fn trans_iface_wrapper(ccx: @crate_ctxt, pt: [ast::ident], m: ty::method,
     })
 }
 
-fn trans_iface_vtable(ccx: @crate_ctxt, pt: [ast::ident], it: @ast::item) {
-    let new_pt = pt + [it.ident + int::str(it.id)];
+fn trans_iface_vtable(ccx: @crate_ctxt, pt: path, it: @ast::item) {
+    let new_pt = pt + [path_name(it.ident), path_name(int::str(it.id))];
     let i_did = ast_util::local_def(it.id), i = 0u;
     let ptrs = vec::map(*ty::iface_methods(ccx.tcx, i_did), {|m|
-        let w = trans_iface_wrapper(ccx, new_pt + [m.ident], m, i);
+        let w = trans_iface_wrapper(ccx, new_pt + [path_name(m.ident)], m, i);
         i += 1u;
         w
     });
-    let s = link::mangle_internal_name_by_path(ccx, new_pt + ["!vtable"]);
+    let s = link::mangle_internal_name_by_path(
+        ccx, new_pt + [path_name("!vtable")]);
     trans_vtable(ccx, it.id, s, ptrs);
 }
 
@@ -340,6 +358,10 @@ fn dict_id(tcx: ty::ctxt, origin: typeck::dict_origin) -> dict_id {
                     d_params += [dict_param_dict(dict_id(tcx, origs[orig]))];
                     orig += 1u;
                   }
+                  _ {
+                    tcx.sess.bug("Someone forgot to document an invariant in \
+                      dict_id");
+                  }
                 }
             }
         }
@@ -348,6 +370,9 @@ fn dict_id(tcx: ty::ctxt, origin: typeck::dict_origin) -> dict_id {
       typeck::dict_iface(did) {
         @{def: did, params: []}
       }
+      _ {
+        tcx.sess.bug("Unexpected dict_param in dict_id");
+      }
     }
 }
 
@@ -366,8 +391,7 @@ fn get_static_dict(bcx: @block_ctxt, origin: typeck::dict_origin)
     });
     llvm::LLVMSetGlobalConstant(gvar, lib::llvm::True);
     llvm::LLVMSetInitializer(gvar, ptrs);
-    llvm::LLVMSetLinkage(gvar,
-                         lib::llvm::LLVMInternalLinkage as llvm::Linkage);
+    lib::llvm::SetLinkage(gvar, lib::llvm::InternalLinkage);
     let cast = llvm::LLVMConstPointerCast(gvar, T_ptr(T_dict()));
     ccx.dicts.insert(id, cast);
     cast
@@ -410,13 +434,16 @@ fn get_vtable(ccx: @crate_ctxt, did: ast::def_id) -> ValueRef {
       typeck::dict_iface(did) {
         {bcx: bcx, ptrs: [get_vtable(ccx, did)]}
       }
+      _ {
+        bcx_tcx(bcx).sess.bug("Unexpected dict_param in get_dict_ptrs");
+      }
     }
 }
 
 fn trans_cast(bcx: @block_ctxt, val: @ast::expr, id: ast::node_id, dest: dest)
     -> @block_ctxt {
     let ccx = bcx_ccx(bcx), tcx = ccx.tcx;
-    let val_ty = ty::expr_ty(tcx, val);
+    let val_ty = expr_ty(bcx, val);
     let {bcx, val: dict} = get_dict(bcx, ccx.dict_map.get(id)[0]);
     let body_ty = ty::mk_tup(tcx, [ty::mk_type(tcx), ty::mk_type(tcx),
                                    val_ty]);
index 91af1ffb8454fde80238e0ed47adbd2a084eb195..a5da4c2cc75c51a3882d1eef3006bc97071c3923 100644 (file)
@@ -1,11 +1,12 @@
 import vec;
 import option::none;
 import syntax::ast;
-import lib::llvm::llvm::{ValueRef, TypeRef};
+import driver::session::session;
+import lib::llvm::{ValueRef, TypeRef};
 import back::abi;
 import base::{call_memmove, trans_shared_malloc, type_of_or_i8,
                INIT, copy_val, load_if_immediate, get_tydesc,
-               node_id_type, new_sub_block_ctxt, do_spill_noroot,
+               new_sub_block_ctxt, do_spill_noroot,
                dest};
 import shape::{llsize_of, size_of};
 import build::*;
@@ -105,7 +106,7 @@ fn trans_vec(bcx: @block_ctxt, args: [@ast::expr], id: ast::node_id,
         }
         ret bcx;
     }
-    let vec_ty = node_id_type(bcx_ccx(bcx), id);
+    let vec_ty = node_id_type(bcx, id);
     let {bcx: bcx,
          val: vptr,
          llunitsz: llunitsz,
@@ -149,19 +150,27 @@ fn trans_append(cx: @block_ctxt, vec_ty: ty::t, lhsptr: ValueRef,
     let ccx = bcx_ccx(cx);
     let unit_ty = ty::sequence_element_type(bcx_tcx(cx), vec_ty);
     let dynamic = ty::type_has_dynamic_size(bcx_tcx(cx), unit_ty);
-    let (lhsptr, rhs) = !dynamic ? (lhsptr, rhs) :
-        (PointerCast(cx, lhsptr, T_ptr(T_ptr(ccx.opaque_vec_type))),
-         PointerCast(cx, rhs, T_ptr(ccx.opaque_vec_type)));
+    let (lhsptr, rhs) =
+        if !dynamic {
+            (lhsptr, rhs)
+        } else {
+            (PointerCast(cx, lhsptr, T_ptr(T_ptr(ccx.opaque_vec_type))),
+             PointerCast(cx, rhs, T_ptr(ccx.opaque_vec_type)))
+        };
     let strings = alt ty::struct(bcx_tcx(cx), vec_ty) {
       ty::ty_str { true }
       ty::ty_vec(_) { false }
+      _ {
+          // precondition?
+          bcx_tcx(cx).sess.bug("Bad argument type in trans_append");
+      }
     };
 
     let {bcx: bcx, val: unit_sz} = size_of(cx, unit_ty);
     let llunitty = type_of_or_i8(cx, unit_ty);
 
     let lhs = Load(bcx, lhsptr);
-    let self_append = ICmp(bcx, lib::llvm::LLVMIntEQ, lhs, rhs);
+    let self_append = ICmp(bcx, lib::llvm::IntEQ, lhs, rhs);
     let lfill = get_fill(bcx, lhs);
     let rfill = get_fill(bcx, rhs);
     let new_fill = Add(bcx, lfill, rfill);
@@ -187,7 +196,11 @@ fn trans_append(cx: @block_ctxt, vec_ty: ty::t, lhsptr: ValueRef,
                              copy_val(bcx, INIT, write_ptr,
                                       load_if_immediate(bcx, addr, unit_ty),
                                       unit_ty);
-                         let incr = dynamic ? unit_sz : C_int(ccx, 1);
+                         let incr = if dynamic {
+                                        unit_sz
+                                    } else {
+                                        C_int(ccx, 1)
+                                    };
                          Store(bcx, InBoundsGEP(bcx, write_ptr, [incr]),
                                write_ptr_ptr);
                          ret bcx;
@@ -222,7 +235,7 @@ fn trans_add(bcx: @block_ctxt, vec_ty: ty::t, lhs: ValueRef,
     let ccx = bcx_ccx(bcx);
     let strings = alt ty::struct(bcx_tcx(bcx), vec_ty) {
       ty::ty_str { true }
-      ty::ty_vec(_) { false }
+      _ { false }
     };
     let unit_ty = ty::sequence_element_type(bcx_tcx(bcx), vec_ty);
     let llunitty = type_of_or_i8(bcx, unit_ty);
@@ -244,8 +257,11 @@ fn trans_add(bcx: @block_ctxt, vec_ty: ty::t, lhs: ValueRef,
         let bcx = copy_val(bcx, INIT, write_ptr,
                            load_if_immediate(bcx, addr, unit_ty), unit_ty);
         let incr =
-            ty::type_has_dynamic_size(bcx_tcx(bcx), unit_ty) ?
-            llunitsz : C_int(ccx, 1);
+            if ty::type_has_dynamic_size(bcx_tcx(bcx), unit_ty) {
+                llunitsz
+            } else {
+                C_int(ccx, 1)
+            };
         Store(bcx, InBoundsGEP(bcx, write_ptr, [incr]),
               write_ptr_ptr);
         ret bcx;
@@ -279,7 +295,7 @@ fn iter_vec_raw(bcx: @block_ctxt, vptr: ValueRef, vec_ty: ty::t,
     Br(bcx, header_cx.llbb);
     let data_ptr = Phi(header_cx, val_ty(data_ptr), [data_ptr], [bcx.llbb]);
     let not_yet_at_end =
-        ICmp(header_cx, lib::llvm::LLVMIntULT, data_ptr, data_end_ptr);
+        ICmp(header_cx, lib::llvm::IntULT, data_ptr, data_end_ptr);
     let body_cx = new_sub_block_ctxt(header_cx, "iter_vec_loop_body");
     let next_cx = new_sub_block_ctxt(header_cx, "iter_vec_next");
     CondBr(header_cx, not_yet_at_end, body_cx.llbb, next_cx.llbb);
index 8cff8794081f6b9d2a52adb5271671a550da9e2e..ffcebe60ddbd92e1a65ade81d72fea2d4fbf29dc 100644 (file)
@@ -1,11 +1,10 @@
 import syntax::ast;
-import lib::llvm::llvm::ValueRef;
+import lib::llvm::ValueRef;
 import common::*;
 import build::*;
 import base::{
     trans_shared_malloc,
     type_of_inner,
-    node_id_type,
     INIT,
     trans_shared_free,
     drop_ty,
@@ -24,7 +23,7 @@
 
 fn trans_uniq(bcx: @block_ctxt, contents: @ast::expr,
               node_id: ast::node_id, dest: dest) -> @block_ctxt {
-    let uniq_ty = node_id_type(bcx_ccx(bcx), node_id);
+    let uniq_ty = node_id_type(bcx, node_id);
     check type_is_unique_box(bcx, uniq_ty);
     let {bcx, val: llptr} = alloc_uniq(bcx, uniq_ty);
     add_clean_free(bcx, llptr, true);
@@ -74,6 +73,7 @@ fn content_ty(bcx: @block_ctxt, t: ty::t)
 
     alt ty::struct(bcx_tcx(bcx), t) {
       ty::ty_uniq({ty: ct, _}) { ct }
+      _ { std::util::unreachable(); }
     }
 }
 
index e1b0ccccad1b8658f1519d09a3a8c2a8ad0a9f49..222006f3fa84f6d846eff89f3983844bed311ff7 100644 (file)
@@ -300,7 +300,7 @@ fn add_node(ccx: crate_ctxt, i: node_id, a: ts_ann) {
     ccx.node_anns[i] = a;
 }
 
-fn get_ts_ann(ccx: crate_ctxt, i: node_id) -> option::t<ts_ann> {
+fn get_ts_ann(ccx: crate_ctxt, i: node_id) -> option<ts_ann> {
     if i as uint < vec::len(*ccx.node_anns) {
         ret some::<ts_ann>(ccx.node_anns[i]);
     } else { ret none::<ts_ann>; }
@@ -515,7 +515,7 @@ fn node_id_to_def_strict(cx: ty::ctxt, id: node_id) -> def {
     }
 }
 
-fn node_id_to_def(ccx: crate_ctxt, id: node_id) -> option::t<def> {
+fn node_id_to_def(ccx: crate_ctxt, id: node_id) -> option<def> {
     ret ccx.tcx.def_map.find(id);
 }
 
@@ -582,12 +582,14 @@ fn expr_to_constr_arg(tcx: ty::ctxt, e: @expr) -> @constr_arg_use {
             ret @respan(p.span,
                         carg_ident({ident: p.node.idents[0], node: id.node}));
           }
-          some(_) {
-            tcx.sess.bug("exprs_to_constr_args: non-local variable " +
-                             "as pred arg");
+          some(what) {
+              tcx.sess.span_bug(e.span,
+                 #fmt("exprs_to_constr_args: non-local variable %? \
+                                     as pred arg", what));
           }
           none {
-            tcx.sess.bug("exprs_to_constr_args: NONE " + "as pred arg");
+              tcx.sess.span_bug(e.span,
+                 "exprs_to_constr_args: unbound id as pred arg");
 
           }
         }
@@ -689,7 +691,7 @@ fn pred_args_matches(pattern: [constr_arg_general_<inst>], desc: pred_args) ->
 }
 
 fn find_instance_(pattern: [constr_arg_general_<inst>], descs: [pred_args]) ->
-   option::t<uint> {
+   option<uint> {
     for d: pred_args in descs {
         if pred_args_matches(pattern, d) { ret some(d.node.bit_num); }
     }
@@ -723,7 +725,7 @@ fn find_instances(_fcx: fn_ctxt, subst: subst, c: constraint) ->
     rslt
 }
 
-fn find_in_subst(id: node_id, s: subst) -> option::t<inst> {
+fn find_in_subst(id: node_id, s: subst) -> option<inst> {
     for p: {from: inst, to: inst} in s {
         if id == p.from.node { ret some(p.to); }
     }
@@ -803,11 +805,11 @@ fn local_node_id_to_def_id_strict(fcx: fn_ctxt, sp: span, i: node_id) ->
     }
 }
 
-fn local_node_id_to_def(fcx: fn_ctxt, i: node_id) -> option::t<def> {
+fn local_node_id_to_def(fcx: fn_ctxt, i: node_id) -> option<def> {
     fcx.ccx.tcx.def_map.find(i)
 }
 
-fn local_node_id_to_def_id(fcx: fn_ctxt, i: node_id) -> option::t<def_id> {
+fn local_node_id_to_def_id(fcx: fn_ctxt, i: node_id) -> option<def_id> {
     alt local_node_id_to_def(fcx, i) {
       some(def_local(id, _)) | some(def_arg(id, _)) | some(def_binding(id)) |
       some(def_upvar(id, _, _)) {
@@ -818,7 +820,7 @@ fn local_node_id_to_def_id(fcx: fn_ctxt, i: node_id) -> option::t<def_id> {
 }
 
 fn local_node_id_to_local_def_id(fcx: fn_ctxt, i: node_id) ->
-   option::t<node_id> {
+   option<node_id> {
     alt local_node_id_to_def_id(fcx, i) {
       some(did) { some(did.node) }
       _ { none }
@@ -1051,14 +1053,12 @@ fn ast_constr_to_sp_constr(tcx: ty::ctxt, args: [arg], c: @constr) ->
     ret respan(c.span, tconstr);
 }
 
-type binding = {lhs: [inst], rhs: option::t<initializer>};
+type binding = {lhs: [inst], rhs: option<initializer>};
 
 fn local_to_bindings(tcx: ty::ctxt, loc: @local) -> binding {
     let lhs = [];
-    pat_bindings(pat_util::normalize_pat(tcx, loc.node.pat)) {|p|
-            let ident = alt p.node
-               { pat_ident(name, _) { path_to_ident(name) } };
-        lhs += [{ident: ident, node: p.id}];
+    pat_bindings(pat_util::normalize_pat(tcx, loc.node.pat)) {|p_id, _s, name|
+        lhs += [{ident: path_to_ident(name), node: p_id}];
     };
     {lhs: lhs, rhs: loc.node.init}
 }
@@ -1070,7 +1070,7 @@ fn locals_to_bindings(tcx: ty::ctxt,
     ret rslt;
 }
 
-fn callee_modes(fcx: fn_ctxt, callee: node_id) -> [ty::mode] {
+fn callee_modes(fcx: fn_ctxt, callee: node_id) -> [mode] {
     let ty =
         ty::type_autoderef(fcx.ccx.tcx,
                            ty::node_id_to_type(fcx.ccx.tcx, callee));
@@ -1089,10 +1089,12 @@ fn callee_modes(fcx: fn_ctxt, callee: node_id) -> [ty::mode] {
 }
 
 fn callee_arg_init_ops(fcx: fn_ctxt, callee: node_id) -> [init_op] {
-    fn mode_to_op(m: ty::mode) -> init_op {
-        alt m { by_move { init_move } _ { init_assign } }
+    vec::map(callee_modes(fcx, callee)) {|m|
+        alt ty::resolved_mode(fcx.ccx.tcx, m) {
+          by_move { init_move }
+          by_copy | by_ref | by_val | by_mut_ref { init_assign }
+        }
     }
-    vec::map(callee_modes(fcx, callee), mode_to_op)
 }
 
 fn anon_bindings(ops: [init_op], es: [@expr]) -> [binding] {
index 30a93e4db368d3993dd8c77947f5a185fe41bc8f..1abc9903d5c1ecd9df5d6123e9a1e94c375cca04 100644 (file)
 type ctxt = {cs: @mutable [sp_constr], tcx: ty::ctxt};
 
 fn collect_local(loc: @local, cx: ctxt, v: visit::vt<ctxt>) {
-    pat_bindings(pat_util::normalize_pat(cx.tcx, loc.node.pat)) {|p|
-            let ident = alt p.node
-                 { pat_ident(id, _) { path_to_ident(id) } };
-        log(debug, "collect_local: pushing " + ident);;
-        *cx.cs += [respan(loc.span, ninit(p.id, ident))];
+    pat_bindings(pat_util::normalize_pat(cx.tcx, loc.node.pat))
+     {|p_id, _s, id|
+       *cx.cs += [respan(loc.span, ninit(p_id, path_to_ident(id)))];
     };
     visit::visit_local(loc, cx, v);
 }
@@ -26,10 +24,6 @@ fn collect_pred(e: @expr, cx: ctxt, v: visit::vt<ctxt>) {
       expr_check(_, ch) { *cx.cs += [expr_to_constr(cx.tcx, ch)]; }
       expr_if_check(ex, _, _) { *cx.cs += [expr_to_constr(cx.tcx, ex)]; }
 
-
-
-
-
       // If it's a call, generate appropriate instances of the
       // call's constraints.
       expr_call(operator, operands, _) {
index 99bb750f3b768372e8950c304de29d5ad98f5f11..0ca3a6ee2947c80c59de0db99de67a28cf2688a3 100644 (file)
@@ -18,7 +18,6 @@
 import syntax::codemap::span;
 import driver::session::session;
 
-
 fn find_pre_post_mod(_m: _mod) -> _mod {
     #debug("implement find_pre_post_mod!");
     fail;
@@ -42,22 +41,7 @@ fn find_pre_post_method(ccx: crate_ctxt, m: @method) {
 fn find_pre_post_item(ccx: crate_ctxt, i: item) {
     alt i.node {
       item_const(_, e) {
-        // make a fake fcx
-        let v: @mutable [node_id] = @mutable [];
-        let fake_fcx =
-            {
-             // just bogus
-             enclosing:
-                 {constrs: new_def_hash::<constraint>(),
-                  num_constraints: 0u,
-                  cf: return_val,
-                  i_return: ninit(0, ""),
-                  i_diverge: ninit(0, ""),
-                  used_vars: v},
-             id: 0,
-             name: "",
-             ccx: ccx};
-        find_pre_post_expr(fake_fcx, e);
+          // do nothing -- item_consts don't refer to local vars
       }
       item_fn(_, _, body) {
         assert (ccx.fm.contains_key(i.id));
@@ -76,6 +60,9 @@ fn find_pre_post_item(ccx: crate_ctxt, i: item) {
              ccx: ccx};
         find_pre_post_fn(fcx, body);
       }
+      item_class(_,_,_,_) {
+          fail "find_pre_post_item: implement item_class";
+      }
       item_impl(_, _, _, ms) { for m in ms { find_pre_post_method(ccx, m); } }
     }
 }
@@ -106,14 +93,12 @@ fn find_pre_post_loop(fcx: fn_ctxt, l: @local, index: @expr, body: blk,
                       id: node_id) {
     find_pre_post_expr(fcx, index);
     find_pre_post_block(fcx, body);
-    pat_bindings(normalize_pat(fcx.ccx.tcx, l.node.pat)) {|p|
-        let ident = alt p.node
-             { pat_ident(id, _) { path_to_ident(id) } };
-        let v_init = ninit(p.id, ident);
+    pat_bindings(normalize_pat(fcx.ccx.tcx, l.node.pat)) {|p_id, _s, n|
+        let v_init = ninit(p_id, path_to_ident(n));
         relax_precond_block(fcx, bit_num(fcx, v_init) as node_id, body);
         // Hack: for-loop index variables are frequently ignored,
         // so we pretend they're used
-        use_var(fcx, p.id);
+        use_var(fcx, p_id);
     };
 
     let loop_precond =
@@ -128,7 +113,7 @@ fn find_pre_post_loop(fcx: fn_ctxt, l: @local, index: @expr, body: blk,
 // annotation for an if-expression with consequent conseq
 // and alternative maybe_alt
 fn join_then_else(fcx: fn_ctxt, antec: @expr, conseq: blk,
-                  maybe_alt: option::t<@expr>, id: node_id, chck: if_ty) {
+                  maybe_alt: option<@expr>, id: node_id, chck: if_ty) {
     find_pre_post_expr(fcx, antec);
     find_pre_post_block(fcx, conseq);
     alt maybe_alt {
@@ -289,14 +274,13 @@ fn handle_var_def(fcx: fn_ctxt, rslt: pre_and_post, def: def, name: ident) {
     }
 }
 
-fn forget_args_moved_in(fcx: fn_ctxt, parent: @expr, modes: [ty::mode],
+fn forget_args_moved_in(fcx: fn_ctxt, parent: @expr, modes: [mode],
                         operands: [@expr]) {
-    let i = 0u;
-    for mode: ty::mode in modes {
-        if mode == by_move {
-            forget_in_postcond(fcx, parent.id, operands[i].id);
+    vec::iteri(modes) {|i,mode|
+        alt ty::resolved_mode(fcx.ccx.tcx, mode) {
+          by_move { forget_in_postcond(fcx, parent.id, operands[i].id); }
+          by_ref | by_val | by_mut_ref | by_copy { }
         }
-        i += 1u;
     }
 }
 
@@ -415,7 +399,6 @@ fn find_pre_post_expr(fcx: fn_ctxt, e: @expr) {
       expr_if(antec, conseq, maybe_alt) {
         join_then_else(fcx, antec, conseq, maybe_alt, e.id, plain_if);
       }
-      expr_ternary(_, _, _) { find_pre_post_expr(fcx, ternary_to_if(e)); }
       expr_binary(bop, l, r) {
         if lazy_binop(bop) {
             find_pre_post_expr(fcx, l);
@@ -540,7 +523,7 @@ fn combine_pp(antec: pre_and_post, fcx: fn_ctxt, &&pp: pre_and_post,
         let cmodes = callee_modes(fcx, operator.id);
         let modes = [];
         let i = 0;
-        for expr_opt: option::t<@expr> in maybe_args {
+        for expr_opt: option<@expr> in maybe_args {
             alt expr_opt {
               none {/* no-op */ }
               some(expr) { modes += [cmodes[i]]; args += [expr]; }
@@ -572,8 +555,8 @@ fn find_pre_post_stmt(fcx: fn_ctxt, s: stmt) {
                     /* LHS always becomes initialized,
                      whether or not this is a move */
                     find_pre_post_expr(fcx, an_init.expr);
-                    pat_bindings(alocal.node.pat) {|p|
-                        copy_pre_post(fcx.ccx, p.id, an_init.expr);
+                    pat_bindings(alocal.node.pat) {|p_id, _s, _n|
+                        copy_pre_post(fcx.ccx, p_id, an_init.expr);
                     };
                     /* Inherit ann from initializer, and add var being
                        initialized to the postcondition */
@@ -586,16 +569,12 @@ fn find_pre_post_stmt(fcx: fn_ctxt, s: stmt) {
                     }
 
                     pat_bindings(normalize_pat(fcx.ccx.tcx, alocal.node.pat))
-                        {|pat|
-                        /* FIXME: This won't be necessary when typestate
-                        works well enough for pat_bindings to return a
-                        refinement-typed thing. */
-                            let ident = alt pat.node
-                                     { pat_ident(n, _) { path_to_ident(n) } };
+                        {|p_id, _s, n|
+                        let ident = path_to_ident(n);
                         alt p {
                           some(p) {
                             copy_in_postcond(fcx, id,
-                                             {ident: ident, node: pat.id},
+                                             {ident: ident, node: p_id},
                                              {ident:
                                                   path_to_ident(p),
                                               node: an_init.expr.id},
@@ -603,7 +582,7 @@ fn find_pre_post_stmt(fcx: fn_ctxt, s: stmt) {
                           }
                           none { }
                         }
-                        gen(fcx, id, ninit(pat.id, ident));
+                        gen(fcx, id, ninit(p_id, ident));
                     };
 
                     if an_init.op == init_move && is_path(an_init.expr) {
@@ -618,22 +597,16 @@ fn find_pre_post_stmt(fcx: fn_ctxt, s: stmt) {
                     /* Include the LHSs too, since those aren't in the
                      postconds of the RHSs themselves */
                     pat_bindings(normalize_pat(fcx.ccx.tcx, alocal.node.pat))
-                        {|pat|
-                            // FIXME
-                            // Generalize this pattern? map_if_ident...
-                        alt pat.node {
-                          pat_ident(n, _) {
+                        {|pat_id, _s, n|
                             set_in_postcond(bit_num(fcx,
-                               ninit(pat.id, path_to_ident(n))), prev_pp);
-                          }
-                        }
-                    };
+                               ninit(pat_id, path_to_ident(n))), prev_pp);
+                          };
                     copy_pre_post_(fcx.ccx, id, prev_pp.precondition,
                                    prev_pp.postcondition);
                   }
                   none {
-                    pat_bindings(alocal.node.pat) {|p|
-                        clear_pp(node_id_to_ts_ann(fcx.ccx, p.id).conditions);
+                      pat_bindings(alocal.node.pat) {|p_id, _s, _n|
+                        clear_pp(node_id_to_ts_ann(fcx.ccx, p_id).conditions);
                     };
                     clear_pp(node_id_to_ts_ann(fcx.ccx, id).conditions);
                   }
index 2a976d0469f998af9bdf88f9e54ace244c230126..f68c7ba7a105d5431527e0077f9ed7571ae109a1 100644 (file)
@@ -103,7 +103,7 @@ fn seq_states(fcx: fn_ctxt, pres: prestate, bindings: [binding]) ->
 }
 
 fn find_pre_post_state_sub(fcx: fn_ctxt, pres: prestate, e: @expr,
-                           parent: node_id, c: option::t<tsconstr>) -> bool {
+                           parent: node_id, c: option<tsconstr>) -> bool {
     let changed = find_pre_post_state_expr(fcx, pres, e);
 
     changed = set_prestate_ann(fcx.ccx, parent, pres) || changed;
@@ -215,6 +215,8 @@ fn find_pre_post_state_exprs(fcx: fn_ctxt, pres: prestate, id: node_id,
 
 fn find_pre_post_state_loop(fcx: fn_ctxt, pres: prestate, l: @local,
                             index: @expr, body: blk, id: node_id) -> bool {
+    // I'm confused about this -- how does the poststate for the body
+    // ever grow larger? It seems like it can't?
     let loop_pres = intersect_states(pres, block_poststate(fcx.ccx, body));
 
     let changed =
@@ -224,10 +226,9 @@ fn find_pre_post_state_loop(fcx: fn_ctxt, pres: prestate, l: @local,
     // Make sure the index vars are considered initialized
     // in the body
     let index_post = tritv_clone(expr_poststate(fcx.ccx, index));
-    pat_bindings(pat_util::normalize_pat(fcx.ccx.tcx, l.node.pat)) {|p|
-        let ident = alt p.node
-           { pat_ident(name, _) { path_to_ident(name) } };
-        set_in_poststate_ident(fcx, p.id, ident, index_post);
+    pat_bindings(pat_util::normalize_pat(fcx.ccx.tcx, l.node.pat))
+      {|p_id, _s, n|
+       set_in_poststate_ident(fcx, p_id, path_to_ident(n), index_post);
     };
 
     changed |= find_pre_post_state_block(fcx, index_post, body);
@@ -260,7 +261,7 @@ fn gen_if_local(fcx: fn_ctxt, p: poststate, e: @expr) -> bool {
 }
 
 fn join_then_else(fcx: fn_ctxt, antec: @expr, conseq: blk,
-                  maybe_alt: option::t<@expr>, id: node_id, chk: if_ty,
+                  maybe_alt: option<@expr>, id: node_id, chk: if_ty,
                   pres: prestate) -> bool {
     let changed =
         set_prestate_ann(fcx.ccx, id, pres) |
@@ -375,7 +376,7 @@ fn find_pre_post_state_expr(fcx: fn_ctxt, pres: prestate, e: @expr) -> bool {
         let callee_ops = callee_arg_init_ops(fcx, operator.id);
         let ops = [];
         let i = 0;
-        for a_opt: option::t<@expr> in maybe_args {
+        for a_opt: option<@expr> in maybe_args {
             alt a_opt {
               none {/* no-op */ }
               some(a) { ops += [callee_ops[i]]; args += [a]; }
@@ -466,9 +467,6 @@ fn find_pre_post_state_expr(fcx: fn_ctxt, pres: prestate, e: @expr) -> bool {
         ret join_then_else(fcx, antec, conseq, maybe_alt, e.id, plain_if,
                            pres);
       }
-      expr_ternary(_, _, _) {
-        ret find_pre_post_state_expr(fcx, pres, ternary_to_if(e));
-      }
       expr_binary(bop, l, r) {
         if lazy_binop(bop) {
             let changed = find_pre_post_state_expr(fcx, pres, l);
index 502510063dfd130286377ccd0729cf8a059ae378..0826eda4cf3848e0895fd13d49e92a569604847a 100644 (file)
 import syntax::util::interner;
 import util::ppaux::ty_to_str;
 import util::ppaux::ty_constr_to_str;
-import util::ppaux::mode_str;
 import syntax::print::pprust::*;
 
-export node_id_to_monotype;
 export node_id_to_type;
 export node_id_to_type_params;
-export node_id_to_ty_param_substs_opt_and_ty;
 export arg;
 export args_eq;
 export ast_constr_to_constr;
@@ -44,6 +41,7 @@
 export field;
 export field_idx;
 export get_field;
+export get_fields;
 export fm_general;
 export get_element_type;
 export idx_nil;
@@ -69,7 +67,6 @@
 export mk_mach_int;
 export mk_mach_uint;
 export mk_mach_float;
-export mk_native;
 export mk_nil;
 export mk_iface;
 export mk_res;
@@ -86,7 +83,6 @@
 export mk_opaque_closure_ptr;
 export mk_named;
 export gen_ty;
-export mode;
 export mt;
 export node_type_table;
 export pat_ty;
 export enum_variants;
 export iface_methods, store_iface_methods, impl_iface;
 export enum_variant_with_id;
-export ty_param_substs_opt_and_ty;
 export ty_param_bounds_and_ty;
 export ty_bool;
 export ty_bot;
 export ty_int;
 export ty_str;
 export ty_vec;
-export ty_native;
 export ty_nil;
 export ty_iface;
 export ty_res;
 export ty_rec;
 export ty_enum;
 export ty_tup;
-export ty_type;
 export ty_send_type;
 export ty_uint;
 export ty_uniq;
 export ty_named;
 export same_type;
 export ty_var_id;
-export ty_param_substs_opt_and_ty_to_monotype;
 export ty_fn_args;
 export type_constr;
 export type_contains_params;
 export type_allows_implicit_copy;
 export type_is_integral;
 export type_is_numeric;
-export type_is_native;
 export type_is_nil;
 export type_is_pod;
 export type_is_scalar;
 export type_structurally_contains_uniques;
 export type_autoderef;
 export type_param;
+export canon_mode;
+export resolved_mode;
+export arg_mode;
+export unify_mode;
+export set_default_mode;
 export unify;
 export variant_info;
 export walk_ty;
 export occurs_check_fails;
 export closure_kind;
-export ck_any;
 export ck_block;
 export ck_box;
 export ck_uniq;
 export param_bound, param_bounds, bound_copy, bound_send, bound_iface;
 export param_bounds_to_kind;
+export default_arg_mode_for_ty;
 
 // Data types
 
-type arg = {mode: mode, ty: t};
+// Note: after typeck, you should use resolved_mode() to convert this mode
+// into an rmode, which will take into account the results of mode inference.
+type arg = {mode: ast::mode, ty: t};
 
 type field = {ident: ast::ident, mt: mt};
 
       sess: session::session,
       def_map: resolve::def_map,
       node_types: node_type_table,
+      node_type_substs: hashmap<node_id, [t]>,
       items: ast_map::map,
       freevars: freevars::freevar_map,
       tcache: type_cache,
       short_names_cache: hashmap<t, @str>,
       needs_drop_cache: hashmap<t, bool>,
       kind_cache: hashmap<t, kind>,
-      ast_ty_to_ty_cache: hashmap<@ast::ty, option::t<t>>,
+      ast_ty_to_ty_cache: hashmap<@ast::ty, option<t>>,
       enum_var_cache: hashmap<def_id, @[variant_info]>,
       iface_method_cache: hashmap<def_id, @[method]>,
-      ty_param_bounds: hashmap<ast::node_id, param_bounds>};
+      ty_param_bounds: hashmap<ast::node_id, param_bounds>,
+      inferred_modes: hashmap<ast::node_id, ast::mode>};
 
 type ty_ctxt = ctxt;
 
 type t = uint;
 
 enum closure_kind {
-    ck_any,
     ck_block,
     ck_box,
     ck_uniq,
@@ -273,7 +272,6 @@ enum sty {
 
     ty_type, // type_desc*
     ty_send_type, // type_desc* that has been cloned into exchange heap
-    ty_native(def_id),
     ty_constr(t, [@type_constr]),
     ty_opaque_closure_ptr(closure_kind), // ptr to env for fn, fn@, fn~
     ty_named(t, @str),
@@ -369,12 +367,7 @@ fn param_bounds_to_kind(bounds: param_bounds) -> kind {
 
 type type_store = interner::interner<@raw_t>;
 
-// substs is a list of actuals that correspond to ty's
-// formal parameters
-type ty_param_substs_opt_and_ty = {substs: option::t<[ty::t]>, ty: ty::t};
-
-type node_type_table =
-    @smallintmap::smallintmap<ty::ty_param_substs_opt_and_ty>;
+type node_type_table = @smallintmap::smallintmap<t>;
 
 fn populate_type_store(cx: ctxt) {
     intern(cx, ty_nil);
@@ -415,8 +408,6 @@ fn new_ty_hash<V: copy>() -> map::hashmap<t, V> { map::new_uint_hash() }
 
 fn mk_ctxt(s: session::session, dm: resolve::def_map, amap: ast_map::map,
            freevars: freevars::freevar_map) -> ctxt {
-    let ntt: node_type_table =
-        @smallintmap::mk::<ty::ty_param_substs_opt_and_ty>();
     fn eq_raw_ty(&&a: @raw_t, &&b: @raw_t) -> bool {
         ret a.hash == b.hash && a.struct == b.struct;
     }
@@ -425,7 +416,8 @@ fn eq_raw_ty(&&a: @raw_t, &&b: @raw_t) -> bool {
         @{ts: ts,
           sess: s,
           def_map: dm,
-          node_types: ntt,
+          node_types: @smallintmap::mk(),
+          node_type_substs: map::new_int_hash(),
           items: amap,
           freevars: freevars,
           tcache: new_def_hash(),
@@ -437,7 +429,8 @@ fn eq_raw_ty(&&a: @raw_t, &&b: @raw_t) -> bool {
               map::mk_hashmap(ast_util::hash_ty, ast_util::eq_ty),
           enum_var_cache: new_def_hash(),
           iface_method_cache: new_def_hash(),
-          ty_param_bounds: map::new_int_hash()};
+          ty_param_bounds: map::new_int_hash(),
+          inferred_modes: map::new_int_hash()};
     populate_type_store(cx);
     ret cx;
 }
@@ -467,10 +460,7 @@ fn derive_flags_sig(cx: ctxt, &has_params: bool, &has_vars: bool,
     }
     alt st {
       ty_nil | ty_bot | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) |
-      ty_str | ty_send_type | ty_type | ty_native(_) |
-      ty_opaque_closure_ptr(_) {
-        /* no-op */
-      }
+      ty_str | ty_type | ty_send_type | ty_opaque_closure_ptr(_) {}
       ty_param(_, _) { has_params = true; }
       ty_var(_) { has_vars = true; }
       ty_enum(_, tys) | ty_iface(_, tys) {
@@ -616,8 +606,6 @@ fn mk_param(cx: ctxt, n: uint, k: def_id) -> t {
 
 fn mk_send_type(_cx: ctxt) -> t { ret idx_send_type; }
 
-fn mk_native(cx: ctxt, did: def_id) -> t { ret gen_ty(cx, ty_native(did)); }
-
 fn mk_opaque_closure_ptr(cx: ctxt, ck: closure_kind) -> t {
     ret gen_ty(cx, ty_opaque_closure_ptr(ck));
 }
@@ -638,7 +626,7 @@ fn mk_named(cx: ctxt, base: t, name: @str) -> t {
     interner::get(*cx.ts, typ).struct
 }
 
-// Returns struact(cx, typ) but replaces all occurences of platform
+// Returns struct(cx, typ) but replaces all occurences of platform
 // dependent primitive types with their machine type equivalent
 pure fn mach_struct(cx: ctxt, cfg: @session::config, typ: t) -> sty {
     alt interner::get(*cx.ts, typ).struct {
@@ -657,42 +645,47 @@ fn mk_named(cx: ctxt, base: t, name: @str) -> t {
     }
 }
 
-pure fn ty_name(cx: ctxt, typ: t) -> option::t<@str> {
+pure fn ty_name(cx: ctxt, typ: t) -> option<@str> {
     alt interner::get(*cx.ts, typ).struct {
       ty_named(_, n) { some(n) }
       _ { none }
     }
 }
 
-fn walk_ty(cx: ctxt, ty: t, walker: fn(t)) {
+fn default_arg_mode_for_ty(tcx: ty::ctxt, ty: ty::t) -> ast::rmode {
+    assert !ty::type_contains_vars(tcx, ty);
+    if ty::type_is_immediate(tcx, ty) { ast::by_val }
+    else { ast::by_ref }
+}
+
+fn walk_ty(cx: ctxt, ty: t, f: fn(t)) {
     alt struct(cx, ty) {
       ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
-      ty_str | ty_send_type | ty_type | ty_native(_) |
-      ty_opaque_closure_ptr(_) {
-        /* no-op */
-      }
-      ty_box(tm) | ty_vec(tm) | ty_ptr(tm) { walk_ty(cx, tm.ty, walker); }
+      ty_str | ty_send_type | ty_type |
+      ty_opaque_closure_ptr(_) | ty_var(_) | ty_param(_, _) {}
+      ty_box(tm) | ty_vec(tm) | ty_ptr(tm) { walk_ty(cx, tm.ty, f); }
       ty_enum(_, subtys) | ty_iface(_, subtys) {
-        for subty: t in subtys { walk_ty(cx, subty, walker); }
+        for subty: t in subtys { walk_ty(cx, subty, f); }
       }
       ty_rec(fields) {
-        for fl: field in fields { walk_ty(cx, fl.mt.ty, walker); }
+        for fl: field in fields { walk_ty(cx, fl.mt.ty, f); }
       }
-      ty_tup(ts) { for tt in ts { walk_ty(cx, tt, walker); } }
-      ty_fn(f) {
-        for a: arg in f.inputs { walk_ty(cx, a.ty, walker); }
-        walk_ty(cx, f.output, walker);
+      ty_tup(ts) { for tt in ts { walk_ty(cx, tt, f); } }
+      ty_fn(ft) {
+        for a: arg in ft.inputs { walk_ty(cx, a.ty, f); }
+        walk_ty(cx, ft.output, f);
       }
       ty_res(_, sub, tps) {
-        walk_ty(cx, sub, walker);
-        for tp: t in tps { walk_ty(cx, tp, walker); }
+        walk_ty(cx, sub, f);
+        for tp: t in tps { walk_ty(cx, tp, f); }
       }
-      ty_constr(sub, _) { walk_ty(cx, sub, walker); }
-      ty_var(_) {/* no-op */ }
-      ty_param(_, _) {/* no-op */ }
-      ty_uniq(tm) { walk_ty(cx, tm.ty, walker); }
+      ty_constr(sub, _) { walk_ty(cx, sub, f); }
+      ty_uniq(tm) { walk_ty(cx, tm.ty, f); }
+      // precondition?
+      ty_named(_,_) { cx.sess.bug("walk_ty: should not see a ty_named \
+                        here"); }
     }
-    walker(ty);
+    f(ty);
 }
 
 enum fold_mode {
@@ -703,19 +696,17 @@ enum fold_mode {
 
 fn fold_ty(cx: ctxt, fld: fold_mode, ty_0: t) -> t {
     let ty = ty_0;
-    // Fast paths.
 
+    // Fast paths.
     alt fld {
       fm_var(_) { if !type_contains_vars(cx, ty) { ret ty; } }
       fm_param(_) { if !type_contains_params(cx, ty) { ret ty; } }
       fm_general(_) {/* no fast path */ }
     }
+
     alt interner::get(*cx.ts, ty).struct {
       ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
-      ty_str | ty_send_type | ty_type | ty_native(_) |
-      ty_opaque_closure_ptr(_) {
-        /* no-op */
-      }
+      ty_str | ty_type | ty_send_type | ty_opaque_closure_ptr(_) {}
       ty_box(tm) {
         ty = mk_box(cx, {ty: fold_ty(cx, fld, tm.ty), mut: tm.mut});
       }
@@ -899,7 +890,7 @@ fn get_element_type(cx: ctxt, ty: t, i: uint) -> t {
 pure fn type_is_scalar(cx: ctxt, ty: t) -> bool {
     alt struct(cx, ty) {
       ty_nil | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) |
-      ty_send_type | ty_type | ty_native(_) | ty_ptr(_) { true }
+      ty_send_type | ty_type | ty_ptr(_) { true }
       _ { false }
     }
 }
@@ -907,7 +898,7 @@ fn get_element_type(cx: ctxt, ty: t, i: uint) -> t {
 // FIXME maybe inline this for speed?
 fn type_is_immediate(cx: ctxt, ty: t) -> bool {
     ret type_is_scalar(cx, ty) || type_is_boxed(cx, ty) ||
-        type_is_unique(cx, ty) || type_is_native(cx, ty);
+        type_is_unique(cx, ty);
 }
 
 fn type_needs_drop(cx: ctxt, ty: t) -> bool {
@@ -920,7 +911,7 @@ fn type_needs_drop(cx: ctxt, ty: t) -> bool {
     let result = alt struct(cx, ty) {
       // scalar types
       ty_nil | ty_bot | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) |
-      ty_type | ty_native(_) | ty_ptr(_) { false }
+      ty_type | ty_ptr(_) { false }
       ty_rec(flds) {
         for f in flds { if type_needs_drop(cx, f.mt.ty) { accum = true; } }
         accum
@@ -1003,8 +994,7 @@ fn type_kind(cx: ctxt, ty: t) -> kind {
     let result = alt struct(cx, ty) {
       // Scalar and unique types are sendable
       ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
-      ty_native(_) | ty_ptr(_) |
-      ty_send_type | ty_str { kind_sendable }
+      ty_ptr(_) | ty_send_type | ty_str { kind_sendable }
       ty_type { kind_copyable }
       ty_fn(f) { proto_kind(f.proto) }
       ty_opaque_closure_ptr(ck_block) { kind_noncopyable }
@@ -1046,18 +1036,13 @@ fn type_kind(cx: ctxt, ty: t) -> kind {
           param_bounds_to_kind(cx.ty_param_bounds.get(did.node))
       }
       ty_constr(t, _) { type_kind(cx, t) }
+      _ { cx.sess.bug("Bad type in type_kind"); }
     };
 
     cx.kind_cache.insert(ty, result);
     ret result;
 }
 
-// FIXME: should we just return true for native types in
-// type_is_scalar?
-fn type_is_native(cx: ctxt, ty: t) -> bool {
-    alt struct(cx, ty) { ty_native(_) { ret true; } _ { ret false; } }
-}
-
 fn type_structurally_contains(cx: ctxt, ty: t, test: fn(sty) -> bool) ->
    bool {
     let sty = struct(cx, ty);
@@ -1177,7 +1162,7 @@ fn type_is_pod(cx: ctxt, ty: t) -> bool {
     alt struct(cx, ty) {
       // Scalar types
       ty_nil | ty_bot | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) |
-      ty_send_type | ty_type | ty_native(_) | ty_ptr(_) { result = true; }
+      ty_send_type | ty_type | ty_ptr(_) { result = true; }
       // Boxed types
       ty_str | ty_box(_) | ty_uniq(_) | ty_vec(_) | ty_fn(_) |
       ty_iface(_, _) { result = false; }
@@ -1205,9 +1190,14 @@ fn type_is_pod(cx: ctxt, ty: t) -> bool {
       }
       ty_constr(subt, _) { result = type_is_pod(cx, subt); }
       ty_var(_) {
-        fail "ty_var in type_is_pod";
+          cx.sess.bug("ty_var in type_is_pod");
       }
       ty_param(_, _) { result = false; }
+      ty_opaque_closure_ptr(_) { result = true; }
+      ty_named(_,_) {
+          cx.sess.bug("ty_named in type_is_pod");
+      }
+
     }
 
     ret result;
@@ -1233,7 +1223,7 @@ fn type_is_c_like_enum(cx: ctxt, ty: t) -> bool {
     }
 }
 
-fn type_param(cx: ctxt, ty: t) -> option::t<uint> {
+fn type_param(cx: ctxt, ty: t) -> option<uint> {
     alt struct(cx, ty) {
       ty_param(id, _) { ret some(id); }
       _ {/* fall through */ }
@@ -1244,14 +1234,11 @@ fn type_param(cx: ctxt, ty: t) -> option::t<uint> {
 // Returns a vec of all the type variables
 // occurring in t. It may contain duplicates.
 fn vars_in_type(cx: ctxt, ty: t) -> [int] {
-    fn collect_var(cx: ctxt, vars: @mutable [int], ty: t) {
-        alt struct(cx, ty) { ty_var(v) { *vars += [v]; } _ { } }
+    let rslt = [];
+    walk_ty(cx, ty) {|ty|
+        alt struct(cx, ty) { ty_var(v) { rslt += [v]; } _ { } }
     }
-    let rslt: @mutable [int] = @mutable [];
-    walk_ty(cx, ty) {|t| collect_var(cx, rslt, t)}
-    // Works because of a "convenient" bug that lets us
-    // return a mutable vec as if it's immutable
-    ret *rslt;
+    rslt
 }
 
 fn type_autoderef(cx: ctxt, t: ty::t) -> ty::t {
@@ -1366,7 +1353,6 @@ fn hash_fn(id: uint, args: [arg], rty: t) -> uint {
       ty_var(v) { ret hash_uint(30u, v as uint); }
       ty_param(pid, _) { ret hash_uint(31u, pid); }
       ty_type { ret 32u; }
-      ty_native(did) { ret hash_def(33u, did); }
       ty_bot { ret 34u; }
       ty_ptr(mt) { ret hash_subty(35u, mt.ty); }
       ty_res(did, sub, tps) {
@@ -1438,73 +1424,35 @@ fn constrs_eq(cs: [@constr], ds: [@constr]) -> bool {
     ret true;
 }
 
-// Type lookups
-fn node_id_to_ty_param_substs_opt_and_ty(cx: ctxt, id: ast::node_id) ->
-   ty_param_substs_opt_and_ty {
-    // Pull out the node type table.
-    alt smallintmap::find(*cx.node_types, id as uint) {
-      none {
-        cx.sess.bug("node_id_to_ty_param_substs_opt_and_ty() called on " +
-                        "an untyped node (" + int::to_str(id, 10u) +
-                        ")");
-      }
-      some(tpot) { ret tpot; }
-    }
-}
-
 fn node_id_to_type(cx: ctxt, id: ast::node_id) -> t {
-    ret node_id_to_ty_param_substs_opt_and_ty(cx, id).ty;
+    smallintmap::get(*cx.node_types, id as uint)
 }
 
 fn node_id_to_type_params(cx: ctxt, id: ast::node_id) -> [t] {
-    alt node_id_to_ty_param_substs_opt_and_ty(cx, id).substs {
+    alt cx.node_type_substs.find(id) {
       none { ret []; }
-      some(tps) { ret tps; }
+      some(ts) { ret ts; }
     }
 }
 
 fn node_id_has_type_params(cx: ctxt, id: ast::node_id) -> bool {
-    ret vec::len(node_id_to_type_params(cx, id)) > 0u;
-}
-
-
-// Returns a type with type parameter substitutions performed if applicable
-fn ty_param_substs_opt_and_ty_to_monotype(cx: ctxt,
-                                          tpot: ty_param_substs_opt_and_ty) ->
-   t {
-    alt tpot.substs {
-      none { ret tpot.ty; }
-      some(tps) { ret substitute_type_params(cx, tps, tpot.ty); }
-    }
+    ret cx.node_type_substs.contains_key(id);
 }
 
-
-// Returns the type of an annotation, with type parameter substitutions
-// performed if applicable
-fn node_id_to_monotype(cx: ctxt, id: ast::node_id) -> t {
-    let tpot = node_id_to_ty_param_substs_opt_and_ty(cx, id);
-    ret ty_param_substs_opt_and_ty_to_monotype(cx, tpot);
-}
-
-
 // Returns the number of distinct type parameters in the given type.
 fn count_ty_params(cx: ctxt, ty: t) -> uint {
-    fn counter(cx: ctxt, param_indices: @mutable [uint], ty: t) {
-        alt struct(cx, ty) {
+    let param_indices = [];
+    walk_ty(cx, ty) {|t|
+        alt struct(cx, t) {
           ty_param(param_idx, _) {
-            let seen = false;
-            for other_param_idx: uint in *param_indices {
-                if param_idx == other_param_idx { seen = true; }
+            if !vec::any(param_indices, {|i| i == param_idx}) {
+                param_indices += [param_idx];
             }
-            if !seen { *param_indices += [param_idx]; }
           }
-          _ {/* fall through */ }
+          _ {}
         }
     }
-    let param_indices: @mutable [uint] = @mutable [];
-    let f = bind counter(cx, param_indices, _);
-    walk_ty(cx, ty, f);
-    ret vec::len::<uint>(*param_indices);
+    vec::len(param_indices)
 }
 
 fn type_contains_vars(cx: ctxt, typ: t) -> bool {
@@ -1583,7 +1531,7 @@ fn block_ty(cx: ctxt, b: ast::blk) -> t {
 // Returns the type of a pattern as a monotype. Like @expr_ty, this function
 // doesn't provide type parameter substitutions.
 fn pat_ty(cx: ctxt, pat: @ast::pat) -> t {
-    ret node_id_to_monotype(cx, pat.id);
+    ret node_id_to_type(cx, pat.id);
 }
 
 
@@ -1594,7 +1542,7 @@ fn pat_ty(cx: ctxt, pat: @ast::pat) -> t {
 // instead of "fn(t) -> T with T = int". If this isn't what you want, see
 // expr_ty_params_and_ty() below.
 fn expr_ty(cx: ctxt, expr: @ast::expr) -> t {
-    ret node_id_to_monotype(cx, expr.id);
+    ret node_id_to_type(cx, expr.id);
 }
 
 fn expr_ty_params_and_ty(cx: ctxt, expr: @ast::expr) -> {params: [t], ty: t} {
@@ -1624,23 +1572,28 @@ fn stmt_node_id(s: @ast::stmt) -> ast::node_id {
     }
 }
 
-fn field_idx(id: ast::ident, fields: [field]) -> option::t<uint> {
+fn field_idx(id: ast::ident, fields: [field]) -> option<uint> {
     let i = 0u;
     for f in fields { if f.ident == id { ret some(i); } i += 1u; }
     ret none;
 }
 
 fn get_field(tcx: ctxt, rec_ty: t, id: ast::ident) -> field {
+    alt vec::find(get_fields(tcx, rec_ty), {|f| str::eq(f.ident, id) }) {
+         some(f) { ret f; }
+         _ { tcx.sess.bug(#fmt("get_field: bad field id %s", id)); }
+    }
+}
+
+// TODO: could have a precondition instead of failing
+fn get_fields(tcx:ctxt, rec_ty:t) -> [field] {
     alt struct(tcx, rec_ty) {
-      ty_rec(fields) {
-        alt vec::find(fields, {|f| str::eq(f.ident, id) }) {
-            some(f) { ret f; }
-        }
-      }
+       ty::ty_rec(fields) { fields }
+       _ { tcx.sess.bug("get_fields called on non-record type"); }
     }
 }
 
-fn method_idx(id: ast::ident, meths: [method]) -> option::t<uint> {
+fn method_idx(id: ast::ident, meths: [method]) -> option<uint> {
     let i = 0u;
     for m in meths { if m.ident == id { ret some(i); } i += 1u; }
     ret none;
@@ -1648,12 +1601,12 @@ fn method_idx(id: ast::ident, meths: [method]) -> option::t<uint> {
 
 fn sort_methods(meths: [method]) -> [method] {
     fn method_lteq(a: method, b: method) -> bool {
-        ret str::lteq(a.ident, b.ident);
+        ret str::le(a.ident, b.ident);
     }
     ret std::sort::merge_sort(bind method_lteq(_, _), meths);
 }
 
-fn occurs_check_fails(tcx: ctxt, sp: option::t<span>, vid: int, rt: t) ->
+fn occurs_check_fails(tcx: ctxt, sp: option<span>, vid: int, rt: t) ->
    bool {
     if !type_contains_vars(tcx, rt) {
         // Fast path
@@ -1679,6 +1632,77 @@ fn occurs_check_fails(tcx: ctxt, sp: option::t<span>, vid: int, rt: t) ->
     } else { ret false; }
 }
 
+// Maintains a little union-set tree for inferred modes.  `canon()` returns
+// the current head value for `m0`.
+fn canon<T:copy>(tbl: hashmap<ast::node_id, ast::inferable<T>>,
+                 m0: ast::inferable<T>) -> ast::inferable<T> {
+    alt m0 {
+      ast::infer(id) {
+        alt tbl.find(id) {
+          none { m0 }
+          some(m1) {
+            let cm1 = canon(tbl, m1);
+            // path compression:
+            if cm1 != m1 { tbl.insert(id, cm1); }
+            cm1
+          }
+        }
+      }
+      _ { m0 }
+    }
+}
+
+// Maintains a little union-set tree for inferred modes.  `resolve_mode()`
+// returns the current head value for `m0`.
+fn canon_mode(cx: ctxt, m0: ast::mode) -> ast::mode {
+    canon(cx.inferred_modes, m0)
+}
+
+// Returns the head value for mode, failing if `m` was a infer(_) that
+// was never inferred.  This should be safe for use after typeck.
+fn resolved_mode(cx: ctxt, m: ast::mode) -> ast::rmode {
+    alt canon_mode(cx, m) {
+      ast::infer(_) {
+        cx.sess.bug(#fmt["mode %? was never resolved", m]);
+      }
+      ast::expl(m0) { m0 }
+    }
+}
+
+fn arg_mode(cx: ctxt, a: arg) -> ast::rmode { ty::resolved_mode(cx, a.mode) }
+
+// Unifies `m1` and `m2`.  Returns unified value or failure code.
+fn unify_mode(cx: ctxt, m1: ast::mode, m2: ast::mode)
+    -> result::t<ast::mode, type_err> {
+    alt (canon_mode(cx, m1), canon_mode(cx, m2)) {
+      (m1, m2) if (m1 == m2) {
+        result::ok(m1)
+      }
+      (ast::infer(id1), ast::infer(id2)) {
+        cx.inferred_modes.insert(id2, m1);
+        result::ok(m1)
+      }
+      (ast::infer(id), m) | (m, ast::infer(id)) {
+        cx.inferred_modes.insert(id, m);
+        result::ok(m1)
+      }
+      (m1, m2) {
+        result::err(terr_mode_mismatch(m1, m2))
+      }
+    }
+}
+
+// If `m` was never unified, unifies it with `m_def`.  Returns the final value
+// for `m`.
+fn set_default_mode(cx: ctxt, m: ast::mode, m_def: ast::rmode) {
+    alt canon_mode(cx, m) {
+      ast::infer(id) {
+        cx.inferred_modes.insert(id, ast::expl(m_def));
+      }
+      ast::expl(_) { }
+    }
+}
+
 // Type unification via Robinson's algorithm (Robinson 1965). Implemented as
 // described in Hoder and Voronkov:
 //
@@ -1723,6 +1747,8 @@ fn union(cx: @ctxt, set_a: uint, set_b: uint,
              variance: variance) -> union_result {
         let vb = alt cx.st {
             in_bindings(vb) { vb }
+            _ { cx.tcx.sess.bug("Someone forgot to document an invariant \
+                         in union"); }
         };
         ufind::grow(vb.sets, math::max(set_a, set_b) + 1u);
         let root_a = ufind::find(vb.sets, set_a);
@@ -1736,7 +1762,6 @@ fn union(cx: @ctxt, set_a: uint, set_b: uint,
             }
         );
 
-
         alt smallintmap::find(vb.types, root_a) {
           none {
             alt smallintmap::find(vb.types, root_b) {
@@ -1774,7 +1799,10 @@ fn record_var_binding_for_actual(
     fn record_var_binding(
         cx: @ctxt, key: int, typ: t, variance: variance) -> result {
 
-        let vb = alt cx.st { in_bindings(vb) { vb } };
+        let vb = alt cx.st { in_bindings(vb) { vb }
+            _ { cx.tcx.sess.bug("Someone forgot to document an invariant \
+                 in record_var_binding");  }
+        };
         ufind::grow(vb.sets, (key as uint) + 1u);
         let root = ufind::find(vb.sets, key as uint);
         let result_type = typ;
@@ -1857,7 +1885,7 @@ fn unify_constr(base_t: t, expected: @type_constr,
     // Unifies two mutability flags.
     fn unify_mut(expected: ast::mutability, actual: ast::mutability,
                  variance: variance) ->
-       option::t<(ast::mutability, variance)> {
+       option<(ast::mutability, variance)> {
 
         // If you're unifying on something mutable then we have to
         // be invariant on the inner type
@@ -1883,7 +1911,7 @@ fn unify_mut(expected: ast::mutability, actual: ast::mutability,
         ret none;
     }
     fn unify_fn_proto(e_proto: ast::proto, a_proto: ast::proto,
-                      variance: variance) -> option::t<result> {
+                      variance: variance) -> option<result> {
         // Prototypes form a diamond-shaped partial order:
         //
         //        block
@@ -1925,15 +1953,14 @@ fn unify_args(cx: @ctxt, e_args: [arg], a_args: [arg], variance: variance)
         for expected_input in e_args {
             let actual_input = a_args[i];
             i += 1u;
+
             // Unify the result modes.
-            let result_mode = if expected_input.mode == ast::mode_infer {
-                actual_input.mode
-            } else if actual_input.mode == ast::mode_infer {
-                expected_input.mode
-            } else if expected_input.mode != actual_input.mode {
-                ret either::left(ures_err(terr_mode_mismatch(
-                    expected_input.mode, actual_input.mode)));
-            } else { expected_input.mode };
+            let result_mode =
+                alt unify_mode(cx.tcx, expected_input.mode,
+                               actual_input.mode) {
+                  result::err(err) { ret either::left(ures_err(err)); }
+                  result::ok(m) { m }
+                };
 
             alt unify_step(cx, expected_input.ty, actual_input.ty,
                            variance) {
@@ -2115,19 +2142,9 @@ fn unify_step(cx: @ctxt, expected: t, actual: t,
             ret ures_ok(actual);
           }
           ty::ty_bool | ty::ty_int(_) | ty_uint(_) | ty_float(_) |
-          ty::ty_str | ty::ty_type | ty::ty_send_type {
+          ty::ty_str | ty::ty_send_type {
             ret struct_cmp(cx, expected, actual);
           }
-          ty::ty_native(ex_id) {
-            alt struct(cx.tcx, actual) {
-              ty_native(act_id) {
-                if ex_id.crate == act_id.crate && ex_id.node == act_id.node {
-                    ret ures_ok(actual);
-                } else { ret ures_err(terr_mismatch); }
-              }
-              _ { ret ures_err(terr_mismatch); }
-            }
-          }
           ty::ty_param(expected_n, _) {
             alt struct(cx.tcx, actual) {
               ty::ty_param(actual_n, _) if expected_n == actual_n {
@@ -2388,6 +2405,7 @@ fn unify_step(cx: @ctxt, expected: t, actual: t,
               }
             }
           }
+          _ { cx.tcx.sess.bug("unify: unexpected type"); }
         }
     }
     fn unify(expected: t, actual: t, st: unify_style,
@@ -2400,7 +2418,7 @@ fn dump_var_bindings(tcx: ty_ctxt, vb: @var_bindings) {
         while i < vec::len::<ufind::node>(vb.sets.nodes) {
             let sets = "";
             let j = 0u;
-            while j < vec::len::<option::t<uint>>(vb.sets.nodes) {
+            while j < vec::len::<option<uint>>(vb.sets.nodes) {
                 if ufind::find(vb.sets, j) == i { sets += #fmt[" %u", j]; }
                 j += 1u;
             }
@@ -2418,10 +2436,10 @@ fn dump_var_bindings(tcx: ty_ctxt, vb: @var_bindings) {
     //    Takes an optional span - complain about occurs check violations
     //    iff the span is present (so that if we already know we're going
     //    to error anyway, we don't complain)
-    fn fixup_vars(tcx: ty_ctxt, sp: option::t<span>, vb: @var_bindings,
+    fn fixup_vars(tcx: ty_ctxt, sp: option<span>, vb: @var_bindings,
                   typ: t) -> fixup_result {
-        fn subst_vars(tcx: ty_ctxt, sp: option::t<span>, vb: @var_bindings,
-                      unresolved: @mutable option::t<int>,
+        fn subst_vars(tcx: ty_ctxt, sp: option<span>, vb: @var_bindings,
+                      unresolved: @mutable option<int>,
                       vars_seen: std::list::list<int>, vid: int) -> t {
             // Should really return a fixup_result instead of a t, but fold_ty
             // doesn't allow returning anything but a t.
@@ -2461,7 +2479,7 @@ fn subst_vars(tcx: ty_ctxt, sp: option::t<span>, vb: @var_bindings,
           some(var_id) { ret fix_err(var_id); }
         }
     }
-    fn resolve_type_var(tcx: ty_ctxt, sp: option::t<span>, vb: @var_bindings,
+    fn resolve_type_var(tcx: ty_ctxt, sp: option<span>, vb: @var_bindings,
                         vid: int) -> fixup_result {
         if vid as uint >= ufind::set_count(vb.sets) { ret fix_err(vid); }
         let root_id = ufind::find(vb.sets, vid as uint);
@@ -2511,8 +2529,8 @@ fn to_str(s: ast::ret_style) -> str {
       }
       terr_arg_count { ret "incorrect number of function parameters"; }
       terr_mode_mismatch(e_mode, a_mode) {
-        ret "expected argument mode " + mode_str(e_mode) + " but found " +
-                mode_str(a_mode);
+        ret "expected argument mode " + mode_to_str(e_mode) + " but found " +
+                mode_to_str(a_mode);
       }
       terr_constr_len(e_len, a_len) {
         ret "Expected a type with " + uint::str(e_len) +
@@ -2530,7 +2548,6 @@ fn to_str(s: ast::ret_style) -> str {
 // Replaces type parameters in the given type using the given list of
 // substitions.
 fn substitute_type_params(cx: ctxt, substs: [ty::t], typ: t) -> t {
-
    if !type_contains_params(cx, typ) { ret typ; }
     // Precondition? idx < vec::len(substs)
     fn substituter(_cx: ctxt, substs: @[ty::t], idx: uint, _did: def_id)
@@ -2551,8 +2568,9 @@ fn def_has_ty_params(def: ast::def) -> bool {
       ast::def_mod(_) | ast::def_const(_) |
       ast::def_arg(_, _) | ast::def_local(_, _) | ast::def_upvar(_, _, _) |
       ast::def_ty_param(_, _) | ast::def_binding(_) | ast::def_use(_) |
-      ast::def_native_ty(_) | ast::def_self(_) | ast::def_ty(_) { false }
+      ast::def_self(_) | ast::def_ty(_) { false }
       ast::def_fn(_, _) | ast::def_variant(_, _) { true }
+      _ { false } // ????
     }
 }
 
@@ -2572,7 +2590,7 @@ fn iface_methods(cx: ctxt, id: ast::def_id) -> @[method] {
     result
 }
 
-fn impl_iface(cx: ctxt, id: ast::def_id) -> option::t<t> {
+fn impl_iface(cx: ctxt, id: ast::def_id) -> option<t> {
     if id.crate == ast::local_crate {
         option::map(cx.tcache.find(id), {|it| it.ty})
     } else {
@@ -2596,10 +2614,10 @@ fn enum_variants(cx: ctxt, id: ast::def_id) -> @[variant_info] {
         // check the disr_expr if it exists), this code should likely be
         // moved there to avoid having to call eval_const_expr twice.
         alt cx.items.get(id.node) {
-          ast_map::node_item(@{node: ast::item_enum(variants, _), _}) {
+          ast_map::node_item(@{node: ast::item_enum(variants, _), _}, _) {
             let disr_val = -1;
             @vec::map(variants, {|variant|
-                let ctor_ty = node_id_to_monotype(cx, variant.node.id);
+                let ctor_ty = node_id_to_type(cx, variant.node.id);
                 let arg_tys = if vec::len(variant.node.args) > 0u {
                     vec::map(ty_fn_args(cx, ctor_ty), {|a| a.ty})
                 } else { [] };
@@ -2608,6 +2626,7 @@ fn enum_variants(cx: ctxt, id: ast::def_id) -> @[variant_info] {
                     // FIXME: issue #1417
                     disr_val = alt syntax::ast_util::eval_const_expr(ex) {
                       ast_util::const_int(val) {val as int}
+                      _ { cx.sess.bug("tag_variants: bad disr expr"); }
                     }
                   }
                   _ {disr_val += 1;}
@@ -2620,6 +2639,7 @@ fn enum_variants(cx: ctxt, id: ast::def_id) -> @[variant_info] {
                  }
             })
           }
+          _ { cx.sess.bug("tag_variants: id not bound to an enum"); }
         }
     };
     cx.enum_var_cache.insert(id, result);
@@ -2644,14 +2664,12 @@ fn enum_variant_with_id(cx: ctxt, enum_id: ast::def_id,
 // If the given item is in an external crate, looks up its type and adds it to
 // the type cache. Returns the type parameters and type.
 fn lookup_item_type(cx: ctxt, did: ast::def_id) -> ty_param_bounds_and_ty {
-    if did.crate == ast::local_crate {
-        // The item is in this crate. The caller should have added it to the
-        // type cache already; we simply return it.
-        ret cx.tcache.get(did);
-    }
     alt cx.tcache.find(did) {
       some(tpt) { ret tpt; }
       none {
+        // The item is in this crate. The caller should have added it to the
+        // type cache already
+        assert did.crate != ast::local_crate;
         let tyt = csearch::get_type(cx, did);
         cx.tcache.insert(did, tyt);
         ret tyt;
index b91379246520f1c016e743e36655a2f554923f0f..50f5dd2100737b3b9ad64f076306f9b1f04a9c41 100644 (file)
@@ -10,7 +10,7 @@
 import middle::ty;
 import middle::ty::{node_id_to_type, arg, block_ty,
                     expr_ty, field, node_type_table, mk_nil,
-                    ty_param_substs_opt_and_ty, ty_param_bounds_and_ty};
+                    ty_param_bounds_and_ty};
 import util::ppaux::ty_to_str;
 import middle::ty::unify::{ures_ok, ures_err, fix_ok, fix_err};
 import core::{int, vec, str, option};
@@ -64,7 +64,6 @@ enum self_info {
      var_bindings: @ty::unify::var_bindings,
      locals: hashmap<ast::node_id, int>,
      next_var_id: @mutable int,
-     mutable fixups: [ast::node_id],
      ccx: @crate_ctxt};
 
 
@@ -107,6 +106,9 @@ fn ty_param_bounds_and_ty_for_def(fcx: @fn_ctxt, sp: span, defn: ast::def) ->
           some(self_impl(impl_t)) {
             ret {bounds: @[], ty: impl_t};
           }
+          none {
+              fcx.ccx.tcx.sess.span_bug(sp, "def_self with no self_info");
+          }
         }
       }
       ast::def_fn(id, _) | ast::def_const(id) |
@@ -137,33 +139,35 @@ fn ty_param_bounds_and_ty_for_def(fcx: @fn_ctxt, sp: span, defn: ast::def) ->
 // Instantiates the given path, which must refer to an item with the given
 // number of type parameters and type.
 fn instantiate_path(fcx: @fn_ctxt, pth: @ast::path,
-                    tpt: ty_param_bounds_and_ty, sp: span)
-    -> ty_param_substs_opt_and_ty {
+                    tpt: ty_param_bounds_and_ty, sp: span,
+                    id: ast::node_id) {
     let ty_param_count = vec::len(*tpt.bounds);
-    let vars = vec::init_fn(ty_param_count, {|_i| next_ty_var(fcx)});
     let ty_substs_len = vec::len(pth.node.types);
     if ty_substs_len > 0u {
-        let param_var_len = vec::len(vars);
-        if param_var_len == 0u {
+        if ty_param_count == 0u {
             fcx.ccx.tcx.sess.span_fatal
                 (sp, "this item does not take type parameters");
-        } else if ty_substs_len > param_var_len {
+        } else if ty_substs_len > ty_param_count {
             fcx.ccx.tcx.sess.span_fatal
                 (sp, "too many type parameter provided for this item");
-        } else if ty_substs_len < param_var_len {
+        } else if ty_substs_len < ty_param_count {
             fcx.ccx.tcx.sess.span_fatal
                 (sp, "not enough type parameters provided for this item");
         }
-        vec::iter2(pth.node.types, vars) {|sub, var|
-            let ty_subst = ast_ty_to_ty_crate(fcx.ccx, sub);
-            demand::simple(fcx, pth.span, var, ty_subst);
-        }
         if ty_param_count == 0u {
             fcx.ccx.tcx.sess.span_fatal(
                 sp, "this item does not take type parameters");
         }
+        let substs = vec::map(pth.node.types, {|aty|
+            ast_ty_to_ty_crate(fcx.ccx, aty)
+        });
+        write_ty_substs(fcx.ccx.tcx, id, tpt.ty, substs);
+    } else if ty_param_count > 0u {
+        let vars = vec::init_fn(ty_param_count, {|_i| next_ty_var(fcx)});
+        write_ty_substs(fcx.ccx.tcx, id, tpt.ty, vars);
+    } else {
+        write_ty(fcx.ccx.tcx, id, tpt.ty);
     }
-    {substs: some(vars), ty: tpt.ty}
 }
 
 // Type tests
@@ -186,7 +190,7 @@ fn structure_of(fcx: @fn_ctxt, sp: span, typ: ty::t) -> ty::sty {
 // Returns the one-level-deep structure of the given type or none if it
 // is not known yet.
 fn structure_of_maybe(fcx: @fn_ctxt, _sp: span, typ: ty::t) ->
-   option::t<ty::sty> {
+   option<ty::sty> {
     let r =
         ty::unify::resolve_type_structure(fcx.ccx.tcx, fcx.var_bindings, typ);
     ret alt r {
@@ -210,27 +214,11 @@ fn type_is_c_like_enum(fcx: @fn_ctxt, sp: span, typ: ty::t) -> bool {
     ret ty::type_is_c_like_enum(fcx.ccx.tcx, typ_s);
 }
 
-// Parses the programmer's textual representation of a type into our internal
-// notion of a type. `getter` is a function that returns the type
-// corresponding to a definition ID:
-fn default_arg_mode_for_ty(tcx: ty::ctxt, m: ast::mode,
-                           ty: ty::t) -> ast::mode {
-    alt m {
-      ast::mode_infer {
-        alt ty::struct(tcx, ty) {
-            ty::ty_var(_) { ast::mode_infer }
-            _ {
-                if ty::type_is_immediate(tcx, ty) { ast::by_val }
-                else { ast::by_ref }
-            }
-        }
-      }
-      _ { m }
-    }
-}
-
 enum mode { m_collect, m_check, m_check_tyvar(@fn_ctxt), }
 
+// Parses the programmer's textual representation of a type into our
+// internal notion of a type. `getter` is a function that returns the type
+// corresponding to a definition ID:
 fn ast_ty_to_ty(tcx: ty::ctxt, mode: mode, &&ast_ty: @ast::ty) -> ty::t {
     fn getter(tcx: ty::ctxt, mode: mode, id: ast::def_id)
         -> ty::ty_param_bounds_and_ty {
@@ -240,22 +228,20 @@ fn getter(tcx: ty::ctxt, mode: mode, id: ast::def_id)
             if id.crate != ast::local_crate { csearch::get_type(tcx, id) }
             else {
                 alt tcx.items.find(id.node) {
-                  some(ast_map::node_item(item)) {
+                  some(ast_map::node_item(item, _)) {
                     ty_of_item(tcx, mode, item)
                   }
-                  some(ast_map::node_native_item(native_item)) {
+                  some(ast_map::node_native_item(native_item, _)) {
                     ty_of_native_item(tcx, mode, native_item)
                   }
+                  _ {
+                    tcx.sess.bug("Unexpected sort of item in ast_ty_to_ty");
+                  }
                 }
             }
           }
         }
     }
-    fn ast_arg_to_arg(tcx: ty::ctxt, mode: mode, arg: ast::arg)
-        -> {mode: ty::mode, ty: ty::t} {
-        let ty = ast_ty_to_ty(tcx, mode, arg.ty);
-        ret {mode: default_arg_mode_for_ty(tcx, arg.mode, ty), ty: ty};
-    }
     alt tcx.ast_ty_to_ty_cache.find(ast_ty) {
       some(some(ty)) { ret ty; }
       some(none) {
@@ -335,7 +321,6 @@ fn instantiate(tcx: ty::ctxt, sp: span, mode: mode,
           some(ast::def_ty(id)) {
             typ = instantiate(tcx, ast_ty.span, mode, id, path.node.types);
           }
-          some(ast::def_native_ty(id)) { typ = getter(tcx, mode, id).ty; }
           some(ast::def_ty_param(id, n)) {
             typ = ty::mk_param(tcx, n, id);
           }
@@ -362,6 +347,10 @@ fn instantiate(tcx: ty::ctxt, sp: span, mode: mode,
                                 "found `ty_infer` in unexpected place"); }
         }
       }
+      ast::ty_mac(_) {
+          tcx.sess.span_bug(ast_ty.span,
+                                "found `ty_mac` in unexpected place");
+      }
     }
     tcx.ast_ty_to_ty_cache.insert(ast_ty, some(typ));
     ret typ;
@@ -412,15 +401,19 @@ fn ty_of_item(tcx: ty::ctxt, mode: mode, it: @ast::item)
         ret tpt;
       }
       ast::item_iface(tps, ms) {
-        let s_tp = vec::len(tps) - 1u;
-        tcx.ty_param_bounds.insert(tps[s_tp].id, @[]);
-        let {bounds, params} = mk_ty_params(tcx, vec::slice(tps, 0u, s_tp));
-        let t = ty::mk_named(tcx, ty::mk_iface(tcx, local_def(it.id), params),
+        let {bounds, params} = mk_ty_params(tcx, tps);
+        let t = ty::mk_named(tcx, ty::mk_iface(tcx, local_def(it.id),
+                                               params),
                              @it.ident);
         let tpt = {bounds: bounds, ty: t};
         tcx.tcache.insert(local_def(it.id), tpt);
         ret tpt;
       }
+      ast::item_class(_,_,_,_) {
+          fail "ty_of_item: implement item_class";
+      }
+      ast::item_impl(_, _, _, _) | ast::item_mod(_) |
+      ast::item_native_mod(_) { fail; }
     }
 }
 fn ty_of_native_item(tcx: ty::ctxt, mode: mode, it: @ast::native_item)
@@ -430,27 +423,41 @@ fn ty_of_native_item(tcx: ty::ctxt, mode: mode, it: @ast::native_item)
         ret ty_of_native_fn_decl(tcx, mode, fn_decl, params,
                                  local_def(it.id));
       }
-      ast::native_item_ty {
-        alt tcx.tcache.find(local_def(it.id)) {
-          some(tpt) { ret tpt; }
-          none { }
-        }
-        let t = ty::mk_native(tcx, local_def(it.id));
-        let t = ty::mk_named(tcx, t, @it.ident);
-        let tpt = {bounds: @[], ty: t};
-        tcx.tcache.insert(local_def(it.id), tpt);
-        ret tpt;
-      }
     }
 }
 fn ty_of_arg(tcx: ty::ctxt, mode: mode, a: ast::arg) -> ty::arg {
+    fn arg_mode(tcx: ty::ctxt, m: ast::mode, ty: ty::t) -> ast::mode {
+        alt m {
+          ast::infer(_) {
+            alt ty::struct(tcx, ty) {
+              // If the type is not specified, then this must be a fn expr.
+              // Leave the mode as infer(_), it will get inferred based
+              // on constraints elsewhere.
+              ty::ty_var(_) { m }
+
+              // If the type is known, then use the default for that type.
+              // Here we unify m and the default.  This should update the
+              // tables in tcx but should never fail, because nothing else
+              // will have been unified with m yet:
+              _ {
+                let m1 = ast::expl(ty::default_arg_mode_for_ty(tcx, ty));
+                result::get(ty::unify_mode(tcx, m, m1))
+              }
+            }
+          }
+          ast::expl(_) { m }
+        }
+    }
+
     let ty = ast_ty_to_ty(tcx, mode, a.ty);
-    {mode: default_arg_mode_for_ty(tcx, a.mode, ty), ty: ty}
-}
-fn ty_of_fn_decl(tcx: ty::ctxt, mode: mode,
-                 proto: ast::proto, decl: ast::fn_decl) -> ty::fn_ty {
-    let input_tys = [];
-    for a: ast::arg in decl.inputs { input_tys += [ty_of_arg(tcx, mode, a)]; }
+    let mode = arg_mode(tcx, a.mode, ty);
+    {mode: mode, ty: ty}
+}
+fn ty_of_fn_decl(tcx: ty::ctxt,
+                 mode: mode,
+                 proto: ast::proto,
+                 decl: ast::fn_decl) -> ty::fn_ty {
+    let input_tys = vec::map(decl.inputs) {|a| ty_of_arg(tcx, mode, a) };
     let output_ty = ast_ty_to_ty(tcx, mode, decl.output);
 
     let out_constrs = [];
@@ -473,7 +480,9 @@ fn ty_of_native_fn_decl(tcx: ty::ctxt, mode: mode, decl: ast::fn_decl,
                         ty_params: [ast::ty_param], def_id: ast::def_id)
     -> ty::ty_param_bounds_and_ty {
     let input_tys = [], bounds = ty_param_bounds(tcx, mode, ty_params);
-    for a: ast::arg in decl.inputs { input_tys += [ty_of_arg(tcx, mode, a)]; }
+    for a: ast::arg in decl.inputs {
+        input_tys += [ty_of_arg(tcx, mode, a)];
+    }
     let output_ty = ast_ty_to_ty(tcx, mode, decl.output);
 
     let t_fn = ty::mk_fn(tcx, {proto: ast::proto_bare,
@@ -537,7 +546,7 @@ fn ast_ty_to_ty_crate(ccx: @crate_ctxt, &&ast_ty: @ast::ty) -> ty::t {
 
 // A wrapper around ast_ty_to_ty_crate that handles ty_infer.
 fn ast_ty_to_ty_crate_infer(ccx: @crate_ctxt, &&ast_ty: @ast::ty) ->
-   option::t<ty::t> {
+   option<ty::t> {
     alt ast_ty.node {
       ast::ty_infer { none }
       _ { some(ast_ty_to_ty_crate(ccx, ast_ty)) }
@@ -546,50 +555,25 @@ fn ast_ty_to_ty_crate_infer(ccx: @crate_ctxt, &&ast_ty: @ast::ty) ->
 
 
 // Functions that write types into the node type table
-mod write {
-    fn inner(ntt: node_type_table, node_id: ast::node_id,
-             tpot: ty_param_substs_opt_and_ty) {
-        smallintmap::insert(*ntt, node_id as uint, tpot);
-    }
-
-    // Writes a type parameter count and type pair into the node type table.
-    fn ty(tcx: ty::ctxt, node_id: ast::node_id,
-          tpot: ty_param_substs_opt_and_ty) {
-        assert (!ty::type_contains_vars(tcx, tpot.ty));
-        inner(tcx.node_types, node_id, tpot);
-    }
-
-    // Writes a type parameter count and type pair into the node type table.
-    // This function allows for the possibility of type variables, which will
-    // be rewritten later during the fixup mode.
-    fn ty_fixup(fcx: @fn_ctxt, node_id: ast::node_id,
-                tpot: ty_param_substs_opt_and_ty) {
-        inner(fcx.ccx.tcx.node_types, node_id, tpot);
-        if ty::type_contains_vars(fcx.ccx.tcx, tpot.ty) {
-            fcx.fixups += [node_id];
-        }
-    }
-
-    // Writes a type with no type parameters into the node type table.
-    fn ty_only(tcx: ty::ctxt, node_id: ast::node_id, typ: ty::t) {
-        ty(tcx, node_id, {substs: none::<[ty::t]>, ty: typ});
-    }
-
-    // Writes a type with no type parameters into the node type table. This
-    // function allows for the possibility of type variables.
-    fn ty_only_fixup(fcx: @fn_ctxt, node_id: ast::node_id, typ: ty::t) {
-        ret ty_fixup(fcx, node_id, {substs: none::<[ty::t]>, ty: typ});
-    }
-
-    // Writes a nil type into the node type table.
-    fn nil_ty(tcx: ty::ctxt, node_id: ast::node_id) {
-        ret ty(tcx, node_id, {substs: none::<[ty::t]>, ty: ty::mk_nil(tcx)});
-    }
-
-    // Writes the bottom type into the node type table.
-    fn bot_ty(tcx: ty::ctxt, node_id: ast::node_id) {
-        ret ty(tcx, node_id, {substs: none::<[ty::t]>, ty: ty::mk_bot(tcx)});
-    }
+fn write_ty(tcx: ty::ctxt, node_id: ast::node_id, ty: ty::t) {
+    smallintmap::insert(*tcx.node_types, node_id as uint, ty);
+}
+fn write_substs(tcx: ty::ctxt, node_id: ast::node_id, +substs: [ty::t]) {
+    tcx.node_type_substs.insert(node_id, substs);
+}
+fn write_ty_substs(tcx: ty::ctxt, node_id: ast::node_id, ty: ty::t,
+                   +substs: [ty::t]) {
+    let ty = if ty::type_contains_params(tcx, ty) {
+        ty::substitute_type_params(tcx, substs, ty)
+    } else { ty };
+    write_ty(tcx, node_id, ty);
+    write_substs(tcx, node_id, substs);
+}
+fn write_nil(tcx: ty::ctxt, node_id: ast::node_id) {
+    write_ty(tcx, node_id, ty::mk_nil(tcx));
+}
+fn write_bot(tcx: ty::ctxt, node_id: ast::node_id) {
+    write_ty(tcx, node_id, ty::mk_bot(tcx));
 }
 
 fn mk_ty_params(tcx: ty::ctxt, atps: [ast::ty_param])
@@ -604,17 +588,15 @@ fn mk_ty_params(tcx: ty::ctxt, atps: [ast::ty_param])
 }
 
 fn compare_impl_method(tcx: ty::ctxt, sp: span, impl_m: ty::method,
-                       impl_tps: uint, if_m: ty::method, substs: [ty::t])
-    -> ty::t {
+                       impl_tps: uint, if_m: ty::method, substs: [ty::t]) {
     if impl_m.tps != if_m.tps {
         tcx.sess.span_err(sp, "method `" + if_m.ident +
                           "` has an incompatible set of type parameters");
-        ty::mk_fn(tcx, impl_m.fty)
     } else {
         let auto_modes = vec::map2(impl_m.fty.inputs, if_m.fty.inputs, {|i, f|
             alt ty::struct(tcx, f.ty) {
-              ty::ty_param(0u, _) if i.mode == ast::mode_infer {
-                {mode: ast::by_ref with i}
+              ty::ty_param(0u, _) {
+                {mode: ast::expl(ast::by_ref) with i}
               }
               _ { i }
             }
@@ -631,9 +613,8 @@ fn compare_impl_method(tcx: ty::ctxt, sp: span, impl_m: ty::method,
             tcx.sess.span_err(sp, "method `" + if_m.ident +
                               "` has an incompatible type: " +
                               ty::type_err_to_str(err));
-            impl_fty
           }
-          ty::unify::ures_ok(tp) { tp }
+          _ {}
         }
     }
 }
@@ -672,7 +653,7 @@ fn get_enum_variant_types(cx: @ctxt, enum_ty: ty::t,
                 let args: [arg] = [];
                 for va: ast::variant_arg in variant.node.args {
                     let arg_ty = ast_ty_to_ty(cx.tcx, m_collect, va.ty);
-                    args += [{mode: ast::by_copy, ty: arg_ty}];
+                    args += [{mode: ast::expl(ast::by_copy), ty: arg_ty}];
                 }
                 // FIXME: this will be different for constrained types
                 ty::mk_fn(cx.tcx,
@@ -683,7 +664,7 @@ fn get_enum_variant_types(cx: @ctxt, enum_ty: ty::t,
             let tpt = {bounds: ty_param_bounds(cx.tcx, m_collect, ty_params),
                        ty: result_ty};
             cx.tcx.tcache.insert(local_def(variant.node.id), tpt);
-            write::ty_only(cx.tcx, variant.node.id, result_ty);
+            write_ty(cx.tcx, variant.node.id, result_ty);
         }
     }
     fn convert(cx: @ctxt, it: @ast::item) {
@@ -692,7 +673,7 @@ fn convert(cx: @ctxt, it: @ast::item) {
           ast::item_mod(_) | ast::item_native_mod(_) {}
           ast::item_enum(variants, ty_params) {
             let tpt = ty_of_item(cx.tcx, m_collect, it);
-            write::ty_only(cx.tcx, it.id, tpt.ty);
+            write_ty(cx.tcx, it.id, tpt.ty);
             get_enum_variant_types(cx, tpt.ty, variants, ty_params);
           }
           ast::item_impl(tps, ifce, selfty, ms) {
@@ -701,15 +682,15 @@ fn convert(cx: @ctxt, it: @ast::item) {
             for m in ms {
                 let bounds = ty_param_bounds(cx.tcx, m_collect, m.tps);
                 let mty = ty_of_method(cx.tcx, m_collect, m);
-                my_methods += [{mty: mty, id: m.id}];
+                my_methods += [mty];
                 let fty = ty::mk_fn(cx.tcx, mty.fty);
                 cx.tcx.tcache.insert(local_def(m.id),
                                      {bounds: @(*i_bounds + *bounds),
                                       ty: fty});
-                write::ty_only(cx.tcx, m.id, fty);
+                write_ty(cx.tcx, m.id, fty);
             }
-            let selfty = ast_ty_to_ty(cx.tcx, m_collect, selfty);
-            write::ty_only(cx.tcx, it.id, selfty);
+            write_ty(cx.tcx, it.id, ast_ty_to_ty(cx.tcx, m_collect,
+                                                       selfty));
             alt ifce {
               some(t) {
                 let iface_ty = ast_ty_to_ty(cx.tcx, m_collect, t);
@@ -719,18 +700,10 @@ fn convert(cx: @ctxt, it: @ast::item) {
                   ty::ty_iface(did, tys) {
                     for if_m in *ty::iface_methods(cx.tcx, did) {
                         alt vec::find(my_methods,
-                                      {|m| if_m.ident == m.mty.ident}) {
-                          some({mty: m, id}) {
-                            let mt = compare_impl_method(
-                                cx.tcx, t.span, m, vec::len(tps), if_m,
-                                tys + [selfty]);
-                            let old = cx.tcx.tcache.get(local_def(id));
-                            if old.ty != mt {
-                                cx.tcx.tcache.insert(local_def(id),
-                                                     {bounds: old.bounds,
-                                                      ty: mt});
-                                write::ty_only(cx.tcx, id, mt);
-                            }
+                                      {|m| if_m.ident == m.ident}) {
+                          some(m) {
+                            compare_impl_method(cx.tcx, t.span, m,
+                                                vec::len(tps), if_m, tys);
                           }
                           none {
                             cx.tcx.sess.span_err(t.span, "missing method `" +
@@ -755,7 +728,7 @@ fn convert(cx: @ctxt, it: @ast::item) {
                                    params);
             let t_ctor = ty::mk_fn(cx.tcx, {
                 proto: ast::proto_box,
-                inputs: [{mode: ast::by_copy with t_arg}],
+                inputs: [{mode: ast::expl(ast::by_copy) with t_arg}],
                 output: t_res,
                 ret_style: ast::return_val, constraints: []
             });
@@ -764,15 +737,15 @@ fn convert(cx: @ctxt, it: @ast::item) {
                 inputs: [t_arg], output: ty::mk_nil(cx.tcx),
                 ret_style: ast::return_val, constraints: []
             });
-            write::ty_only(cx.tcx, it.id, t_res);
-            write::ty_only(cx.tcx, ctor_id, t_ctor);
+            write_ty(cx.tcx, it.id, t_res);
+            write_ty(cx.tcx, ctor_id, t_ctor);
             cx.tcx.tcache.insert(local_def(ctor_id),
                                  {bounds: bounds, ty: t_ctor});
-            write::ty_only(cx.tcx, dtor_id, t_dtor);
+            write_ty(cx.tcx, dtor_id, t_dtor);
           }
           ast::item_iface(_, ms) {
             let tpt = ty_of_item(cx.tcx, m_collect, it);
-            write::ty_only(cx.tcx, it.id, tpt.ty);
+            write_ty(cx.tcx, it.id, tpt.ty);
             ty::store_iface_methods(cx.tcx, it.id, @vec::map(ms, {|m|
                 ty_of_ty_method(cx.tcx, m_collect, m)
             }));
@@ -782,7 +755,7 @@ fn convert(cx: @ctxt, it: @ast::item) {
             // of the item in passing. All we have to do here is to write
             // it into the node type table.
             let tpt = ty_of_item(cx.tcx, m_collect, it);
-            write::ty_only(cx.tcx, it.id, tpt.ty);
+            write_ty(cx.tcx, it.id, tpt.ty);
           }
         }
     }
@@ -792,11 +765,8 @@ fn convert_native(cx: @ctxt, i: @ast::native_item) {
         // table.
         let tpt = ty_of_native_item(cx.tcx, m_collect, i);
         alt i.node {
-          ast::native_item_ty {
-            // FIXME: Native types have no annotation. Should they? --pcw
-          }
           ast::native_item_fn(_, _) {
-            write::ty_only(cx.tcx, i.id, tpt.ty);
+            write_ty(cx.tcx, i.id, tpt.ty);
           }
         }
     }
@@ -967,16 +937,13 @@ fn variant_arg_types(ccx: @crate_ctxt, _sp: span, vid: ast::def_id,
 // Type resolution: the phase that finds all the types in the AST with
 // unresolved type variables and replaces "ty_var" types with their
 // substitutions.
-//
-// TODO: inefficient since not all types have vars in them. It would be better
-// to maintain a list of fixups.
 mod writeback {
 
     export resolve_type_vars_in_block;
     export resolve_type_vars_in_expr;
 
     fn resolve_type_vars_in_type(fcx: @fn_ctxt, sp: span, typ: ty::t) ->
-       option::t<ty::t> {
+       option<ty::t> {
         if !ty::type_contains_vars(fcx.ccx.tcx, typ) { ret some(typ); }
         alt ty::unify::fixup_vars(fcx.ccx.tcx, some(sp), fcx.var_bindings,
                                   typ) {
@@ -988,29 +955,33 @@ fn resolve_type_vars_in_type(fcx: @fn_ctxt, sp: span, typ: ty::t) ->
           }
         }
     }
-    fn resolve_type_vars_for_node(wbcx: wb_ctxt, sp: span, id: ast::node_id) {
-        let fcx = wbcx.fcx;
-        let tpot = ty::node_id_to_ty_param_substs_opt_and_ty(fcx.ccx.tcx, id);
-        let new_ty =
-            alt resolve_type_vars_in_type(fcx, sp, tpot.ty) {
-              some(t) { t }
-              none { wbcx.success = false; ret }
-            };
-        let new_substs_opt;
-        alt tpot.substs {
-          none { new_substs_opt = none; }
-          some(substs) {
-            let new_substs: [ty::t] = [];
-            for subst: ty::t in substs {
-                alt resolve_type_vars_in_type(fcx, sp, subst) {
-                  some(t) { new_substs += [t]; }
-                  none { wbcx.success = false; ret; }
+    fn resolve_type_vars_for_node(wbcx: wb_ctxt, sp: span, id: ast::node_id)
+        -> option<ty::t> {
+        let fcx = wbcx.fcx, tcx = fcx.ccx.tcx;
+        alt resolve_type_vars_in_type(fcx, sp, ty::node_id_to_type(tcx, id)) {
+          none {
+            wbcx.success = false;
+            ret none;
+          }
+
+          some(t) {
+            write_ty(tcx, id, t);
+            alt tcx.node_type_substs.find(id) {
+              some(substs) {
+                let new_substs = [];
+                for subst: ty::t in substs {
+                    alt resolve_type_vars_in_type(fcx, sp, subst) {
+                      some(t) { new_substs += [t]; }
+                      none { wbcx.success = false; ret none; }
+                    }
                 }
+                write_substs(tcx, id, new_substs);
+              }
+              none {}
             }
-            new_substs_opt = some(new_substs);
+            ret some(t);
           }
         }
-        write::ty(fcx.ccx.tcx, id, {substs: new_substs_opt, ty: new_ty});
     }
 
     type wb_ctxt =
@@ -1030,8 +1001,19 @@ fn visit_expr(e: @ast::expr, wbcx: wb_ctxt, v: wb_vt) {
         alt e.node {
           ast::expr_fn(_, decl, _, _) |
           ast::expr_fn_block(decl, _) {
-            for input in decl.inputs {
-                resolve_type_vars_for_node(wbcx, e.span, input.id);
+            vec::iter(decl.inputs) {|input|
+                let r_ty = resolve_type_vars_for_node(wbcx, e.span, input.id);
+
+                // Just in case we never constrained the mode to anything,
+                // constrain it to the default for the type in question.
+                alt (r_ty, input.mode) {
+                  (some(t), ast::infer(_)) {
+                    let tcx = wbcx.fcx.ccx.tcx;
+                    let m_def = ty::default_arg_mode_for_ty(tcx, t);
+                    ty::set_default_mode(tcx, input.mode, m_def);
+                  }
+                  _ {}
+                }
             }
           }
           _ { }
@@ -1055,7 +1037,7 @@ fn visit_local(l: @ast::local, wbcx: wb_ctxt, v: wb_vt) {
             ty::unify::resolve_type_var(wbcx.fcx.ccx.tcx, some(l.span),
                                         wbcx.fcx.var_bindings, var_id);
         alt fix_rslt {
-          fix_ok(lty) { write::ty_only(wbcx.fcx.ccx.tcx, l.node.id, lty); }
+          fix_ok(lty) { write_ty(wbcx.fcx.ccx.tcx, l.node.id, lty); }
           fix_err(_) {
             wbcx.fcx.ccx.tcx.sess.span_err(l.span,
                                            "cannot determine a type \
@@ -1111,7 +1093,7 @@ fn gather_locals(ccx: @crate_ctxt,
                  decl: ast::fn_decl,
                  body: ast::blk,
                  id: ast::node_id,
-                 old_fcx: option::t<@fn_ctxt>) -> gather_result {
+                 old_fcx: option<@fn_ctxt>) -> gather_result {
     let {vb: vb, locals: locals, nvi: nvi} =
         alt old_fcx {
           none {
@@ -1128,7 +1110,7 @@ fn gather_locals(ccx: @crate_ctxt,
     let tcx = ccx.tcx;
 
     let next_var_id = fn@() -> int { let rv = *nvi; *nvi += 1; ret rv; };
-    let assign = fn@(nid: ast::node_id, ty_opt: option::t<ty::t>) {
+    let assign = fn@(nid: ast::node_id, ty_opt: option<ty::t>) {
             let var_id = next_var_id();
             locals.insert(nid, var_id);
             alt ty_opt {
@@ -1203,53 +1185,48 @@ fn valid_range_bounds(from: @ast::expr, to: @ast::expr) -> bool {
 // their types immediately.
 fn check_pat(fcx: @fn_ctxt, map: pat_util::pat_id_map, pat: @ast::pat,
              expected: ty::t) {
-    alt normalize_pat(fcx.ccx.tcx, pat).node {
+    let tcx = fcx.ccx.tcx;
+    alt normalize_pat(tcx, pat).node {
       ast::pat_wild {
           alt structure_of(fcx, pat.span, expected) {
                   ty::ty_enum(_, expected_tps) {
-                      let path_tpt = {substs: some(expected_tps),
-                                      ty: expected};
-                      write::ty_fixup(fcx, pat.id, path_tpt);
+                    write_ty_substs(tcx, pat.id, expected,
+                                    expected_tps);
                   }
                   _ {
-                      write::ty_only_fixup(fcx, pat.id, expected);
+                    write_ty(tcx, pat.id, expected);
                   }
               }
       }
       ast::pat_lit(lt) {
         check_expr_with(fcx, lt, expected);
-        write::ty_only_fixup(fcx, pat.id, expr_ty(fcx.ccx.tcx, lt));
+        write_ty(tcx, pat.id, expr_ty(tcx, lt));
       }
       ast::pat_range(begin, end) {
         check_expr_with(fcx, begin, expected);
         check_expr_with(fcx, end, expected);
-        let b_ty = resolve_type_vars_if_possible(fcx, expr_ty(fcx.ccx.tcx,
-                                                              begin));
-        if !ty::same_type(fcx.ccx.tcx, b_ty, resolve_type_vars_if_possible(
-            fcx, expr_ty(fcx.ccx.tcx, end))) {
-            fcx.ccx.tcx.sess.span_err(pat.span, "mismatched types in range");
-        } else if !ty::type_is_numeric(fcx.ccx.tcx, b_ty) {
-            fcx.ccx.tcx.sess.span_err(pat.span,
-                                      "non-numeric type used in range");
+        let b_ty = resolve_type_vars_if_possible(fcx, expr_ty(tcx, begin));
+        if !ty::same_type(tcx, b_ty, resolve_type_vars_if_possible(
+            fcx, expr_ty(tcx, end))) {
+            tcx.sess.span_err(pat.span, "mismatched types in range");
+        } else if !ty::type_is_numeric(tcx, b_ty) {
+            tcx.sess.span_err(pat.span, "non-numeric type used in range");
         } else if !valid_range_bounds(begin, end) {
-            fcx.ccx.tcx.sess.span_err(begin.span,
-                                      "lower range bound must be less \
-                                       than upper");
+            tcx.sess.span_err(begin.span, "lower range bound must be less \
+                                           than upper");
         }
-        write::ty_only_fixup(fcx, pat.id, b_ty);
+        write_ty(tcx, pat.id, b_ty);
       }
       ast::pat_ident(name, sub) {
         let vid = lookup_local(fcx, pat.span, pat.id);
-        let typ = ty::mk_var(fcx.ccx.tcx, vid);
+        let typ = ty::mk_var(tcx, vid);
         typ = demand::simple(fcx, pat.span, expected, typ);
         let canon_id = map.get(path_to_ident(name));
         if canon_id != pat.id {
-            let ct =
-                ty::mk_var(fcx.ccx.tcx,
-                           lookup_local(fcx, pat.span, canon_id));
+            let ct = ty::mk_var(tcx, lookup_local(fcx, pat.span, canon_id));
             typ = demand::simple(fcx, pat.span, ct, typ);
         }
-        write::ty_only_fixup(fcx, pat.id, typ);
+        write_ty(tcx, pat.id, typ);
         alt sub {
           some(p) { check_pat(fcx, map, p, expected); }
           _ {}
@@ -1259,23 +1236,15 @@ fn check_pat(fcx: @fn_ctxt, map: pat_util::pat_id_map, pat: @ast::pat,
         // Typecheck the path.
         let v_def = lookup_def(fcx, path.span, pat.id);
         let v_def_ids = ast_util::variant_def_ids(v_def);
-        let enum_tpt = ty::lookup_item_type(fcx.ccx.tcx, v_def_ids.tg);
-        let path_tpot = instantiate_path(fcx, path, enum_tpt, pat.span);
+        let ctor_tpt = ty::lookup_item_type(tcx, v_def_ids.enm);
+        instantiate_path(fcx, path, ctor_tpt, pat.span, pat.id);
 
         // Take the enum type params out of `expected`.
         alt structure_of(fcx, pat.span, expected) {
           ty::ty_enum(_, expected_tps) {
-            // Unify with the expected enum type.
-            let ctor_ty =
-                ty::ty_param_substs_opt_and_ty_to_monotype(fcx.ccx.tcx,
-                                                           path_tpot);
-
-            let path_tpt =
-                demand::with_substs(fcx, pat.span, expected, ctor_ty,
-                                    expected_tps);
-            path_tpot =
-                {substs: some::<[ty::t]>(path_tpt.substs), ty: path_tpt.ty};
-
+            let ctor_ty = ty::node_id_to_type(tcx, pat.id);
+            demand::with_substs(fcx, pat.span, expected, ctor_ty,
+                                expected_tps);
             // Get the number of arguments in this enum variant.
             let arg_types =
                 variant_arg_types(fcx.ccx, pat.span, v_def_ids.var,
@@ -1283,68 +1252,59 @@ fn check_pat(fcx: @fn_ctxt, map: pat_util::pat_id_map, pat: @ast::pat,
             let subpats_len = vec::len::<@ast::pat>(subpats);
             if vec::len::<ty::t>(arg_types) > 0u {
                 // N-ary variant.
-
                 let arg_len = vec::len::<ty::t>(arg_types);
                 if arg_len != subpats_len {
                     // TODO: note definition of enum variant
                     // TODO (issue #448): Wrap a #fmt string over multiple
                     // lines...
-                    let s =
-                        #fmt["this pattern has %u field%s, but the \
-                                       corresponding variant has %u field%s",
-                             subpats_len,
-                             if subpats_len == 1u { "" } else { "s" },
-                             arg_len, if arg_len == 1u { "" } else { "s" }];
-                    fcx.ccx.tcx.sess.span_fatal(pat.span, s);
+                    let s = #fmt["this pattern has %u field%s, but the \
+                                  corresponding variant has %u field%s",
+                                 subpats_len,
+                                 if subpats_len == 1u { "" } else { "s" },
+                                 arg_len,
+                                 if arg_len == 1u { "" } else { "s" }];
+                    tcx.sess.span_err(pat.span, s);
                 }
 
-                // TODO: vec::iter2
-
-                let i = 0u;
-                for subpat: @ast::pat in subpats {
-                    check_pat(fcx, map, subpat, arg_types[i]);
-                    i += 1u;
+                vec::iter2(subpats, arg_types) {|subpat, arg_ty|
+                    check_pat(fcx, map, subpat, arg_ty);
                 }
             } else if subpats_len > 0u {
                 // TODO: note definition of enum variant
-                fcx.ccx.tcx.sess.span_fatal
-                    (pat.span,
-                     #fmt["this pattern has %u field%s, \
-                          but the corresponding \
-                          variant has no fields",
-                                                 subpats_len,
-                                                 if subpats_len == 1u {
-                                                     ""
-                                                 } else { "s" }]);
+                tcx.sess.span_err
+                    (pat.span, #fmt["this pattern has %u field%s, \
+                                     but the corresponding \
+                                     variant has no fields",
+                                    subpats_len,
+                                    if subpats_len == 1u { "" }
+                                    else { "s" }]);
             }
-            write::ty_fixup(fcx, pat.id, path_tpot);
           }
           _ {
             // FIXME: Switch expected and actual in this message? I
             // can never tell.
-            fcx.ccx.tcx.sess.span_fatal
+            tcx.sess.span_err
                 (pat.span,
                  #fmt["mismatched types: expected `%s` but found enum",
-                      ty_to_str(fcx.ccx.tcx, expected)]);
+                      ty_to_str(tcx, expected)]);
           }
         }
-        write::ty_fixup(fcx, pat.id, path_tpot);
       }
       ast::pat_rec(fields, etc) {
         let ex_fields;
         alt structure_of(fcx, pat.span, expected) {
           ty::ty_rec(fields) { ex_fields = fields; }
           _ {
-            fcx.ccx.tcx.sess.span_fatal
+            tcx.sess.span_fatal
                 (pat.span,
                 #fmt["mismatched types: expected `%s` but found record",
-                                ty_to_str(fcx.ccx.tcx, expected)]);
+                                ty_to_str(tcx, expected)]);
           }
         }
         let f_count = vec::len(fields);
         let ex_f_count = vec::len(ex_fields);
         if ex_f_count < f_count || !etc && ex_f_count > f_count {
-            fcx.ccx.tcx.sess.span_fatal
+            tcx.sess.span_fatal
                 (pat.span, #fmt["mismatched types: expected a record \
                       with %u fields, found one with %u \
                       fields",
@@ -1357,47 +1317,47 @@ fn matches(name: str, f: ty::field) -> bool {
             alt vec::find(ex_fields, bind matches(f.ident, _)) {
               some(field) { check_pat(fcx, map, f.pat, field.mt.ty); }
               none {
-                fcx.ccx.tcx.sess.span_fatal(pat.span,
-                                            #fmt["mismatched types: did not \
-                                           expect a record with a field `%s`",
-                                                 f.ident]);
+                tcx.sess.span_fatal(pat.span,
+                                    #fmt["mismatched types: did not \
+                                          expect a record with a field `%s`",
+                                         f.ident]);
               }
             }
         }
-        write::ty_only_fixup(fcx, pat.id, expected);
+        write_ty(tcx, pat.id, expected);
       }
       ast::pat_tup(elts) {
         let ex_elts;
         alt structure_of(fcx, pat.span, expected) {
           ty::ty_tup(elts) { ex_elts = elts; }
           _ {
-            fcx.ccx.tcx.sess.span_fatal
+            tcx.sess.span_fatal
                 (pat.span,
                  #fmt["mismatched types: expected `%s`, found tuple",
-                        ty_to_str(fcx.ccx.tcx, expected)]);
+                        ty_to_str(tcx, expected)]);
           }
         }
         let e_count = vec::len(elts);
         if e_count != vec::len(ex_elts) {
-            fcx.ccx.tcx.sess.span_fatal
+            tcx.sess.span_fatal
                 (pat.span, #fmt["mismatched types: expected a tuple \
                       with %u fields, found one with %u \
                       fields", vec::len(ex_elts), e_count]);
         }
         let i = 0u;
         for elt in elts { check_pat(fcx, map, elt, ex_elts[i]); i += 1u; }
-        write::ty_only_fixup(fcx, pat.id, expected);
+        write_ty(tcx, pat.id, expected);
       }
       ast::pat_box(inner) {
         alt structure_of(fcx, pat.span, expected) {
           ty::ty_box(e_inner) {
             check_pat(fcx, map, inner, e_inner.ty);
-            write::ty_only_fixup(fcx, pat.id, expected);
+            write_ty(tcx, pat.id, expected);
           }
           _ {
-            fcx.ccx.tcx.sess.span_fatal(pat.span,
+            tcx.sess.span_fatal(pat.span,
                                         "mismatched types: expected `" +
-                                            ty_to_str(fcx.ccx.tcx, expected) +
+                                            ty_to_str(tcx, expected) +
                                             "` found box");
           }
         }
@@ -1406,12 +1366,12 @@ fn matches(name: str, f: ty::field) -> bool {
         alt structure_of(fcx, pat.span, expected) {
           ty::ty_uniq(e_inner) {
             check_pat(fcx, map, inner, e_inner.ty);
-            write::ty_only_fixup(fcx, pat.id, expected);
+            write_ty(tcx, pat.id, expected);
           }
           _ {
-            fcx.ccx.tcx.sess.span_fatal(pat.span,
+            tcx.sess.span_fatal(pat.span,
                                         "mismatched types: expected `" +
-                                            ty_to_str(fcx.ccx.tcx, expected) +
+                                            ty_to_str(tcx, expected) +
                                             "` found uniq");
           }
         }
@@ -1486,9 +1446,12 @@ fn impl_self_ty(tcx: ty::ctxt, did: ast::def_id) -> {n_tps: uint, ty: ty::t} {
     if did.crate == ast::local_crate {
         alt tcx.items.get(did.node) {
           ast_map::node_item(@{node: ast::item_impl(ts, _, st, _),
-                               _}) {
+                               _}, _) {
             {n_tps: vec::len(ts), ty: ast_ty_to_ty(tcx, m_check, st)}
           }
+          an_item {
+              tcx.sess.bug("Undocumented invariant in impl_self_ty");
+          }
         }
     } else {
         let tpt = csearch::get_type(tcx, did);
@@ -1498,7 +1461,7 @@ fn impl_self_ty(tcx: ty::ctxt, did: ast::def_id) -> {n_tps: uint, ty: ty::t} {
 
 fn lookup_method(fcx: @fn_ctxt, isc: resolve::iscopes,
                  name: ast::ident, ty: ty::t, sp: span)
-    -> option::t<{method_ty: ty::t, n_tps: uint, substs: [ty::t],
+    -> option<{method_ty: ty::t, n_tps: uint, substs: [ty::t],
                   origin: method_origin}> {
     let tcx = fcx.ccx.tcx;
 
@@ -1511,6 +1474,10 @@ fn lookup_method(fcx: @fn_ctxt, isc: resolve::iscopes,
               ty::bound_iface(t) {
                 let (iid, tps) = alt ty::struct(tcx, t) {
                     ty::ty_iface(i, tps) { (i, tps) }
+                    _ {
+                        tcx.sess.span_bug(sp, "Undocument invariant in \
+                          lookup_method");
+                    }
                 };
                 let ifce_methods = ty::iface_methods(tcx, iid);
                 alt vec::position(*ifce_methods, {|m| m.ident == name}) {
@@ -1518,7 +1485,7 @@ fn lookup_method(fcx: @fn_ctxt, isc: resolve::iscopes,
                     let m = ifce_methods[pos];
                     ret some({method_ty: ty::mk_fn(tcx, m.fty),
                               n_tps: vec::len(*m.tps),
-                              substs: tps + [ty],
+                              substs: tps,
                               origin: method_param(iid, pos, n, bound_n)});
                   }
                   _ {}
@@ -1536,7 +1503,7 @@ fn lookup_method(fcx: @fn_ctxt, isc: resolve::iscopes,
             if m.ident == name {
                 ret some({method_ty: ty::mk_fn(tcx, m.fty),
                           n_tps: vec::len(*m.tps),
-                          substs: tps + [ty::mk_int(tcx)],
+                          substs: tps,
                           origin: method_iface(i)});
             }
             i += 1u;
@@ -1545,6 +1512,20 @@ fn lookup_method(fcx: @fn_ctxt, isc: resolve::iscopes,
       _ {}
     }
 
+    fn ty_from_did(tcx: ty::ctxt, did: ast::def_id) -> ty::t {
+        if did.crate == ast::local_crate {
+            alt tcx.items.get(did.node) {
+              ast_map::node_method(m, _) {
+                let mt = ty_of_method(tcx, m_check, m);
+                ty::mk_fn(tcx, mt.fty)
+              }
+              _ {
+                  tcx.sess.bug("Undocumented invariant in ty_from_did");
+              }
+            }
+        } else { csearch::get_type(tcx, did).ty }
+    }
+
     let result = none;
     std::list::iter(isc) {|impls|
         if option::is_some(result) { ret; }
@@ -1563,7 +1544,7 @@ fn lookup_method(fcx: @fn_ctxt, isc: resolve::iscopes,
                             sp, "multiple applicable methods in scope");
                     } else {
                         result = some({
-                            method_ty: ty::lookup_item_type(tcx, m.did).ty,
+                            method_ty: ty_from_did(tcx, m.did),
                             n_tps: m.n_tps,
                             substs: vars,
                             origin: method_static(m.did)
@@ -1588,15 +1569,14 @@ fn check_expr_fn_with_unifier(fcx: @fn_ctxt,
                               unify: unifier,
                               expected: ty::t) {
     let tcx = fcx.ccx.tcx;
-
-    let fty = ty::mk_fn(tcx, ty_of_fn_decl(tcx, m_check_tyvar(fcx),
-                                           proto, decl));
+    let fty = ty::mk_fn(tcx,
+                        ty_of_fn_decl(tcx, m_check_tyvar(fcx), proto, decl));
 
     #debug("check_expr_fn_with_unifier %s fty=%s",
            expr_to_str(expr),
            ty_to_str(tcx, fty));
 
-    write::ty_only_fixup(fcx, expr.id, fty);
+    write_ty(tcx, expr.id, fty);
 
     // Unify the type of the function with the expected type before we
     // typecheck the body so that we have more information about the
@@ -1615,7 +1595,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
     // A generic function to factor out common logic from call and bind
     // expressions.
     fn check_call_or_bind(fcx: @fn_ctxt, sp: span, fty: ty::t,
-                          args: [option::t<@ast::expr>]) -> bool {
+                          args: [option<@ast::expr>]) -> bool {
         let sty = structure_of(fcx, sp, fty);
         // Grab the argument types
         let arg_tys = alt sty {
@@ -1635,12 +1615,21 @@ fn check_call_or_bind(fcx: @fn_ctxt, sp: span, fty: ty::t,
             fcx.ccx.tcx.sess.span_err(
                 sp, #fmt["this function takes %u parameter%s but %u \
                           parameter%s supplied", expected_arg_count,
-                         expected_arg_count == 1u ? "" : "s",
+                         if expected_arg_count == 1u {
+                             ""
+                         } else {
+                             "s"
+                         },
                          supplied_arg_count,
-                         supplied_arg_count == 1u ? " was" : "s were"]);
+                         if supplied_arg_count == 1u {
+                             " was"
+                         } else {
+                             "s were"
+                         }]);
             // HACK: build an arguments list with dummy arguments to
             // check against
-            let dummy = {mode: ast::by_ref, ty: ty::mk_bot(fcx.ccx.tcx)};
+            let dummy = {mode: ast::expl(ast::by_ref),
+                         ty: ty::mk_bot(fcx.ccx.tcx)};
             arg_tys = vec::init_elt(supplied_arg_count, dummy);
         }
 
@@ -1679,14 +1668,14 @@ fn check_assignment(fcx: @fn_ctxt, _sp: span, lhs: @ast::expr,
                         rhs: @ast::expr, id: ast::node_id) -> bool {
         let t = next_ty_var(fcx);
         let bot = check_expr_with(fcx, lhs, t) | check_expr_with(fcx, rhs, t);
-        write::ty_only_fixup(fcx, id, ty::mk_nil(fcx.ccx.tcx));
+        write_ty(fcx.ccx.tcx, id, ty::mk_nil(fcx.ccx.tcx));
         ret bot;
     }
 
     // A generic function for checking call expressions
     fn check_call(fcx: @fn_ctxt, sp: span, f: @ast::expr, args: [@ast::expr])
         -> bool {
-        let args_opt_0: [option::t<@ast::expr>] = [];
+        let args_opt_0: [option<@ast::expr>] = [];
         for arg: @ast::expr in args {
             args_opt_0 += [some::<@ast::expr>(arg)];
         }
@@ -1715,7 +1704,7 @@ fn check_call_full(fcx: @fn_ctxt, sp: span, f: @ast::expr,
           }
           _ { fcx.ccx.tcx.sess.span_fatal(sp, "calling non-function"); }
         };
-        write::ty_only_fixup(fcx, id, rt_1);
+        write_ty(fcx.ccx.tcx, id, rt_1);
         ret bot;
     }
 
@@ -1732,7 +1721,7 @@ fn check_for(fcx: @fn_ctxt, local: @ast::local,
         demand::simple(fcx, local.span,
                        ty::node_id_to_type(fcx.ccx.tcx, local.node.id),
                        element_ty);
-        write::nil_ty(fcx.ccx.tcx, node_id);
+        write_nil(fcx.ccx.tcx, node_id);
         ret bot;
     }
 
@@ -1740,7 +1729,7 @@ fn check_for(fcx: @fn_ctxt, local: @ast::local,
     // A generic function for checking the then and else in an if
     // or if-check
     fn check_then_else(fcx: @fn_ctxt, thn: ast::blk,
-                       elsopt: option::t<@ast::expr>, id: ast::node_id,
+                       elsopt: option<@ast::expr>, id: ast::node_id,
                        _sp: span) -> bool {
         let (if_t, if_bot) =
             alt elsopt {
@@ -1761,11 +1750,11 @@ fn check_then_else(fcx: @fn_ctxt, thn: ast::blk,
                 (ty::mk_nil(fcx.ccx.tcx), false)
               }
             };
-        write::ty_only_fixup(fcx, id, if_t);
+        write_ty(fcx.ccx.tcx, id, if_t);
         ret if_bot;
     }
 
-    fn binop_method(op: ast::binop) -> option::t<str> {
+    fn binop_method(op: ast::binop) -> option<str> {
         alt op {
           ast::add | ast::subtract | ast::mul | ast::div | ast::rem |
           ast::bitxor | ast::bitand | ast::bitor | ast::lsl | ast::lsr |
@@ -1775,13 +1764,12 @@ fn binop_method(op: ast::binop) -> option::t<str> {
     }
     fn lookup_op_method(fcx: @fn_ctxt, op_ex: @ast::expr, self_t: ty::t,
                         opname: str,
-                        args: [option::t<@ast::expr>]) -> option::t<ty::t> {
+                        args: [option<@ast::expr>]) -> option<ty::t> {
         let isc = fcx.ccx.impl_map.get(op_ex.id);
         alt lookup_method(fcx, isc, opname, self_t, op_ex.span) {
           some({method_ty, n_tps: 0u, substs, origin}) {
             let callee_id = ast_util::op_expr_callee_id(op_ex);
-            write::ty_fixup(fcx, callee_id, {substs: some(substs),
-                                             ty: method_ty});
+            write_ty_substs(fcx.ccx.tcx, callee_id, method_ty, substs);
             check_call_or_bind(fcx, op_ex.span, method_ty, args);
             fcx.ccx.method_map.insert(op_ex.id, origin);
             some(ty::ty_fn_ret(fcx.ccx.tcx, method_ty))
@@ -1835,7 +1823,7 @@ fn check_user_unop(fcx: @fn_ctxt, op_str: str, mname: str,
     alt expr.node {
       ast::expr_lit(lit) {
         let typ = check_lit(fcx.ccx, lit);
-        write::ty_only_fixup(fcx, id, typ);
+        write_ty(tcx, id, typ);
       }
       ast::expr_binary(binop, lhs, rhs) {
         let lhs_t = next_ty_var(fcx);
@@ -1843,9 +1831,8 @@ fn check_user_unop(fcx: @fn_ctxt, op_str: str, mname: str,
 
         let rhs_bot = check_expr_with(fcx, rhs, lhs_t);
         if !ast_util::lazy_binop(binop) { bot |= rhs_bot; }
-
         let result = check_binop(fcx, expr, lhs_t, binop, rhs);
-        write::ty_only_fixup(fcx, id, result);
+        write_ty(tcx, id, result);
       }
       ast::expr_assign_op(op, lhs, rhs) {
         require_impure(tcx.sess, fcx.purity, expr.span);
@@ -1906,15 +1893,14 @@ fn check_user_unop(fcx: @fn_ctxt, op_str: str, mname: str,
             }
           }
         }
-        write::ty_only_fixup(fcx, id, oper_t);
+        write_ty(tcx, id, oper_t);
       }
       ast::expr_path(pth) {
         let defn = lookup_def(fcx, pth.span, id);
 
         let tpt = ty_param_bounds_and_ty_for_def(fcx, expr.span, defn);
         if ty::def_has_ty_params(defn) {
-            let path_tpot = instantiate_path(fcx, pth, tpt, expr.span);
-            write::ty_fixup(fcx, id, path_tpot);
+            instantiate_path(fcx, pth, tpt, expr.span, expr.id);
         } else {
             // The definition doesn't take type parameters. If the programmer
             // supplied some, that's an error
@@ -1923,7 +1909,7 @@ fn check_user_unop(fcx: @fn_ctxt, op_str: str, mname: str,
                                     "this kind of value does not \
                                      take type parameters");
             }
-            write::ty_only_fixup(fcx, id, tpt.ty);
+            write_ty(tcx, id, tpt.ty);
         }
       }
       ast::expr_mac(_) { tcx.sess.bug("unexpanded macro"); }
@@ -1933,10 +1919,10 @@ fn check_user_unop(fcx: @fn_ctxt, op_str: str, mname: str,
           none {/* do nothing */ }
           some(e) { check_expr_with(fcx, e, ty::mk_str(tcx)); }
         }
-        write::bot_ty(tcx, id);
+        write_bot(tcx, id);
       }
-      ast::expr_break { write::bot_ty(tcx, id); bot = true; }
-      ast::expr_cont { write::bot_ty(tcx, id); bot = true; }
+      ast::expr_break { write_bot(tcx, id); bot = true; }
+      ast::expr_cont { write_bot(tcx, id); bot = true; }
       ast::expr_ret(expr_opt) {
         bot = true;
         alt expr_opt {
@@ -1949,42 +1935,36 @@ fn check_user_unop(fcx: @fn_ctxt, op_str: str, mname: str,
           }
           some(e) { check_expr_with(fcx, e, fcx.ret_ty); }
         }
-        write::bot_ty(tcx, id);
+        write_bot(tcx, id);
       }
       ast::expr_be(e) {
         // FIXME: prove instead of assert
         assert (ast_util::is_call_expr(e));
         check_expr_with(fcx, e, fcx.ret_ty);
         bot = true;
-        write::nil_ty(tcx, id);
+        write_nil(tcx, id);
       }
       ast::expr_log(_, lv, e) {
         bot = check_expr_with(fcx, lv, ty::mk_mach_uint(tcx, ast::ty_u32));
         bot |= check_expr(fcx, e);
-        write::nil_ty(tcx, id);
+        write_nil(tcx, id);
       }
       ast::expr_check(_, e) {
         bot = check_pred_expr(fcx, e);
-        write::nil_ty(tcx, id);
+        write_nil(tcx, id);
       }
       ast::expr_if_check(cond, thn, elsopt) {
         bot =
             check_pred_expr(fcx, cond) |
                 check_then_else(fcx, thn, elsopt, id, expr.span);
       }
-      ast::expr_ternary(_, _, _) {
-        bot = check_expr(fcx, ast_util::ternary_to_if(expr));
-      }
       ast::expr_assert(e) {
         bot = check_expr_with(fcx, e, ty::mk_bool(tcx));
-        write::nil_ty(tcx, id);
+        write_nil(tcx, id);
       }
       ast::expr_copy(a) {
         bot = check_expr_with_unifier(fcx, a, unify, expected);
-        let tpot =
-            ty::node_id_to_ty_param_substs_opt_and_ty(tcx, a.id);
-        write::ty_fixup(fcx, id, tpot);
-
+        write_ty(tcx, id, ty::node_id_to_type(tcx, a.id));
       }
       ast::expr_move(lhs, rhs) {
         require_impure(tcx.sess, fcx.purity, expr.span);
@@ -2021,12 +2001,12 @@ fn check_user_unop(fcx: @fn_ctxt, op_str: str, mname: str,
       ast::expr_while(cond, body) {
         bot = check_expr_with(fcx, cond, ty::mk_bool(tcx));
         check_block_no_value(fcx, body);
-        write::ty_only_fixup(fcx, id, ty::mk_nil(tcx));
+        write_ty(tcx, id, ty::mk_nil(tcx));
       }
       ast::expr_do_while(body, cond) {
         bot = check_expr_with(fcx, cond, ty::mk_bool(tcx)) |
               check_block_no_value(fcx, body);
-        write::ty_only_fixup(fcx, id, block_ty(tcx, body));
+        write_ty(tcx, id, block_ty(tcx, body));
       }
       ast::expr_alt(expr, arms) {
         bot = check_expr(fcx, expr);
@@ -2054,7 +2034,7 @@ fn check_user_unop(fcx: @fn_ctxt, op_str: str, mname: str,
         }
         bot |= !arm_non_bot;
         if !arm_non_bot { result_ty = ty::mk_bot(tcx); }
-        write::ty_only_fixup(fcx, id, result_ty);
+        write_ty(tcx, id, result_ty);
       }
       ast::expr_fn(proto, decl, body, captures) {
         check_expr_fn_with_unifier(fcx, expr, proto, decl, body,
@@ -2065,18 +2045,13 @@ fn check_user_unop(fcx: @fn_ctxt, op_str: str, mname: str,
         // Take the prototype from the expected type, but default to block:
         let proto = alt ty::struct(tcx, expected) {
           ty::ty_fn({proto, _}) { proto }
-          _ {
-            tcx.sess.span_warn(expr.span, "unable to infer kind of closure, \
-                                           defaulting to block");
-            ast::proto_block
-          }
+          _ { ast::proto_box }
         };
         #debug("checking expr_fn_block %s expected=%s",
                expr_to_str(expr),
                ty_to_str(tcx, expected));
         check_expr_fn_with_unifier(fcx, expr, proto, decl, body,
                                    unify, expected);
-        write::ty_only_fixup(fcx, id, expected);
       }
       ast::expr_block(b) {
         // If this is an unchecked block, turn off purity-checking
@@ -2086,7 +2061,7 @@ fn check_user_unop(fcx: @fn_ctxt, op_str: str, mname: str,
               some(expr) { expr_ty(tcx, expr) }
               none { ty::mk_nil(tcx) }
             };
-        write::ty_only_fixup(fcx, id, typ);
+        write_ty(tcx, id, typ);
       }
       ast::expr_bind(f, args) {
         // Call the generic checker.
@@ -2133,7 +2108,7 @@ fn lower_bound_proto(proto: ast::proto) -> ast::proto {
         let ft = ty::mk_fn(tcx, {proto: lower_bound_proto(proto),
                                  inputs: out_args, output: rt,
                                  ret_style: cf, constraints: constrs});
-        write::ty_only_fixup(fcx, id, ft);
+        write_ty(tcx, id, ft);
       }
       ast::expr_call(f, args, _) {
         bot = check_call_full(fcx, expr.span, f, args, expr.id);
@@ -2169,13 +2144,13 @@ fn lower_bound_proto(proto: ast::proto) -> ast::proto {
             }
           }
         }
-        write::ty_only_fixup(fcx, id, t_1);
+        write_ty(tcx, id, t_1);
       }
       ast::expr_vec(args, mut) {
         let t: ty::t = next_ty_var(fcx);
         for e: @ast::expr in args { bot |= check_expr_with(fcx, e, t); }
         let typ = ty::mk_vec(tcx, {ty: t, mut: mut});
-        write::ty_only_fixup(fcx, id, typ);
+        write_ty(tcx, id, typ);
       }
       ast::expr_tup(elts) {
         let elt_ts = [];
@@ -2186,7 +2161,7 @@ fn lower_bound_proto(proto: ast::proto) -> ast::proto {
             elt_ts += [ety];
         }
         let typ = ty::mk_tup(tcx, elt_ts);
-        write::ty_only_fixup(fcx, id, typ);
+        write_ty(tcx, id, typ);
       }
       ast::expr_rec(fields, base) {
         alt base { none {/* no-op */ } some(b_0) { check_expr(fcx, b_0); } }
@@ -2205,7 +2180,7 @@ fn lower_bound_proto(proto: ast::proto) -> ast::proto {
           none {
             fn get_node(f: spanned<field>) -> field { f.node }
             let typ = ty::mk_rec(tcx, vec::map(fields_t, get_node));
-            write::ty_only_fixup(fcx, id, typ);
+            write_ty(tcx, id, typ);
           }
           some(bexpr) {
             bot |= check_expr(fcx, bexpr);
@@ -2218,7 +2193,7 @@ fn get_node(f: spanned<field>) -> field { f.node }
                                     "record update has non-record base");
               }
             }
-            write::ty_only_fixup(fcx, id, bexpr_t);
+            write_ty(tcx, id, bexpr_t);
             for f: spanned<ty::field> in fields_t {
                 let found = false;
                 for bf: ty::field in base_fields {
@@ -2251,7 +2226,7 @@ fn get_node(f: spanned<field>) -> field { f.node }
                                       "can't provide type parameters \
                                        to a field access");
                 }
-                write::ty_only_fixup(fcx, id, fields[ix].mt.ty);
+                write_ty(tcx, id, fields[ix].mt.ty);
                 handled = true;
               }
               _ {}
@@ -2282,13 +2257,13 @@ fn get_node(f: spanned<field>) -> field { f.node }
                             i += 1u;
                         }
                     }
-                    write::ty_fixup(fcx, id, {substs: some(substs), ty: fty});
+                    write_ty_substs(fcx.ccx.tcx, id, fty, substs);
                 } else if n_tys > 0u {
                     tcx.sess.span_fatal(expr.span,
                                         "this method does not take type \
                                          parameters");
                 } else {
-                    write::ty_only_fixup(fcx, id, fty);
+                    write_ty(tcx, id, fty);
                 }
                 fcx.ccx.method_map.insert(id, origin);
               }
@@ -2299,7 +2274,7 @@ fn get_node(f: spanned<field>) -> field { f.node }
                                field, ty_to_str(tcx, t_err)];
                 tcx.sess.span_err(expr.span, msg);
                 // NB: Adding a bogus type to allow typechecking to continue
-                write::ty_only_fixup(fcx, id, ty::mk_nil(tcx));
+                write_ty(tcx, id, ty::mk_nil(tcx));
               }
             }
         }
@@ -2320,19 +2295,19 @@ fn require_integral(fcx: @fn_ctxt, sp: span, t: ty::t) {
         alt structure_of(fcx, expr.span, base_t) {
           ty::ty_vec(mt) {
             require_integral(fcx, idx.span, idx_t);
-            write::ty_only_fixup(fcx, id, mt.ty);
+            write_ty(tcx, id, mt.ty);
           }
           ty::ty_str {
             require_integral(fcx, idx.span, idx_t);
             let typ = ty::mk_mach_uint(tcx, ast::ty_u8);
-            write::ty_only_fixup(fcx, id, typ);
+            write_ty(tcx, id, typ);
           }
           _ {
             let resolved = structurally_resolved_type(fcx, expr.span,
                                                       raw_base_t);
             alt lookup_op_method(fcx, expr, resolved, "[]",
                                  [some(idx)]) {
-              some(ret_ty) { write::ty_only_fixup(fcx, id, ret_ty); }
+              some(ret_ty) { write_ty(tcx, id, ret_ty); }
               _ {
                 tcx.sess.span_fatal(
                     expr.span, "cannot index a value of type `" +
@@ -2344,7 +2319,7 @@ fn require_integral(fcx: @fn_ctxt, sp: span, t: ty::t) {
       }
       _ { tcx.sess.unimpl("expr type in typeck::check_expr"); }
     }
-    if bot { write::ty_only_fixup(fcx, expr.id, ty::mk_bot(tcx)); }
+    if bot { write_ty(tcx, expr.id, ty::mk_bot(tcx)); }
 
     unify(fcx, expr.span, expected, expr_ty(tcx, expr));
     ret bot;
@@ -2366,7 +2341,7 @@ fn bind_params(fcx: @fn_ctxt, tp: ty::t, count: uint)
     {vars: vars, ty: ty::substitute_type_params(fcx.ccx.tcx, vars, tp)}
 }
 
-fn get_self_info(ccx: @crate_ctxt) -> option::t<self_info> {
+fn get_self_info(ccx: @crate_ctxt) -> option<self_info> {
     ret vec::last(ccx.self_infos);
 }
 
@@ -2382,7 +2357,7 @@ fn check_decl_local(fcx: @fn_ctxt, local: @ast::local) -> bool {
     alt fcx.locals.find(local.node.id) {
       some(i) {
         let t = ty::mk_var(fcx.ccx.tcx, i);
-        write::ty_only_fixup(fcx, local.node.id, t);
+        write_ty(fcx.ccx.tcx, local.node.id, t);
         alt local.node.init {
           some(init) {
             bot = check_decl_initializer(fcx, local.node.id, init);
@@ -2392,6 +2367,8 @@ fn check_decl_local(fcx: @fn_ctxt, local: @ast::local) -> bool {
         let id_map = pat_util::pat_id_map(fcx.ccx.tcx, local.node.pat);
         check_pat(fcx, id_map, local.node.pat, t);
       }
+      _ { fcx.ccx.tcx.sess.span_bug(local.span, "Undocumented invariant \
+            in check_decl_local");  }
     }
     ret bot;
 }
@@ -2418,14 +2395,14 @@ fn check_stmt(fcx: @fn_ctxt, stmt: @ast::stmt) -> bool {
         bot = check_expr(fcx, expr);
       }
     }
-    write::nil_ty(fcx.ccx.tcx, node_id);
+    write_nil(fcx.ccx.tcx, node_id);
     ret bot;
 }
 
 fn check_block_no_value(fcx: @fn_ctxt, blk: ast::blk) -> bool {
     let bot = check_block(fcx, blk);
     if !bot {
-        let blkty = ty::node_id_to_monotype(fcx.ccx.tcx, blk.node.id);
+        let blkty = ty::node_id_to_type(fcx.ccx.tcx, blk.node.id);
         let nilty = ty::mk_nil(fcx.ccx.tcx);
         demand::simple(fcx, blk.span, nilty, blkty);
     }
@@ -2455,18 +2432,18 @@ fn check_block(fcx0: @fn_ctxt, blk: ast::blk) -> bool {
         bot |= check_stmt(fcx, s);
     }
     alt blk.node.expr {
-      none { write::nil_ty(fcx.ccx.tcx, blk.node.id); }
+      none { write_nil(fcx.ccx.tcx, blk.node.id); }
       some(e) {
         if bot && !warned {
             fcx.ccx.tcx.sess.span_warn(e.span, "unreachable expression");
         }
         bot |= check_expr(fcx, e);
         let ety = expr_ty(fcx.ccx.tcx, e);
-        write::ty_only_fixup(fcx, blk.node.id, ety);
+        write_ty(fcx.ccx.tcx, blk.node.id, ety);
       }
     }
     if bot {
-        write::ty_only_fixup(fcx, blk.node.id, ty::mk_bot(fcx.ccx.tcx));
+        write_ty(fcx.ccx.tcx, blk.node.id, ty::mk_bot(fcx.ccx.tcx));
     }
     ret bot;
 }
@@ -2475,7 +2452,6 @@ fn check_const(ccx: @crate_ctxt, _sp: span, e: @ast::expr, id: ast::node_id) {
     // FIXME: this is kinda a kludge; we manufacture a fake function context
     // and statement context for checking the initializer expression.
     let rty = node_id_to_type(ccx.tcx, id);
-    let fixups: [ast::node_id] = [];
     let fcx: @fn_ctxt =
         @{ret_ty: rty,
           purity: ast::pure_fn,
@@ -2483,7 +2459,6 @@ fn check_const(ccx: @crate_ctxt, _sp: span, e: @ast::expr, id: ast::node_id) {
           var_bindings: ty::unify::mk_var_bindings(),
           locals: new_int_hash::<int>(),
           next_var_id: @mutable 0,
-          mutable fixups: fixups,
           ccx: ccx};
     check_expr(fcx, e);
     let cty = expr_ty(fcx.ccx.tcx, e);
@@ -2496,7 +2471,6 @@ fn check_enum_variants(ccx: @crate_ctxt, sp: span, vs: [ast::variant],
     // FIXME: this is kinda a kludge; we manufacture a fake function context
     // and statement context for checking the initializer expression.
     let rty = node_id_to_type(ccx.tcx, id);
-    let fixups: [ast::node_id] = [];
     let fcx: @fn_ctxt =
         @{ret_ty: rty,
           purity: ast::pure_fn,
@@ -2504,7 +2478,6 @@ fn check_enum_variants(ccx: @crate_ctxt, sp: span, vs: [ast::variant],
           var_bindings: ty::unify::mk_var_bindings(),
           locals: new_int_hash::<int>(),
           next_var_id: @mutable 0,
-          mutable fixups: fixups,
           ccx: ccx};
     let disr_vals: [int] = [];
     let disr_val = 0;
@@ -2668,7 +2641,7 @@ fn check_fn(ccx: @crate_ctxt,
             decl: ast::fn_decl,
             body: ast::blk,
             id: ast::node_id,
-            old_fcx: option::t<@fn_ctxt>) {
+            old_fcx: option<@fn_ctxt>) {
     // If old_fcx is some(...), this is a block fn { |x| ... }.
     // In that case, the purity is inherited from the context.
     let purity = alt old_fcx {
@@ -2677,7 +2650,6 @@ fn check_fn(ccx: @crate_ctxt,
     };
 
     let gather_result = gather_locals(ccx, decl, body, id, old_fcx);
-    let fixups: [ast::node_id] = [];
     let fcx: @fn_ctxt =
         @{ret_ty: ty::ty_fn_ret(ccx.tcx, ty::node_id_to_type(ccx.tcx, id)),
           purity: purity,
@@ -2685,7 +2657,6 @@ fn check_fn(ccx: @crate_ctxt,
           var_bindings: gather_result.var_bindings,
           locals: gather_result.locals,
           next_var_id: gather_result.next_var_id,
-          mutable fixups: fixups,
           ccx: ccx};
 
     check_constraints(fcx, decl.constraints, decl.inputs);
@@ -2704,7 +2675,7 @@ fn check_fn(ccx: @crate_ctxt,
     let args = ty::ty_fn_args(ccx.tcx, ty::node_id_to_type(ccx.tcx, id));
     let i = 0u;
     for arg: ty::arg in args {
-        write::ty_only_fixup(fcx, decl.inputs[i].id, arg.ty);
+        write_ty(ccx.tcx, decl.inputs[i].id, arg.ty);
         i += 1u;
     }
 
@@ -2754,8 +2725,8 @@ fn arg_is_argv_ty(tcx: ty::ctxt, a: ty::arg) -> bool {
     }
 }
 
-fn check_main_fn_ty(tcx: ty::ctxt, main_id: ast::node_id) {
-    let main_t = ty::node_id_to_monotype(tcx, main_id);
+fn check_main_fn_ty(tcx: ty::ctxt, main_id: ast::node_id, main_span: span) {
+    let main_t = ty::node_id_to_type(tcx, main_id);
     alt ty::struct(tcx, main_t) {
       ty::ty_fn({proto: ast::proto_bare, inputs, output,
                  ret_style: ast::return_val, constraints}) {
@@ -2765,15 +2736,13 @@ fn check_main_fn_ty(tcx: ty::ctxt, main_id: ast::node_id) {
         ok &= num_args == 0u || num_args == 1u &&
               arg_is_argv_ty(tcx, inputs[0]);
         if !ok {
-            let span = ast_map::node_span(tcx.items.get(main_id));
-            tcx.sess.span_err(span,
+            tcx.sess.span_err(main_span,
                               "wrong type in main function: found `" +
                                   ty_to_str(tcx, main_t) + "`");
         }
       }
       _ {
-        let span = ast_map::node_span(tcx.items.get(main_id));
-        tcx.sess.span_bug(span,
+        tcx.sess.span_bug(main_span,
                           "main has a non-function type: found `" +
                               ty_to_str(tcx, main_t) + "`");
       }
@@ -2783,7 +2752,7 @@ fn check_main_fn_ty(tcx: ty::ctxt, main_id: ast::node_id) {
 fn check_for_main_fn(tcx: ty::ctxt, crate: @ast::crate) {
     if !tcx.sess.building_library {
         alt tcx.sess.main_fn {
-          some(id) { check_main_fn_ty(tcx, id); }
+          some((id, sp)) { check_main_fn_ty(tcx, id, sp); }
           none { tcx.sess.span_err(crate.span, "main function not found"); }
         }
     }
@@ -2822,6 +2791,8 @@ fn lookup_dict(fcx: @fn_ctxt, isc: resolve::iscopes, sp: span,
         let tcx = fcx.ccx.tcx;
         let (iface_id, iface_tps) = alt ty::struct(tcx, iface_ty) {
             ty::ty_iface(did, tps) { (did, tps) }
+            _ { tcx.sess.span_bug(sp, "Undocumented invariant in lookup\
+                 _dict"); }
         };
         let ty = fixup_ty(fcx, sp, ty);
         alt ty::struct(tcx, ty) {
@@ -2834,6 +2805,8 @@ fn lookup_dict(fcx: @fn_ctxt, isc: resolve::iscopes, sp: span,
                       ty::ty_iface(idid, _) {
                         if iface_id == idid { ret dict_param(n, n_bound); }
                       }
+                      _ { tcx.sess.span_bug(sp, "Undocumented invariant in \
+                           lookup_dict"); }
                     }
                     n_bound += 1u;
                   }
@@ -2853,6 +2826,9 @@ fn lookup_dict(fcx: @fn_ctxt, isc: resolve::iscopes, sp: span,
                       some(ity) {
                         alt ty::struct(tcx, ity) {
                           ty::ty_iface(id, _) { id == iface_id }
+                          // Bleah, abstract this
+                          _ { tcx.sess.span_bug(sp, "Undocumented invariant \
+                               in lookup_dict"); }
                         }
                       }
                       _ { false }
@@ -2919,6 +2895,10 @@ fn connect_iface_tps(fcx: @fn_ctxt, sp: span, impl_tys: [ty::t],
             vec::iter2(tps, iface_tys,
                        {|a, b| demand::simple(fcx, sp, a, b);});
           }
+          _ {
+              tcx.sess.span_bug(sp, "Undocumented invariant in \
+                 connect_iface_tps");
+          }
         }
     }
 
@@ -2926,9 +2906,7 @@ fn resolve_expr(ex: @ast::expr, &&fcx: @fn_ctxt, v: visit::vt<@fn_ctxt>) {
         let cx = fcx.ccx;
         alt ex.node {
           ast::expr_path(_) {
-            let substs = ty::node_id_to_ty_param_substs_opt_and_ty(
-                cx.tcx, ex.id);
-            alt substs.substs {
+            alt cx.tcx.node_type_substs.find(ex.id) {
               some(ts) {
                 let did = ast_util::def_id_of_def(cx.tcx.def_map.get(ex.id));
                 let item_ty = ty::lookup_item_type(cx.tcx, did);
@@ -2963,38 +2941,9 @@ fn resolve_expr(ex: @ast::expr, &&fcx: @fn_ctxt, v: visit::vt<@fn_ctxt>) {
             }
           }
           ast::expr_cast(src, _) {
-            // Ifaces that refer to a self type can not be cast to -- callers
-            // wouldn't know what self refers to.
-            fn type_refers_to_self(tcx: ty::ctxt, t: ty::t, s_param: uint)
-                -> bool {
-                let found = false;
-                if ty::type_contains_params(tcx, t) {
-                    ty::walk_ty(tcx, t) {|t|
-                        alt ty::struct(tcx, t) {
-                          ty::ty_param(n, _) if n == s_param { found = true; }
-                          _ {}
-                        }
-                    }
-                }
-                found
-            }
-            fn method_refers_to_self(tcx: ty::ctxt, m: ty::method,
-                                     s_param: uint) -> bool {
-                vec::any(m.fty.inputs, {|in|
-                    type_refers_to_self(tcx, in.ty, s_param)
-                }) || type_refers_to_self(tcx, m.fty.output, s_param)
-            }
             let target_ty = expr_ty(cx.tcx, ex);
             alt ty::struct(cx.tcx, target_ty) {
-              ty::ty_iface(id, tps) {
-                for m in *ty::iface_methods(cx.tcx, id) {
-                    if method_refers_to_self(cx.tcx, m, vec::len(tps)) {
-                        cx.tcx.sess.span_err(
-                            ex.span, "can not cast to an iface type that \
-                                      refers to `self` " + m.ident);
-                        break;
-                    }
-                }
+              ty::ty_iface(_, _) {
                 let impls = cx.impl_map.get(ex.id);
                 let dict = lookup_dict(fcx, impls, ex.span,
                                        expr_ty(cx.tcx, src), target_ty);
index f655054ab1feda85a446424c58d52655ef40ecbb..bfb26382a84d0b4cca5dd6b7243356b031976ba5 100644 (file)
@@ -39,7 +39,6 @@ mod middle {
     mod kind;
     mod freevars;
     mod shape;
-    mod gc;
     mod debuginfo;
     mod capture;
     mod pat_util;
@@ -75,6 +74,8 @@ mod syntax {
     mod ext {
         mod base;
         mod expand;
+        mod qquote;
+        mod build;
 
         mod fmt;
         mod env;
index 4ff96c17daadd26b9780b0189a89ebffb55187f8..8db4573c2b43c7a62826647f5f5ff9b4e030949e 100644 (file)
@@ -8,7 +8,7 @@
 type ident = str;
 
 // Functions may or may not have names.
-type fn_ident = option::t<ident>;
+type fn_ident = option<ident>;
 
 // FIXME: with typestate constraint, could say
 // idents and types are the same length, and are
@@ -45,7 +45,6 @@ enum def {
     def_ty_param(def_id, uint),
     def_binding(def_id),
     def_use(def_id),
-    def_native_ty(def_id),
     def_upvar(def_id, @def, node_id), // node_id == expr_fn or expr_fn_block
 }
 
@@ -87,7 +86,7 @@ enum meta_item_ {
 
 type blk = spanned<blk_>;
 
-type blk_ = {view_items: [@view_item], stmts: [@stmt], expr: option::t<@expr>,
+type blk_ = {view_items: [@view_item], stmts: [@stmt], expr: option<@expr>,
              id: node_id, rules: blk_check_mode};
 
 type pat = {id: node_id, node: pat_, span: span};
@@ -106,7 +105,7 @@ enum pat_ {
     // After the resolution phase, code should never pattern-
     // match on a pat directly! Always call pat_util::normalize_pat --
     // it turns any pat_idents that refer to nullary enums into pat_enums.
-    pat_ident(@path, option::t<@pat>),
+    pat_ident(@path, option<@pat>),
     pat_enum(@path, [@pat]),
     pat_rec([field_pat], bool),
     pat_tup([@pat]),
@@ -161,7 +160,17 @@ enum unop {
     deref, not, neg,
 }
 
-enum mode { by_ref, by_val, by_mut_ref, by_move, by_copy, mode_infer, }
+// Generally, after typeck you can get the inferred value
+// using ty::resolved_T(...).
+enum inferable<T> {
+    expl(T), infer(node_id)
+}
+
+// "resolved" mode: the real modes.
+enum rmode { by_ref, by_val, by_mut_ref, by_move, by_copy }
+
+// inferable mode.
+type mode = inferable<rmode>;
 
 type stmt = spanned<stmt_>;
 
@@ -180,7 +189,7 @@ enum init_op { init_assign, init_move, }
 type initializer = {op: init_op, expr: @expr};
 
 type local_ =  // FIXME: should really be a refinement on pat
-    {ty: @ty, pat: @pat, init: option::t<initializer>, id: node_id};
+    {ty: @ty, pat: @pat, init: option<initializer>, id: node_id};
 
 type local = spanned<local_>;
 
@@ -190,7 +199,7 @@ enum let_style { let_copy, let_ref, }
 
 enum decl_ { decl_local([(let_style, @local)]), decl_item(@item), }
 
-type arm = {pats: [@pat], guard: option::t<@expr>, body: blk};
+type arm = {pats: [@pat], guard: option<@expr>, body: blk};
 
 type field_ = {mut: mutability, ident: ident, expr: @expr};
 
@@ -204,16 +213,15 @@ enum expr_check_mode { claimed_expr, checked_expr, }
 
 enum expr_ {
     expr_vec([@expr], mutability),
-    expr_rec([field], option::t<@expr>),
+    expr_rec([field], option<@expr>),
     expr_call(@expr, [@expr], bool),
     expr_tup([@expr]),
-    expr_bind(@expr, [option::t<@expr>]),
+    expr_bind(@expr, [option<@expr>]),
     expr_binary(binop, @expr, @expr),
     expr_unary(unop, @expr),
     expr_lit(@lit),
     expr_cast(@expr, @ty),
-    expr_if(@expr, blk, option::t<@expr>),
-    expr_ternary(@expr, @expr, @expr),
+    expr_if(@expr, blk, option<@expr>),
     expr_while(@expr, blk),
     expr_for(@local, @expr, blk),
     expr_do_while(blk, @expr),
@@ -234,10 +242,10 @@ enum expr_ {
     expr_field(@expr, ident, [@ty]),
     expr_index(@expr, @expr),
     expr_path(@path),
-    expr_fail(option::t<@expr>),
+    expr_fail(option<@expr>),
     expr_break,
     expr_cont,
-    expr_ret(option::t<@expr>),
+    expr_ret(option<@expr>),
     expr_be(@expr),
     expr_log(int, @expr, @expr),
 
@@ -249,7 +257,7 @@ enum expr_ {
 
     /* FIXME Would be nice if expr_check desugared
        to expr_if_check. */
-    expr_if_check(@expr, blk, option::t<@expr>),
+    expr_if_check(@expr, blk, option<@expr>),
     expr_mac(mac),
 }
 
@@ -274,11 +282,20 @@ enum blk_sort {
 
 type mac = spanned<mac_>;
 
+type mac_arg = option::t<@expr>;
+
+type mac_body_ = {span: span};
+type mac_body = option::t<mac_body_>;
+
 enum mac_ {
-    mac_invoc(@path, @expr, option::t<str>),
+    mac_invoc(@path, mac_arg, mac_body),
     mac_embed_type(@ty),
     mac_embed_block(blk),
     mac_ellipsis,
+    // the span is used by the quoter/anti-quoter ...
+    mac_qq(span /* span of expr */, @expr), // quasi-quote
+    mac_aq(span /* span of quote */, @expr), // anti-quote
+    mac_var(uint)
 }
 
 type lit = spanned<lit_>;
@@ -300,7 +317,8 @@ enum lit_ {
 
 type ty_field = spanned<ty_field_>;
 
-type ty_method = {ident: ident, decl: fn_decl, tps: [ty_param], span: span};
+type ty_method = {ident: ident, attrs: [attribute],
+                  decl: fn_decl, tps: [ty_param], span: span};
 
 enum int_ty { ty_i, ty_char, ty_i8, ty_i16, ty_i32, ty_i64, }
 
@@ -328,14 +346,10 @@ enum ty_ {
     ty_uniq(mt),
     ty_vec(mt),
     ty_ptr(mt),
-    ty_task,
-    ty_port(@ty),
-    ty_chan(@ty),
     ty_rec([ty_field]),
     ty_fn(proto, fn_decl),
     ty_tup([@ty]),
     ty_path(@path, node_id),
-    ty_type,
     ty_constr(@ty, [@ty_constr]),
     ty_mac(mac),
     // ty_infer means the type should be inferred instead of it having been
@@ -400,7 +414,8 @@ enum ret_style {
     return_val, // everything else
 }
 
-type method = {ident: ident, tps: [ty_param], decl: fn_decl, body: blk,
+type method = {ident: ident, attrs: [attribute],
+               tps: [ty_param], decl: fn_decl, body: blk,
                id: node_id, span: span};
 
 type _mod = {view_items: [@view_item], items: [@item]};
@@ -418,7 +433,7 @@ enum native_abi {
 type variant_arg = {ty: @ty, id: node_id};
 
 type variant_ = {name: ident, attrs: [attribute], args: [variant_arg],
-                 id: node_id, disr_expr: option::t<@expr>};
+                 id: node_id, disr_expr: option<@expr>};
 
 type variant = spanned<variant_>;
 
@@ -467,11 +482,29 @@ enum item_ {
     item_enum([variant], [ty_param]),
     item_res(fn_decl /* dtor */, [ty_param], blk,
              node_id /* dtor id */, node_id /* ctor id */),
+    item_class([ty_param], /* ty params for class */
+               [@class_item], /* methods, etc. */
+                             /* (not including ctor) */
+               fn_decl, /* ctor decl */
+               blk /* ctor body */
+               ),
     item_iface([ty_param], [ty_method]),
-    item_impl([ty_param], option::t<@ty> /* iface */,
+    item_impl([ty_param], option<@ty> /* iface */,
               @ty /* self */, [@method]),
 }
 
+type class_item_ = {privacy: privacy, decl: @class_member};
+type class_item = spanned<class_item_>;
+
+enum class_member {
+    instance_var(ident, @ty, class_mutability, node_id),
+    class_method(@item)
+}
+
+enum class_mutability { class_mutable, class_immutable }
+
+enum privacy { priv, pub }
+
 type native_item =
     {ident: ident,
      attrs: [attribute],
@@ -480,7 +513,6 @@ enum item_ {
      span: span};
 
 enum native_item_ {
-    native_item_ty,
     native_item_fn(fn_decl, [ty_param]),
 }
 
index 65c117cfa6bf5ea9699ebe04ead4cb6f389e8593..bdfaee5d4c2d3e77fdb0aa2e91a693b00be4bf7c 100644 (file)
@@ -19,8 +19,10 @@ fn path_name_i(idents: [ident]) -> str { str::connect(idents, "::") }
 
 fn local_def(id: node_id) -> def_id { ret {crate: local_crate, node: id}; }
 
-fn variant_def_ids(d: def) -> {tg: def_id, var: def_id} {
-    alt d { def_variant(enum_id, var_id) { ret {tg: enum_id, var: var_id}; } }
+fn variant_def_ids(d: def) -> {enm: def_id, var: def_id} {
+    alt d { def_variant(enum_id, var_id) {
+            ret {enm: enum_id, var: var_id}; }
+        _ { fail "non-variant in variant_def_ids"; } }
 }
 
 fn def_id_of_def(d: def) -> def_id {
@@ -28,8 +30,7 @@ fn def_id_of_def(d: def) -> def_id {
       def_fn(id, _) | def_self(id) | def_mod(id) |
       def_native_mod(id) | def_const(id) | def_arg(id, _) | def_local(id, _) |
       def_variant(_, id) | def_ty(id) | def_ty_param(id, _) |
-      def_binding(id) | def_use(id) | def_native_ty(id) |
-      def_upvar(id, _, _) { id }
+      def_binding(id) | def_use(id) | def_upvar(id, _, _) { id }
     }
 }
 
@@ -77,6 +78,7 @@ fn is_path(e: @expr) -> bool {
 
 fn int_ty_to_str(t: int_ty) -> str {
     alt t {
+      ty_char { "u8" } // ???
       ty_i { "" } ty_i8 { "i8" } ty_i16 { "i16" }
       ty_i32 { "i32" } ty_i64 { "i64" }
     }
@@ -86,7 +88,7 @@ fn int_ty_max(t: int_ty) -> u64 {
     alt t {
       ty_i8 { 0x80u64 }
       ty_i16 { 0x800u64 }
-      ty_char | ty_i32 { 0x80000000u64 }
+      ty_i | ty_char | ty_i32 { 0x80000000u64 } // actually ni about ty_i
       ty_i64 { 0x8000000000000000u64 }
     }
 }
@@ -102,7 +104,7 @@ fn uint_ty_max(t: uint_ty) -> u64 {
     alt t {
       ty_u8 { 0xffu64 }
       ty_u16 { 0xffffu64 }
-      ty_u32 { 0xffffffffu64 }
+      ty_u | ty_u32 { 0xffffffffu64 } // actually ni about ty_u
       ty_u64 { 0xffffffffffffffffu64 }
     }
 }
@@ -200,28 +202,11 @@ fn block_from_expr(e: @expr) -> blk {
     ret {node: blk_, span: e.span};
 }
 
-fn default_block(stmts1: [@stmt], expr1: option::t<@expr>, id1: node_id) ->
+fn default_block(stmts1: [@stmt], expr1: option<@expr>, id1: node_id) ->
    blk_ {
     {view_items: [], stmts: stmts1, expr: expr1, id: id1, rules: default_blk}
 }
 
-// This is a convenience function to transfor ternary expressions to if
-// expressions so that they can be treated the same
-fn ternary_to_if(e: @expr) -> @expr {
-    alt e.node {
-      expr_ternary(cond, then, els) {
-        let then_blk = block_from_expr(then);
-        let els_blk = block_from_expr(els);
-        let els_expr =
-            @{id: els.id, node: expr_block(els_blk), span: els.span};
-        ret @{id: e.id,
-              node: expr_if(cond, then_blk, option::some(els_expr)),
-              span: e.span};
-      }
-      _ { fail; }
-    }
-}
-
 // FIXME this doesn't handle big integer/float literals correctly (nor does
 // the rest of our literal handling)
 enum const_val {
@@ -240,12 +225,14 @@ fn fromb(b: bool) -> const_val { const_int(b as i64) }
           const_float(f) { const_float(-f) }
           const_int(i) { const_int(-i) }
           const_uint(i) { const_uint(-i) }
+          _ { fail "eval_const_expr: bad neg argument"; }
         }
       }
       expr_unary(not, inner) {
         alt eval_const_expr(inner) {
           const_int(i) { const_int(!i) }
           const_uint(i) { const_uint(!i) }
+          _ { fail "eval_const_expr: bad not argument"; }
         }
       }
       expr_binary(op, a, b) {
@@ -257,6 +244,7 @@ fn fromb(b: bool) -> const_val { const_int(b as i64) }
               rem { const_float(a % b) } eq { fromb(a == b) }
               lt { fromb(a < b) } le { fromb(a <= b) } ne { fromb(a != b) }
               ge { fromb(a >= b) } gt { fromb(a > b) }
+              _ { fail "eval_const_expr: can't apply this binop to floats"; }
             }
           }
           (const_int(a), const_int(b)) {
@@ -270,6 +258,7 @@ fn fromb(b: bool) -> const_val { const_int(b as i64) }
               eq { fromb(a == b) } lt { fromb(a < b) }
               le { fromb(a <= b) } ne { fromb(a != b) }
               ge { fromb(a >= b) } gt { fromb(a > b) }
+              _ { fail "eval_const_expr: can't apply this binop to ints"; }
             }
           }
           (const_uint(a), const_uint(b)) {
@@ -284,11 +273,17 @@ fn fromb(b: bool) -> const_val { const_int(b as i64) }
               eq { fromb(a == b) } lt { fromb(a < b) }
               le { fromb(a <= b) } ne { fromb(a != b) }
               ge { fromb(a >= b) } gt { fromb(a > b) }
+              _ { fail "eval_const_expr: can't apply this binop to uints"; }
             }
           }
+          _ { fail "eval_constr_expr: bad binary arguments"; }
         }
       }
       expr_lit(lit) { lit_to_const(lit) }
+      // Precondition?
+      _ {
+          fail "eval_const_expr: non-constant expression";
+      }
     }
 }
 
@@ -305,10 +300,45 @@ fn lit_to_const(lit: @lit) -> const_val {
 
 fn compare_const_vals(a: const_val, b: const_val) -> int {
   alt (a, b) {
-    (const_int(a), const_int(b)) { a == b ? 0 : a < b ? -1 : 1 }
-    (const_uint(a), const_uint(b)) { a == b ? 0 : a < b ? -1 : 1 }
-    (const_float(a), const_float(b)) { a == b ? 0 : a < b ? -1 : 1 }
-    (const_str(a), const_str(b)) { a == b ? 0 : a < b ? -1 : 1 }
+    (const_int(a), const_int(b)) {
+        if a == b {
+            0
+        } else if a < b {
+            -1
+        } else {
+            1
+        }
+    }
+    (const_uint(a), const_uint(b)) {
+        if a == b {
+            0
+        } else if a < b {
+            -1
+        } else {
+            1
+        }
+    }
+    (const_float(a), const_float(b)) {
+        if a == b {
+            0
+        } else if a < b {
+            -1
+        } else {
+            1
+        }
+    }
+    (const_str(a), const_str(b)) {
+        if a == b {
+            0
+        } else if a < b {
+            -1
+        } else {
+            1
+        }
+    }
+    _ {
+        fail "compare_const_vals: ill-typed comparison";
+    }
   }
 }
 
@@ -326,6 +356,17 @@ fn ident_to_path(s: span, i: ident) -> @path {
     @respan(s, {global: false, idents: [i], types: []})
 }
 
+pure fn is_unguarded(&&a: arm) -> bool {
+    alt a.guard {
+      none { true }
+      _    { false }
+    }
+}
+
+pure fn unguarded_pat(a: arm) -> option<[@pat]> {
+    if is_unguarded(a) { some(a.pats) } else { none }
+}
+
 // Provides an extra node_id to hang callee information on, in case the
 // operator is deferred to a user-supplied method. The parser is responsible
 // for reserving this id.
index 3c7d036d1f2ddb373017ab4763cf0f7ded4bc49c..74b9bb091b42288e457eb4560f74a19c4c59bd95 100644 (file)
  * with single-word things, rather than passing records all over the
  * compiler.
  */
+
+type file_substr_ = {lo: uint, hi: uint, col: uint, line: uint};
+type file_substr = option<file_substr_>;
+
 type filemap =
-    @{name: filename, src: @str,
+    @{name: filename, substr: file_substr, src: @str,
       start_pos: file_pos, mutable lines: [file_pos]};
 
 type codemap = @{mutable files: [filemap]};
 
-type loc = {filename: filename, line: uint, col: uint};
+type loc = {file: filemap, line: uint, col: uint};
 
-fn new_codemap() -> codemap { ret @{mutable files: []}; }
+fn new_codemap() -> codemap { @{mutable files: [] } }
 
-fn new_filemap(filename: filename, src: @str,
-               start_pos_ch: uint, start_pos_byte: uint)
+fn new_filemap_w_substr(filename: filename, substr: file_substr,
+                        src: @str,
+                        start_pos_ch: uint, start_pos_byte: uint)
    -> filemap {
-    ret @{name: filename, src: src,
+    ret @{name: filename, substr: substr, src: src,
           start_pos: {ch: start_pos_ch, byte: start_pos_byte},
           mutable lines: [{ch: start_pos_ch, byte: start_pos_byte}]};
 }
 
+fn new_filemap(filename: filename, src: @str,
+               start_pos_ch: uint, start_pos_byte: uint)
+    -> filemap {
+    ret new_filemap_w_substr(filename, none, src,
+                             start_pos_ch, start_pos_byte);
+}
+
+fn get_substr_info(cm: codemap, lo: uint, hi: uint)
+    -> (filename, file_substr_)
+{
+    let pos = lookup_char_pos(cm, lo);
+    let name = #fmt("<%s:%u:%u>", pos.file.name, pos.line, pos.col);
+    ret (name, {lo: lo, hi: hi, col: pos.col, line: pos.line});
+}
+
 fn next_line(file: filemap, chpos: uint, byte_pos: uint) {
     file.lines += [{ch: chpos, byte: byte_pos}];
 }
 
 type lookup_fn = fn@(file_pos) -> uint;
 
-fn lookup_pos(map: codemap, pos: uint, lookup: lookup_fn) -> loc {
+fn lookup_line(map: codemap, pos: uint, lookup: lookup_fn)
+    -> {fm: filemap, line: uint}
+{
     let len = vec::len(map.files);
     let a = 0u;
     let b = len;
@@ -43,7 +65,7 @@ fn lookup_pos(map: codemap, pos: uint, lookup: lookup_fn) -> loc {
         if lookup(map.files[m].start_pos) > pos { b = m; } else { a = m; }
     }
     if (a >= len) {
-        ret { filename: "-", line: 0u, col: 0u };
+        fail #fmt("position %u does not resolve to a source location", pos)
     }
     let f = map.files[a];
     a = 0u;
@@ -52,7 +74,12 @@ fn lookup_pos(map: codemap, pos: uint, lookup: lookup_fn) -> loc {
         let m = (a + b) / 2u;
         if lookup(f.lines[m]) > pos { b = m; } else { a = m; }
     }
-    ret {filename: f.name, line: a + 1u, col: pos - lookup(f.lines[a])};
+    ret {fm: f, line: a};
+}
+
+fn lookup_pos(map: codemap, pos: uint, lookup: lookup_fn) -> loc {
+    let {fm: f, line: a} = lookup_line(map, pos, lookup);
+    ret {file: f, line: a + 1u, col: pos - lookup(f.lines[a])};
 }
 
 fn lookup_char_pos(map: codemap, pos: uint) -> loc {
@@ -67,7 +94,7 @@ fn lookup_byte_pos(map: codemap, pos: uint) -> loc {
 
 enum opt_span {
 
-    //hack (as opposed to option::t), to make `span` compile
+    //hack (as opposed to option), to make `span` compile
     os_none,
     os_some(@span),
 }
@@ -76,20 +103,21 @@ enum opt_span {
 fn span_to_str(sp: span, cm: codemap) -> str {
     let cur = sp;
     let res = "";
+    // FIXME: Should probably be doing pointer comparison on filemap
     let prev_file = none;
     while true {
         let lo = lookup_char_pos(cm, cur.lo);
         let hi = lookup_char_pos(cm, cur.hi);
         res +=
             #fmt["%s:%u:%u: %u:%u",
-                 if some(lo.filename) == prev_file {
+                 if some(lo.file.name) == prev_file {
                      "-"
-                 } else { lo.filename }, lo.line, lo.col, hi.line, hi.col];
+                 } else { lo.file.name }, lo.line, lo.col, hi.line, hi.col];
         alt cur.expanded_from {
           os_none { break; }
           os_some(new_sp) {
             cur = *new_sp;
-            prev_file = some(lo.filename);
+            prev_file = some(lo.file.name);
             res += "<<";
           }
         }
@@ -98,17 +126,18 @@ fn span_to_str(sp: span, cm: codemap) -> str {
     ret res;
 }
 
-type file_lines = {name: str, lines: [uint]};
+type file_lines = {file: filemap, lines: [uint]};
 
 fn span_to_lines(sp: span, cm: codemap::codemap) -> @file_lines {
     let lo = lookup_char_pos(cm, sp.lo);
     let hi = lookup_char_pos(cm, sp.hi);
+    // FIXME: Check for filemap?
     let lines = [];
     uint::range(lo.line - 1u, hi.line as uint) {|i| lines += [i]; };
-    ret @{name: lo.filename, lines: lines};
+    ret @{file: lo.file, lines: lines};
 }
 
-fn get_line(fm: filemap, line: int) -> str {
+fn get_line(fm: filemap, line: int) -> str unsafe {
     let begin: uint = fm.lines[line].byte - fm.start_pos.byte;
     let end: uint;
     if line as uint < vec::len(fm.lines) - 1u {
@@ -118,11 +147,35 @@ fn get_line(fm: filemap, line: int) -> str {
         // parsed. If we just slice the rest of the string, we'll print out
         // the remainder of the file, which is undesirable.
         end = str::byte_len(*fm.src);
-        let rest = str::slice(*fm.src, begin, end);
+        let rest = str::unsafe::slice_bytes(*fm.src, begin, end);
         let newline = str::index(rest, '\n' as u8);
         if newline != -1 { end = begin + (newline as uint); }
     }
-    ret str::slice(*fm.src, begin, end);
+    ret str::unsafe::slice_bytes(*fm.src, begin, end);
+}
+
+fn lookup_byte_offset(cm: codemap::codemap, chpos: uint)
+    -> {fm: filemap, pos: uint}
+{
+    fn lookup(pos: file_pos) -> uint { ret pos.ch; }
+    let {fm,line} = lookup_line(cm,chpos,lookup);
+    let line_offset = fm.lines[line].byte - fm.start_pos.byte;
+    let col = chpos - fm.lines[line].ch;
+    let col_offset = str::byte_len_range(*fm.src, line_offset, col);
+    ret {fm: fm, pos: line_offset + col_offset};
+}
+
+fn span_to_snippet(sp: span, cm: codemap::codemap) -> str {
+    let begin = lookup_byte_offset(cm,sp.lo);
+    let end   = lookup_byte_offset(cm,sp.hi);
+    assert begin.fm == end.fm;
+    ret str::slice(*begin.fm.src, begin.pos, end.pos);
+}
+
+fn get_snippet(cm: codemap::codemap, fidx: uint, lo: uint, hi: uint) -> str
+{
+    let fm = cm.files[fidx];
+    ret str::slice(*fm.src, lo, hi)
 }
 
 fn get_filemap(cm: codemap, filename: str) -> filemap {
index 50ff9932e7ebc1494b376ca2a83bfb1a69d8de2e..42ec73077f6ceeebad38290541838762d7816585 100644 (file)
@@ -6,10 +6,10 @@
 import codemap;
 
 type syntax_expander =
-    fn@(ext_ctxt, span, @ast::expr, option::t<str>) -> @ast::expr;
+    fn@(ext_ctxt, span, ast::mac_arg, ast::mac_body) -> @ast::expr;
 type macro_def = {ident: str, ext: syntax_extension};
 type macro_definer =
-    fn@(ext_ctxt, span, @ast::expr, option::t<str>) -> macro_def;
+    fn@(ext_ctxt, span, ast::mac_arg, ast::mac_body) -> macro_def;
 
 enum syntax_extension {
     normal(syntax_expander),
@@ -30,6 +30,8 @@ fn syntax_expander_table() -> hashmap<str, syntax_extension> {
                             normal(ext::ident_to_str::expand_syntax_ext));
     syntax_expanders.insert("log_syntax",
                             normal(ext::log_syntax::expand_syntax_ext));
+    syntax_expanders.insert("ast",
+                            normal(ext::qquote::expand_ast));
     ret syntax_expanders;
 }
 
@@ -118,7 +120,21 @@ fn make_new_lit(cx: ext_ctxt, sp: codemap::span, lit: ast::lit_) ->
     ret @{id: cx.next_id(), node: ast::expr_lit(sp_lit), span: sp};
 }
 
+fn get_mac_arg(cx: ext_ctxt, sp: span, arg: ast::mac_arg) -> @ast::expr {
+    alt (arg) {
+      some(expr) {expr}
+      none {cx.span_fatal(sp, "missing macro args")}
+    }
+}
 
+fn get_mac_body(cx: ext_ctxt, sp: span, args: ast::mac_body)
+    -> ast::mac_body_
+{
+    alt (args) {
+      some(body) {body}
+      none {cx.span_fatal(sp, "missing macro body")}
+    }
+}
 
 //
 // Local Variables:
diff --git a/src/comp/syntax/ext/build.rs b/src/comp/syntax/ext/build.rs
new file mode 100644 (file)
index 0000000..ec7ff47
--- /dev/null
@@ -0,0 +1,83 @@
+import core::{vec, str, option};
+import option::{some};
+import codemap::span;
+import syntax::ext::base::ext_ctxt;
+
+// NOTE: Moved from fmt.rs which had this fixme:
+// FIXME: Cleanup the naming of these functions
+
+fn mk_lit(cx: ext_ctxt, sp: span, lit: ast::lit_) -> @ast::expr {
+    let sp_lit = @{node: lit, span: sp};
+    ret @{id: cx.next_id(), node: ast::expr_lit(sp_lit), span: sp};
+}
+fn mk_str(cx: ext_ctxt, sp: span, s: str) -> @ast::expr {
+    let lit = ast::lit_str(s);
+    ret mk_lit(cx, sp, lit);
+}
+fn mk_int(cx: ext_ctxt, sp: span, i: int) -> @ast::expr {
+    let lit = ast::lit_int(i as i64, ast::ty_i);
+    ret mk_lit(cx, sp, lit);
+}
+fn mk_uint(cx: ext_ctxt, sp: span, u: uint) -> @ast::expr {
+    let lit = ast::lit_uint(u as u64, ast::ty_u);
+    ret mk_lit(cx, sp, lit);
+}
+fn mk_binary(cx: ext_ctxt, sp: span, op: ast::binop,
+             lhs: @ast::expr, rhs: @ast::expr)
+   -> @ast::expr {
+    let binexpr = ast::expr_binary(op, lhs, rhs);
+    ret @{id: cx.next_id(), node: binexpr, span: sp};
+}
+fn mk_unary(cx: ext_ctxt, sp: span, op: ast::unop, e: @ast::expr)
+    -> @ast::expr {
+    let expr = ast::expr_unary(op, e);
+    ret @{id: cx.next_id(), node: expr, span: sp};
+}
+fn mk_path(cx: ext_ctxt, sp: span, idents: [ast::ident]) ->
+    @ast::expr {
+    let path = {global: false, idents: idents, types: []};
+    let sp_path = @{node: path, span: sp};
+    let pathexpr = ast::expr_path(sp_path);
+    ret @{id: cx.next_id(), node: pathexpr, span: sp};
+}
+fn mk_access_(cx: ext_ctxt, sp: span, p: @ast::expr, m: ast::ident)
+    -> @ast::expr {
+    let expr = ast::expr_field(p, m, []);
+    ret @{id: cx.next_id(), node: expr, span: sp};
+}
+fn mk_access(cx: ext_ctxt, sp: span, p: [ast::ident], m: ast::ident)
+    -> @ast::expr {
+    let pathexpr = mk_path(cx, sp, p);
+    ret mk_access_(cx, sp, pathexpr, m);
+}
+fn mk_call_(cx: ext_ctxt, sp: span, fn_expr: @ast::expr,
+            args: [@ast::expr]) -> @ast::expr {
+    let callexpr = ast::expr_call(fn_expr, args, false);
+    ret @{id: cx.next_id(), node: callexpr, span: sp};
+}
+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);
+    ret mk_call_(cx, sp, pathexpr, args);
+}
+// e = expr, t = type
+fn mk_vec_e(cx: ext_ctxt, sp: span, exprs: [@ast::expr]) ->
+   @ast::expr {
+    let vecexpr = ast::expr_vec(exprs, ast::imm);
+    ret @{id: cx.next_id(), node: vecexpr, span: sp};
+}
+fn mk_rec_e(cx: ext_ctxt, sp: span,
+            fields: [{ident: ast::ident, ex: @ast::expr}]) ->
+    @ast::expr {
+    let astfields: [ast::field] = [];
+    for field: {ident: ast::ident, ex: @ast::expr} in fields {
+        let ident = field.ident;
+        let val = field.ex;
+        let astfield =
+            {node: {mut: ast::imm, ident: ident, expr: val}, span: sp};
+        astfields += [astfield];
+    }
+    let recexpr = ast::expr_rec(astfields, option::none::<@ast::expr>);
+    ret @{id: cx.next_id(), node: recexpr, span: sp};
+}
+
index c487a3ecc3612a85c4545326b92bacd9b72d7621..538c40a9d66e5b0fe35ac204a2cbbe25f4623a10 100644 (file)
@@ -2,8 +2,9 @@
 import base::*;
 import syntax::ast;
 
-fn expand_syntax_ext(cx: ext_ctxt, sp: codemap::span, arg: @ast::expr,
-                     _body: option::t<str>) -> @ast::expr {
+fn expand_syntax_ext(cx: ext_ctxt, sp: codemap::span, arg: ast::mac_arg,
+                     _body: ast::mac_body) -> @ast::expr {
+    let arg = get_mac_arg(cx,sp,arg);
     let args: [@ast::expr] =
         alt arg.node {
           ast::expr_vec(elts, _) { elts }
index e5d80c3f314fe9c898963ef5936e7802baa308c0..b9b42028c0fc5ec6f60fff8ca402ce819dbf6ee7 100644 (file)
@@ -9,8 +9,9 @@
 import base::*;
 export expand_syntax_ext;
 
-fn expand_syntax_ext(cx: ext_ctxt, sp: codemap::span, arg: @ast::expr,
-                     _body: option::t<str>) -> @ast::expr {
+fn expand_syntax_ext(cx: ext_ctxt, sp: codemap::span, arg: ast::mac_arg,
+                     _body: ast::mac_body) -> @ast::expr {
+    let arg = get_mac_arg(cx,sp,arg);
     let args: [@ast::expr] =
         alt arg.node {
           ast::expr_vec(elts, _) { elts }
@@ -22,7 +23,7 @@ fn expand_syntax_ext(cx: ext_ctxt, sp: codemap::span, arg: @ast::expr,
         cx.span_fatal(sp, "malformed #env call");
     }
     // FIXME: if this was more thorough it would manufacture an
-    // option::t<str> rather than just an maybe-empty string.
+    // option<str> rather than just an maybe-empty string.
 
     let var = expr_to_str(cx, args[0], "#env requires a string");
     alt generic_os::getenv(var) {
index d5482a1e62f580027261310d0a8c2c5369990cb2..a0bba6eee5c4274fc2e48c190b37d439e5fccebe 100644 (file)
@@ -5,9 +5,10 @@
 import std::map::hashmap;
 import vec;
 
-import syntax::ast::{crate, expr_, expr_mac, mac_invoc};
+import syntax::ast::{crate, expr_, expr_mac, mac_invoc, mac_qq};
 import syntax::fold::*;
 import syntax::ext::base::*;
+import syntax::ext::qquote::{expand_qquote,qq_helper};
 import syntax::parse::parser::parse_expr_from_source_str;
 
 import codemap::span;
@@ -45,6 +46,13 @@ fn expand_expr(exts: hashmap<str, syntax_extension>, cx: ext_ctxt,
                   }
                 }
               }
+              mac_qq(sp, exp) {
+                let r = expand_qquote(cx, sp, none, exp);
+                // need to keep going, resuls may contain embedded qquote or
+                // macro that need expanding
+                let r2 = fld.fold_expr(r);
+                (r2.node, s)
+              }
               _ { cx.span_bug(mac.span, "naked syntactic bit") }
             }
           }
@@ -75,7 +83,8 @@ fn expand_crate(sess: session::session, c: @crate) -> @crate {
         {fold_expr: bind expand_expr(exts, cx, _, _, _, afp.fold_expr)
             with *afp};
     let f = make_fold(f_pre);
-    let cm = parse_expr_from_source_str("<anon>", @core_macros(),
+    let cm = parse_expr_from_source_str("<core-macros>",
+                                        @core_macros(),
                                         sess.opts.cfg,
                                         sess.parse_sess);
 
index 5b57923e3088bdddb4f7c164eefcecd0fd2450b1..b7834175d2f5f2fead0ee029427be2d18ae8e6db 100644 (file)
 import extfmt::ct::*;
 import base::*;
 import codemap::span;
+import syntax::ext::build::*;
 export expand_syntax_ext;
 
-fn expand_syntax_ext(cx: ext_ctxt, sp: span, arg: @ast::expr,
-                     _body: option::t<str>) -> @ast::expr {
+fn expand_syntax_ext(cx: ext_ctxt, sp: span, arg: ast::mac_arg,
+                     _body: ast::mac_body) -> @ast::expr {
+    let arg = get_mac_arg(cx,sp,arg);
     let args: [@ast::expr] =
         alt arg.node {
           ast::expr_vec(elts, _) { elts }
@@ -41,67 +43,15 @@ fn parse_fmt_err_(cx: ext_ctxt, sp: span, msg: str) -> ! {
 // FIXME: A lot of these functions for producing expressions can probably
 // be factored out in common with other code that builds expressions.
 // FIXME: 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, pieces: [piece], args: [@ast::expr])
    -> @ast::expr {
-    fn make_new_lit(cx: ext_ctxt, sp: span, lit: ast::lit_) -> @ast::expr {
-        let sp_lit = @{node: lit, span: sp};
-        ret @{id: cx.next_id(), node: ast::expr_lit(sp_lit), span: sp};
-    }
-    fn make_new_str(cx: ext_ctxt, sp: span, s: str) -> @ast::expr {
-        let lit = ast::lit_str(s);
-        ret make_new_lit(cx, sp, lit);
-    }
-    fn make_new_int(cx: ext_ctxt, sp: span, i: int) -> @ast::expr {
-        let lit = ast::lit_int(i as i64, ast::ty_i);
-        ret make_new_lit(cx, sp, lit);
-    }
-    fn make_new_uint(cx: ext_ctxt, sp: span, u: uint) -> @ast::expr {
-        let lit = ast::lit_uint(u as u64, ast::ty_u);
-        ret make_new_lit(cx, sp, lit);
-    }
-    fn make_add_expr(cx: ext_ctxt, sp: span, lhs: @ast::expr, rhs: @ast::expr)
-       -> @ast::expr {
-        let binexpr = ast::expr_binary(ast::add, lhs, rhs);
-        ret @{id: cx.next_id(), node: binexpr, span: sp};
-    }
-    fn make_path_expr(cx: ext_ctxt, sp: span, idents: [ast::ident]) ->
-       @ast::expr {
-        let path = {global: false, idents: idents, types: []};
-        let sp_path = @{node: path, span: sp};
-        let pathexpr = ast::expr_path(sp_path);
-        ret @{id: cx.next_id(), node: pathexpr, span: sp};
-    }
-    fn make_vec_expr(cx: ext_ctxt, sp: span, exprs: [@ast::expr]) ->
-       @ast::expr {
-        let vecexpr = ast::expr_vec(exprs, ast::imm);
-        ret @{id: cx.next_id(), node: vecexpr, span: sp};
-    }
-    fn make_call(cx: ext_ctxt, sp: span, fn_path: [ast::ident],
-                 args: [@ast::expr]) -> @ast::expr {
-        let pathexpr = make_path_expr(cx, sp, fn_path);
-        let callexpr = ast::expr_call(pathexpr, args, false);
-        ret @{id: cx.next_id(), node: callexpr, span: sp};
-    }
-    fn make_rec_expr(cx: ext_ctxt, sp: span,
-                     fields: [{ident: ast::ident, ex: @ast::expr}]) ->
-       @ast::expr {
-        let astfields: [ast::field] = [];
-        for field: {ident: ast::ident, ex: @ast::expr} in fields {
-            let ident = field.ident;
-            let val = field.ex;
-            let astfield =
-                {node: {mut: ast::imm, ident: ident, expr: val}, span: sp};
-            astfields += [astfield];
-        }
-        let recexpr = ast::expr_rec(astfields, option::none::<@ast::expr>);
-        ret @{id: cx.next_id(), node: recexpr, span: sp};
-    }
     fn make_path_vec(_cx: ext_ctxt, ident: ast::ident) -> [ast::ident] {
         ret ["extfmt", "rt", ident];
     }
     fn make_rt_path_expr(cx: ext_ctxt, sp: span, ident: str) -> @ast::expr {
         let path = make_path_vec(cx, ident);
-        ret make_path_expr(cx, sp, path);
+        ret mk_path(cx, sp, path);
     }
     // Produces an AST expression that represents a RT::conv record,
     // which tells the RT::conv* functions how to perform the conversion
@@ -127,7 +77,7 @@ fn make_flags(cx: ext_ctxt, sp: span, flags: [flag]) -> @ast::expr {
             if vec::len::<@ast::expr>(flagexprs) == 0u {
                 flagexprs += [make_rt_path_expr(cx, sp, "flag_none")];
             }
-            ret make_vec_expr(cx, sp, flagexprs);
+            ret mk_vec_e(cx, sp, flagexprs);
         }
         fn make_count(cx: ext_ctxt, sp: span, cnt: count) -> @ast::expr {
             alt cnt {
@@ -135,10 +85,10 @@ fn make_count(cx: ext_ctxt, sp: span, cnt: count) -> @ast::expr {
                 ret make_rt_path_expr(cx, sp, "count_implied");
               }
               count_is(c) {
-                let count_lit = make_new_int(cx, sp, c);
+                let count_lit = mk_int(cx, sp, c);
                 let count_is_path = make_path_vec(cx, "count_is");
                 let count_is_args = [count_lit];
-                ret make_call(cx, sp, count_is_path, count_is_args);
+                ret mk_call(cx, sp, count_is_path, count_is_args);
               }
               _ { cx.span_unimpl(sp, "unimplemented #fmt conversion"); }
             }
@@ -161,11 +111,11 @@ fn make_ty(cx: ext_ctxt, sp: span, t: ty) -> @ast::expr {
         fn make_conv_rec(cx: ext_ctxt, sp: span, flags_expr: @ast::expr,
                          width_expr: @ast::expr, precision_expr: @ast::expr,
                          ty_expr: @ast::expr) -> @ast::expr {
-            ret make_rec_expr(cx, sp,
-                              [{ident: "flags", ex: flags_expr},
-                               {ident: "width", ex: width_expr},
-                               {ident: "precision", ex: precision_expr},
-                               {ident: "ty", ex: ty_expr}]);
+            ret mk_rec_e(cx, sp,
+                         [{ident: "flags", ex: flags_expr},
+                          {ident: "width", ex: width_expr},
+                          {ident: "precision", ex: precision_expr},
+                          {ident: "ty", ex: ty_expr}]);
         }
         let rt_conv_flags = make_flags(cx, sp, cnv.flags);
         let rt_conv_width = make_count(cx, sp, cnv.width);
@@ -180,7 +130,7 @@ fn make_conv_call(cx: ext_ctxt, sp: span, conv_type: str, cnv: conv,
         let path = make_path_vec(cx, fname);
         let cnv_expr = make_rt_conv_expr(cx, sp, cnv);
         let args = [cnv_expr, arg];
-        ret make_call(cx, arg.span, path, args);
+        ret mk_call(cx, arg.span, path, args);
     }
     fn make_new_conv(cx: ext_ctxt, sp: span, cnv: conv, arg: @ast::expr) ->
        @ast::expr {
@@ -309,13 +259,13 @@ fn log_conv(c: conv) {
     }
     let fmt_sp = args[0].span;
     let n = 0u;
-    let tmp_expr = make_new_str(cx, sp, "");
+    let tmp_expr = mk_str(cx, sp, "");
     let nargs = vec::len::<@ast::expr>(args);
     for pc: piece in pieces {
         alt pc {
           piece_string(s) {
-            let s_expr = make_new_str(cx, fmt_sp, s);
-            tmp_expr = make_add_expr(cx, fmt_sp, tmp_expr, s_expr);
+            let s_expr = mk_str(cx, fmt_sp, s);
+            tmp_expr = mk_binary(cx, fmt_sp, ast::add, tmp_expr, s_expr);
           }
           piece_conv(conv) {
             n += 1u;
@@ -328,7 +278,7 @@ fn log_conv(c: conv) {
             log_conv(conv);
             let arg_expr = args[n];
             let c_expr = make_new_conv(cx, fmt_sp, conv, arg_expr);
-            tmp_expr = make_add_expr(cx, fmt_sp, tmp_expr, c_expr);
+            tmp_expr = mk_binary(cx, fmt_sp, ast::add, tmp_expr, c_expr);
           }
         }
     }
index d6093b61dbfd584be6e25c430434559ce6a04b6a..9245e5aa6d4fc818d3ce5e1158011f91198a2e97 100644 (file)
@@ -2,8 +2,9 @@
 import base::*;
 import syntax::ast;
 
-fn expand_syntax_ext(cx: ext_ctxt, sp: codemap::span, arg: @ast::expr,
-                     _body: option::t<str>) -> @ast::expr {
+fn expand_syntax_ext(cx: ext_ctxt, sp: codemap::span, arg: ast::mac_arg,
+                     _body: ast::mac_body) -> @ast::expr {
+    let arg = get_mac_arg(cx,sp,arg);
     let args: [@ast::expr] =
         alt arg.node {
           ast::expr_vec(elts, _) { elts }
index 47a639b7ed0b88c35fd7bbec317baeca8636895a..911cf9ff2eb60d83e3d888edfd19db95f1e17811 100644 (file)
@@ -2,9 +2,9 @@
 import syntax::ast;
 import std::io::writer_util;
 
-fn expand_syntax_ext(cx: ext_ctxt, sp: codemap::span, arg: @ast::expr,
-                     _body: option::t<str>) -> @ast::expr {
-
+fn expand_syntax_ext(cx: ext_ctxt, sp: codemap::span, arg: ast::mac_arg,
+                     _body: ast::mac_body) -> @ast::expr {
+    let arg = get_mac_arg(cx,sp,arg);
     cx.print_backtrace();
     std::io::stdout().write_line(print::pprust::expr_to_str(arg));
 
diff --git a/src/comp/syntax/ext/qquote.rs b/src/comp/syntax/ext/qquote.rs
new file mode 100644 (file)
index 0000000..f215d37
--- /dev/null
@@ -0,0 +1,321 @@
+import driver::session;
+
+import option::{none, some};
+
+import syntax::ast::{crate, expr_, mac_invoc,
+                     mac_qq, mac_aq, mac_var};
+import syntax::fold::*;
+import syntax::visit::*;
+import syntax::ext::base::*;
+import syntax::ext::build::*;
+import syntax::parse::parser;
+import syntax::parse::parser::{parser, parse_from_source_str};
+
+import syntax::print::*;
+import std::io::*;
+
+import codemap::span;
+
+type aq_ctxt = @{lo: uint,
+                 mutable gather: [{lo: uint, hi: uint,
+                                   e: @ast::expr,
+                                   constr: str}]};
+enum fragment {
+    from_expr(@ast::expr),
+    from_ty(@ast::ty)
+}
+
+iface qq_helper {
+    fn span() -> span;
+    fn visit(aq_ctxt, vt<aq_ctxt>);
+    fn extract_mac() -> option<ast::mac_>;
+    fn mk_parse_fn(ext_ctxt,span) -> @ast::expr;
+    fn get_fold_fn() -> str;
+}
+impl of qq_helper for @ast::expr {
+    fn span() -> span {self.span}
+    fn visit(cx: aq_ctxt, v: vt<aq_ctxt>) {visit_expr(self, cx, v);}
+    fn extract_mac() -> option<ast::mac_> {
+        alt (self.node) {
+          ast::expr_mac({node: mac, _}) {some(mac)}
+          _ {none}
+        }
+    }
+    fn mk_parse_fn(cx: ext_ctxt, sp: span) -> @ast::expr {
+        mk_path(cx, sp, ["syntax", "parse", "parser", "parse_expr"])
+    }
+    fn get_fold_fn() -> str {"fold_expr"}
+}
+impl of qq_helper for @ast::ty {
+    fn span() -> span {self.span}
+    fn visit(cx: aq_ctxt, v: vt<aq_ctxt>) {visit_ty(self, cx, v);}
+    fn extract_mac() -> option<ast::mac_> {
+        alt (self.node) {
+          ast::ty_mac({node: mac, _}) {some(mac)}
+          _ {none}
+        }
+    }
+    fn mk_parse_fn(cx: ext_ctxt, sp: span) -> @ast::expr {
+        mk_path(cx, sp, ["syntax", "ext", "qquote", "parse_ty"])
+    }
+    fn get_fold_fn() -> str {"fold_ty"}
+}
+impl of qq_helper for @ast::item {
+    fn span() -> span {self.span}
+    fn visit(cx: aq_ctxt, v: vt<aq_ctxt>) {visit_item(self, cx, v);}
+    fn extract_mac() -> option<ast::mac_> {fail}
+    fn mk_parse_fn(cx: ext_ctxt, sp: span) -> @ast::expr {
+        mk_path(cx, sp, ["syntax", "ext", "qquote", "parse_item"])
+    }
+    fn get_fold_fn() -> str {"fold_item"}
+}
+impl of qq_helper for @ast::stmt {
+    fn span() -> span {self.span}
+    fn visit(cx: aq_ctxt, v: vt<aq_ctxt>) {visit_stmt(self, cx, v);}
+    fn extract_mac() -> option<ast::mac_> {fail}
+    fn mk_parse_fn(cx: ext_ctxt, sp: span) -> @ast::expr {
+        mk_path(cx, sp, ["syntax", "ext", "qquote", "parse_stmt"])
+    }
+    fn get_fold_fn() -> str {"fold_stmt"}
+}
+impl of qq_helper for @ast::pat {
+    fn span() -> span {self.span}
+    fn visit(cx: aq_ctxt, v: vt<aq_ctxt>) {visit_pat(self, cx, v);}
+    fn extract_mac() -> option<ast::mac_> {fail}
+    fn mk_parse_fn(cx: ext_ctxt, sp: span) -> @ast::expr {
+        mk_path(cx, sp, ["syntax", "parse", "parser", "parse_pat"])
+    }
+    fn get_fold_fn() -> str {"fold_pat"}
+}
+
+fn gather_anti_quotes<N: qq_helper>(lo: uint, node: N) -> aq_ctxt
+{
+    let v = @{visit_expr: visit_aq_expr,
+              visit_ty: visit_aq_ty
+              with *default_visitor()};
+    let cx = @{lo:lo, mutable gather: []};
+    node.visit(cx, mk_vt(v));
+    ret cx;
+}
+
+fn visit_aq<T:qq_helper>(node: T, constr: str, &&cx: aq_ctxt, v: vt<aq_ctxt>)
+{
+    alt (node.extract_mac()) {
+      some(mac_aq(sp, e)) {
+        cx.gather += [{lo: sp.lo - cx.lo, hi: sp.hi - cx.lo,
+                       e: e, constr: constr}];
+      }
+      _ {node.visit(cx, v);}
+    }
+}
+// FIXME: these are only here because I (kevina) couldn't figure out how to
+// get bind to work in gather_anti_quotes
+fn visit_aq_expr(node: @ast::expr, &&cx: aq_ctxt, v: vt<aq_ctxt>) {
+    visit_aq(node,"from_expr",cx,v);
+}
+fn visit_aq_ty(node: @ast::ty, &&cx: aq_ctxt, v: vt<aq_ctxt>) {
+    visit_aq(node,"from_ty",cx,v);
+}
+
+fn is_space(c: char) -> bool {
+    syntax::parse::lexer::is_whitespace(c)
+}
+
+fn expand_ast(ecx: ext_ctxt, _sp: span,
+              arg: ast::mac_arg, body: ast::mac_body)
+    -> @ast::expr
+{
+    let what = "expr";
+    option::may(arg) {|arg|
+        let args: [@ast::expr] =
+            alt arg.node {
+              ast::expr_vec(elts, _) { elts }
+              _ {
+                ecx.span_fatal
+                    (_sp, "#ast requires arguments of the form `[...]`.")
+              }
+            };
+        if vec::len::<@ast::expr>(args) != 1u {
+            ecx.span_fatal(_sp, "#ast requires exactly one arg");
+        }
+        alt (args[0].node) {
+          ast::expr_path(@{node: {idents: id, _},_}) if vec::len(id) == 1u
+              {what = id[0]}
+          _ {ecx.span_fatal(args[0].span, "expected an identifier");}
+        }
+    }
+    let body = get_mac_body(ecx,_sp,body);
+    fn finish<T: qq_helper>(ecx: ext_ctxt, body: ast::mac_body_,
+                            f: fn (p: parser) -> T)
+        -> @ast::expr
+    {
+        let cm = ecx.session().parse_sess.cm;
+        let str = @codemap::span_to_snippet(body.span, cm);
+        let (fname, ss) = codemap::get_substr_info
+            (cm, body.span.lo, body.span.hi);
+        let node = parse_from_source_str
+            (f, fname, some(ss), str,
+             ecx.session().opts.cfg, ecx.session().parse_sess);
+        ret expand_qquote(ecx, node.span(), some(*str), node);
+    }
+
+    ret alt what {
+      "expr" {finish(ecx, body, parser::parse_expr)}
+      "ty" {finish(ecx, body, parse_ty)}
+      "item" {finish(ecx, body, parse_item)}
+      "stmt" {finish(ecx, body, parse_stmt)}
+      "pat" {finish(ecx, body, parser::parse_pat)}
+      _ {ecx.span_fatal(_sp, "unsupported ast type")}
+    };
+}
+
+fn parse_ty(p: parser) -> @ast::ty {
+    parser::parse_ty(p, false)
+}
+
+fn parse_stmt(p: parser) -> @ast::stmt {
+    parser::parse_stmt(p, [])
+}
+
+fn parse_item(p: parser) -> @ast::item {
+    alt (parser::parse_item(p, [])) {
+      some(item) {item}
+      none {fail; /* FIXME: Error message, somehow */}
+    }
+}
+
+fn expand_qquote<N: qq_helper>
+    (ecx: ext_ctxt, sp: span, maybe_str: option::t<str>, node: N)
+    -> @ast::expr
+{
+    let str = alt(maybe_str) {
+      some(s) {s}
+      none {codemap::span_to_snippet(sp, ecx.session().parse_sess.cm)}
+    };
+    let qcx = gather_anti_quotes(sp.lo, node);
+    let cx = qcx;
+    let prev = 0u;
+    for {lo: lo, _} in cx.gather {
+        assert lo > prev;
+        prev = lo;
+    }
+    let str2 = "";
+    enum state {active, skip(uint), blank};
+    let state = active;
+    let i = 0u, j = 0u;
+    let g_len = vec::len(cx.gather);
+    str::chars_iter(str) {|ch|
+        if (j < g_len && i == cx.gather[j].lo) {
+            assert ch == '$';
+            let repl = #fmt("$%u ", j);
+            state = skip(str::char_len(repl));
+            str2 += repl;
+        }
+        alt state {
+          active {str::push_char(str2, ch);}
+          skip(1u) {state = blank;}
+          skip(sk) {state = skip (sk-1u);}
+          blank if is_space(ch) {str::push_char(str2, ch);}
+          blank {str::push_char(str2, ' ');}
+        }
+        i += 1u;
+        if (j < g_len && i == cx.gather[j].hi) {
+            assert ch == ')';
+            state = active;
+            j += 1u;
+        }
+    }
+
+    let cx = ecx;
+    let session_call = bind mk_call_(cx,sp,
+                                     mk_access(cx,sp,["ext_cx"], "session"),
+                                     []);
+    let pcall = mk_call(cx,sp,
+                       ["syntax", "parse", "parser",
+                        "parse_from_source_str"],
+                       [node.mk_parse_fn(cx,sp),
+                        mk_str(cx,sp, "<anon>"),
+                        mk_path(cx,sp, ["option","none"]),
+                        mk_unary(cx,sp, ast::box(ast::imm),
+                                 mk_str(cx,sp, str2)),
+                        mk_access_(cx,sp,
+                                   mk_access_(cx,sp, session_call(), "opts"),
+                                   "cfg"),
+                        mk_access_(cx,sp, session_call(), "parse_sess")]
+                      );
+    let rcall = pcall;
+    if (g_len > 0u) {
+        rcall = mk_call(cx,sp,
+                        ["syntax", "ext", "qquote", "replace"],
+                        [pcall,
+                         mk_vec_e(cx,sp, vec::map(copy qcx.gather) {|g|
+                             mk_call(cx,sp,
+                                     ["syntax", "ext", "qquote", g.constr],
+                                     [g.e])}),
+                         mk_path(cx,sp,
+                                 ["syntax", "ext", "qquote",
+                                  node.get_fold_fn()])]);
+    }
+    ret rcall;
+}
+
+fn replace<T>(node: T, repls: [fragment], ff: fn (ast_fold, T) -> T)
+    -> T
+{
+    let aft = default_ast_fold();
+    let f_pre = {fold_expr: bind replace_expr(repls, _, _, _,
+                                              aft.fold_expr),
+                 fold_ty: bind replace_ty(repls, _, _, _,
+                                          aft.fold_ty)
+                 with *aft};
+    ret ff(make_fold(f_pre), node);
+}
+fn fold_expr(f: ast_fold, &&n: @ast::expr) -> @ast::expr {f.fold_expr(n)}
+fn fold_ty(f: ast_fold, &&n: @ast::ty) -> @ast::ty {f.fold_ty(n)}
+fn fold_item(f: ast_fold, &&n: @ast::item) -> @ast::item {f.fold_item(n)}
+fn fold_stmt(f: ast_fold, &&n: @ast::stmt) -> @ast::stmt {f.fold_stmt(n)}
+fn fold_pat(f: ast_fold, &&n: @ast::pat) -> @ast::pat {f.fold_pat(n)}
+
+fn replace_expr(repls: [fragment],
+                e: ast::expr_, s: span, fld: ast_fold,
+                orig: fn@(ast::expr_, span, ast_fold)->(ast::expr_, span))
+    -> (ast::expr_, span)
+{
+    alt e {
+      ast::expr_mac({node: mac_var(i), _}) {
+        alt (repls[i]) {
+          from_expr(r) {(r.node, r.span)}
+          _ {fail /* fixme error message */}}}
+      _ {orig(e,s,fld)}
+    }
+}
+
+fn replace_ty(repls: [fragment],
+                e: ast::ty_, s: span, fld: ast_fold,
+                orig: fn@(ast::ty_, span, ast_fold)->(ast::ty_, span))
+    -> (ast::ty_, span)
+{
+    alt e {
+      ast::ty_mac({node: mac_var(i), _}) {
+        alt (repls[i]) {
+          from_ty(r) {(r.node, r.span)}
+          _ {fail /* fixme error message */}}}
+      _ {orig(e,s,fld)}
+    }
+}
+
+fn print_expr(expr: @ast::expr) {
+    let stdout = std::io::stdout();
+    let pp = pprust::rust_printer(stdout);
+    pprust::print_expr(pp, expr);
+    pp::eof(pp.s);
+    stdout.write_str("\n");
+}
+
+// Local Variables:
+// mode: rust
+// fill-column: 78;
+// indent-tabs-mode: nil
+// c-basic-offset: 4
+// buffer-file-coding-system: utf-8-unix
+// End:
index 5477c49588348c9f596a0652a5528bb0fa292683..d8496203e3d9d5c0381eb20f8f34f1982acb217d 100644 (file)
@@ -4,8 +4,9 @@
 import core::{vec, option};
 import std::map::{hashmap, new_str_hash};
 import option::{some, none};
+import driver::session::session;
 
-import base::{ext_ctxt, normal};
+import base::*;
 
 import fold::*;
 import ast_util::respan;
@@ -14,7 +15,7 @@
 
 export add_new_extension;
 
-fn path_to_ident(pth: @path) -> option::t<ident> {
+fn path_to_ident(pth: @path) -> option<ident> {
     if vec::len(pth.node.idents) == 1u && vec::len(pth.node.types) == 0u {
         ret some(pth.node.idents[0u]);
     }
@@ -70,11 +71,11 @@ fn match_error(cx: ext_ctxt, m: matchable, expected: str) -> ! {
 // If we want better match failure error messages (like in Fortifying Syntax),
 // we'll want to return something indicating amount of progress and location
 // of failure instead of `none`.
-type match_result = option::t<arb_depth<matchable>>;
+type match_result = option<arb_depth<matchable>>;
 type selector = fn@(matchable) -> match_result;
 
 fn elts_to_ell(cx: ext_ctxt, elts: [@expr]) ->
-   {pre: [@expr], rep: option::t<@expr>, post: [@expr]} {
+   {pre: [@expr], rep: option<@expr>, post: [@expr]} {
     let idx: uint = 0u;
     let res = none;
     for elt: @expr in elts {
@@ -103,8 +104,8 @@ fn elts_to_ell(cx: ext_ctxt, elts: [@expr]) ->
         }
 }
 
-fn option_flatten_map<T: copy, U: copy>(f: fn@(T) -> option::t<U>, v: [T]) ->
-   option::t<[U]> {
+fn option_flatten_map<T: copy, U: copy>(f: fn@(T) -> option<U>, v: [T]) ->
+   option<[U]> {
     let res = [];
     for elem: T in v {
         alt f(elem) { none { ret none; } some(fv) { res += [fv]; } }
@@ -164,7 +165,7 @@ fn pattern_to_selectors(cx: ext_ctxt, e: @expr) -> binders {
 bindings. Most of the work is done in p_t_s, which generates the
 selectors. */
 
-fn use_selectors_to_bind(b: binders, e: @expr) -> option::t<bindings> {
+fn use_selectors_to_bind(b: binders, e: @expr) -> option<bindings> {
     let res = new_str_hash::<arb_depth<matchable>>();
     //need to do this first, to check vec lengths.
     for sel: selector in b.literal_ast_matchers {
@@ -222,8 +223,8 @@ fn follow(m: arb_depth<matchable>, idx_path: @mutable [uint]) ->
     ret res;
 }
 
-fn follow_for_trans(cx: ext_ctxt, mmaybe: option::t<arb_depth<matchable>>,
-                    idx_path: @mutable [uint]) -> option::t<matchable> {
+fn follow_for_trans(cx: ext_ctxt, mmaybe: option<arb_depth<matchable>>,
+                    idx_path: @mutable [uint]) -> option<matchable> {
     alt mmaybe {
       none { ret none }
       some(m) {
@@ -268,7 +269,7 @@ fn transcribe_exprs(cx: ext_ctxt, b: bindings, idx_path: @mutable [uint],
         alt repeat_me_maybe {
           none { }
           some(repeat_me) {
-            let repeat: option::t<{rep_count: uint, name: ident}> = none;
+            let repeat: option<{rep_count: uint, name: ident}> = none;
             /* we need to walk over all the free vars in lockstep, except for
             the leaves, which are just duplicated */
             free_vars(b, repeat_me) {|fv|
@@ -460,11 +461,6 @@ fn p_t_s_rec(cx: ext_ctxt, m: matchable, s: selector, b: binders) {
               }
             }
           }
-
-
-
-
-
           /* TODO: handle embedded types and blocks, at least */
           expr_mac(mac) {
             p_t_s_r_mac(cx, mac, s, b);
@@ -483,6 +479,9 @@ fn select(cx: ext_ctxt, m: matchable, pat: @expr) ->
           }
         }
       }
+      _ {
+          cx.session().bug("undocumented invariant in p_t_s_rec");
+      }
     }
 }
 
@@ -524,7 +523,7 @@ fn select(cx: ext_ctxt, m: matchable) -> match_result {
     }
 }
 
-fn block_to_ident(blk: blk_) -> option::t<ident> {
+fn block_to_ident(blk: blk_) -> option<ident> {
     if vec::len(blk.stmts) != 0u { ret none; }
     ret alt blk.expr {
           some(expr) {
@@ -588,6 +587,9 @@ fn select_pt_2(m: ast::mac) -> match_result {
           none { no_des(cx, blk.span, "under `#{}`"); }
         }
       }
+      ast::mac_qq(_,_) { no_des(cx, mac.span, "quasiquotes"); }
+      ast::mac_aq(_,_) { no_des(cx, mac.span, "antiquotes"); }
+      ast::mac_var(_) { no_des(cx, mac.span, "antiquote variables"); }
     }
 }
 
@@ -667,8 +669,9 @@ fn select(cx: ext_ctxt, m: matchable, idx: uint) -> match_result {
     }
 }
 
-fn add_new_extension(cx: ext_ctxt, sp: span, arg: @expr,
-                     _body: option::t<str>) -> base::macro_def {
+fn add_new_extension(cx: ext_ctxt, sp: span, arg: ast::mac_arg,
+                     _body: ast::mac_body) -> base::macro_def {
+    let arg = get_mac_arg(cx,sp,arg);
     let args: [@ast::expr] =
         alt arg.node {
           ast::expr_vec(elts, _) { elts }
@@ -678,7 +681,7 @@ fn add_new_extension(cx: ext_ctxt, sp: span, arg: @expr,
           }
         };
 
-    let macro_name: option::t<str> = none;
+    let macro_name: option<str> = none;
     let clauses: [@clause] = [];
     for arg: @expr in args {
         alt arg.node {
@@ -713,11 +716,17 @@ fn add_new_extension(cx: ext_ctxt, sp: span, arg: @expr,
                       }
                     }
                     clauses +=
-                        [@{params: pattern_to_selectors(cx, invoc_arg),
+                        [@{params: pattern_to_selectors
+                               (cx, get_mac_arg(cx,mac.span,invoc_arg)),
                            body: elts[1u]}];
+
                     // FIXME: check duplicates (or just simplify
                     // the macro arg situation)
                   }
+                  _ {
+                      cx.span_bug(mac.span, "undocumented invariant in \
+                         add_extension");
+                  }
                 }
               }
               _ {
@@ -747,8 +756,9 @@ fn add_new_extension(cx: ext_ctxt, sp: span, arg: @expr,
              },
          ext: normal(ext)};
 
-    fn generic_extension(cx: ext_ctxt, sp: span, arg: @expr,
-                         _body: option::t<str>, clauses: [@clause]) -> @expr {
+    fn generic_extension(cx: ext_ctxt, sp: span, arg: ast::mac_arg,
+                         _body: ast::mac_body, clauses: [@clause]) -> @expr {
+        let arg = get_mac_arg(cx,sp,arg);
         for c: @clause in clauses {
             alt use_selectors_to_bind(c.params, arg) {
               some(bindings) { ret transcribe(cx, bindings, c.body); }
index b24f3aae4737648e107eebb30eca3504d8d65c27..012b6257d891038894727436b0a0bce300823c26 100644 (file)
@@ -27,6 +27,7 @@
      fold_view_item: fn@(view_item_, ast_fold) -> view_item_,
      fold_native_item: fn@(&&@native_item, ast_fold) -> @native_item,
      fold_item: fn@(&&@item, ast_fold) -> @item,
+     fold_class_item: fn@(&&@class_item, ast_fold) -> @class_item,
      fold_item_underscore: fn@(item_, ast_fold) -> item_,
      fold_method: fn@(&&@method, ast_fold) -> @method,
      fold_block: fn@(blk_, span, ast_fold) -> (blk_, span),
@@ -53,6 +54,7 @@
      fold_view_item: fn@(&&@view_item) -> @view_item,
      fold_native_item: fn@(&&@native_item) -> @native_item,
      fold_item: fn@(&&@item) -> @item,
+     fold_class_item: fn@(&&@class_item) -> @class_item,
      fold_item_underscore: fn@(item_) -> item_,
      fold_method: fn@(&&@method) -> @method,
      fold_block: fn@(blk) -> blk,
@@ -82,6 +84,7 @@ fn nf_crate_directive_dummy(&&_c: @crate_directive) -> @crate_directive {
 fn nf_view_item_dummy(&&_v: @view_item) -> @view_item { fail; }
 fn nf_native_item_dummy(&&_n: @native_item) -> @native_item { fail; }
 fn nf_item_dummy(&&_i: @item) -> @item { fail; }
+fn nf_class_item_dummy(&&_ci: @class_item) -> @class_item { fail; }
 fn nf_item_underscore_dummy(_i: item_) -> item_ { fail; }
 fn nf_method_dummy(&&_m: @method) -> @method { fail; }
 fn nf_blk_dummy(_b: blk) -> blk { fail; }
@@ -133,11 +136,17 @@ fn fold_mac_(m: mac, fld: ast_fold) -> mac {
     ret {node:
              alt m.node {
                mac_invoc(pth, arg, body) {
-                 mac_invoc(fld.fold_path(pth), fld.fold_expr(arg), body)
+                 mac_invoc(fld.fold_path(pth),
+                           // FIXME: bind should work, but causes a crash
+                           option::map(arg) {|arg| fld.fold_expr(arg)},
+                           body)
                }
                mac_embed_type(ty) { mac_embed_type(fld.fold_ty(ty)) }
                mac_embed_block(blk) { mac_embed_block(fld.fold_block(blk)) }
                mac_ellipsis { mac_ellipsis }
+               mac_qq(_,_) { /* fixme */ m.node }
+               mac_aq(_,_) { /* fixme */ m.node }
+               mac_var(_) { /* fixme */ m.node }
              },
          span: m.span};
 }
@@ -189,7 +198,6 @@ fn noop_fold_native_item(&&ni: @native_item, fld: ast_fold) -> @native_item {
           attrs: vec::map(ni.attrs, fold_attribute),
           node:
               alt ni.node {
-                native_item_ty { native_item_ty }
                 native_item_fn(fdec, typms) {
                   native_item_fn({inputs: vec::map(fdec.inputs, fold_arg),
                                   output: fld.fold_ty(fdec.output),
@@ -215,6 +223,20 @@ fn noop_fold_item(&&i: @item, fld: ast_fold) -> @item {
           span: i.span};
 }
 
+fn noop_fold_class_item(&&ci: @class_item, fld: ast_fold)
+    -> @class_item {
+    @{node: {
+      privacy:ci.node.privacy,
+            decl:
+     @alt *ci.node.decl {
+        instance_var(ident, t, cm, id) {
+            instance_var(ident, fld.fold_ty(t), cm, id)
+        }
+        class_method(i) { class_method(fld.fold_item(i)) }
+         }},
+       span: ci.span}
+}
+
 fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ {
     ret alt i {
           item_const(t, e) { item_const(fld.fold_ty(t), fld.fold_expr(e)) }
@@ -228,6 +250,12 @@ fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ {
           item_enum(variants, typms) {
             item_enum(vec::map(variants, fld.fold_variant), typms)
           }
+          item_class(typms, items, ctor_decl, ctor_body) {
+              item_class(typms,
+                         vec::map(items, fld.fold_class_item),
+                         fold_fn_decl(ctor_decl, fld),
+                         fld.fold_block(ctor_body))
+          }
           item_impl(tps, ifce, ty, methods) {
             item_impl(tps, option::map(ifce, fld.fold_ty), fld.fold_ty(ty),
                       vec::map(methods, fld.fold_method))
@@ -352,10 +380,6 @@ fn fold_field_(field: field, fld: ast_fold) -> field {
             expr_if(fld.fold_expr(cond), fld.fold_block(tr),
                     option::map(fl, fld.fold_expr))
           }
-          expr_ternary(cond, tr, fl) {
-            expr_ternary(fld.fold_expr(cond), fld.fold_expr(tr),
-                         fld.fold_expr(fl))
-          }
           expr_while(cond, body) {
             expr_while(fld.fold_expr(cond), fld.fold_block(body))
           }
@@ -414,9 +438,32 @@ fn fold_field_(field: field, fld: ast_fold) -> field {
         }
 }
 
-fn noop_fold_ty(t: ty_, _fld: ast_fold) -> ty_ {
-    //drop in ty::fold_ty here if necessary
-    ret t;
+fn noop_fold_ty(t: ty_, fld: ast_fold) -> ty_ {
+    let fold_mac = bind fold_mac_(_, fld);
+    fn fold_mt(mt: mt, fld: ast_fold) -> mt {
+        {ty: fld.fold_ty(mt.ty), mut: mt.mut}
+    }
+    fn fold_field(f: ty_field, fld: ast_fold) -> ty_field {
+        {node: {ident: fld.fold_ident(f.node.ident),
+                mt: fold_mt(f.node.mt, fld)},
+         span: fld.new_span(f.span)}
+    }
+    alt t {
+      ty_nil | ty_bot | ty_bool | ty_str {t}
+      ty_int(_) | ty_uint(_) | ty_float(_) {t}
+      ty_box(mt) {ty_box(fold_mt(mt, fld))}
+      ty_uniq(mt) {ty_uniq(fold_mt(mt, fld))}
+      ty_vec(mt) {ty_vec(fold_mt(mt, fld))}
+      ty_ptr(mt) {ty_ptr(fold_mt(mt, fld))}
+      ty_rec(fields) {ty_rec(vec::map(fields) {|f| fold_field(f, fld)})}
+      ty_fn(proto, decl) {ty_fn(proto, fold_fn_decl(decl, fld))}
+      ty_tup(tys) {ty_tup(vec::map(tys) {|ty| fld.fold_ty(ty)})}
+      ty_path(path, id) {ty_path(fld.fold_path(path), fld.new_id(id))}
+      // FIXME: constrs likely needs to be folded...
+      ty_constr(ty, constrs) {ty_constr(fld.fold_ty(ty), constrs)}
+      ty_mac(mac) {ty_mac(fold_mac(mac))}
+      ty_infer {t}
+    }
 }
 
 fn noop_fold_constr(c: constr_, fld: ast_fold) -> constr_ {
@@ -494,6 +541,7 @@ fn default_ast_fold() -> @ast_fold_precursor {
           fold_view_item: noop_fold_view_item,
           fold_native_item: noop_fold_native_item,
           fold_item: noop_fold_item,
+          fold_class_item: noop_fold_class_item,
           fold_item_underscore: noop_fold_item_underscore,
           fold_method: noop_fold_method,
           fold_block: wrap(noop_fold_block),
@@ -524,6 +572,7 @@ fn make_fold(afp: ast_fold_precursor) -> ast_fold {
                   fold_view_item: bind nf_view_item_dummy(_),
                   fold_native_item: bind nf_native_item_dummy(_),
                   fold_item: bind nf_item_dummy(_),
+                  fold_class_item: bind nf_class_item_dummy(_),
                   fold_item_underscore: bind nf_item_underscore_dummy(_),
                   fold_method: bind nf_method_dummy(_),
                   fold_block: bind nf_blk_dummy(_),
@@ -567,6 +616,21 @@ fn f_native_item(afp: ast_fold_precursor, f: ast_fold, &&x: @native_item)
     fn f_item(afp: ast_fold_precursor, f: ast_fold, &&i: @item) -> @item {
         ret afp.fold_item(i, f);
     }
+    fn f_class_item(afp: ast_fold_precursor, f: ast_fold,
+                      &&ci: @class_item) -> @class_item {
+        @{node:
+         {privacy:ci.node.privacy,
+               decl:
+        @alt *ci.node.decl {
+           instance_var(nm, t, mt, id) {
+               instance_var(nm, f_ty(afp, f, t),
+                                 mt, id)
+           }
+           class_method(i) {
+               class_method(afp.fold_item(i, f))
+           }
+            }}, span: ci.span}
+    }
     fn f_item_underscore(afp: ast_fold_precursor, f: ast_fold, i: item_) ->
        item_ {
         ret afp.fold_item_underscore(i, f);
@@ -641,6 +705,7 @@ fn f_local(afp: ast_fold_precursor, f: ast_fold, &&x: @local) -> @local {
          fold_view_item: bind f_view_item(afp, result, _),
          fold_native_item: bind f_native_item(afp, result, _),
          fold_item: bind f_item(afp, result, _),
+         fold_class_item: bind f_class_item(afp, result, _),
          fold_item_underscore: bind f_item_underscore(afp, result, _),
          fold_method: bind f_method(afp, result, _),
          fold_block: bind f_block(afp, result, _),
index 2530c794c94fe5f3fdc48af27486c713b5620551..74d2259c51e5ecc8dde6bc695fb1718c93949e4a 100644 (file)
@@ -25,7 +25,7 @@ fn eval_crate_directives(cx: ctx, cdirs: [@ast::crate_directive], prefix: str,
 }
 
 fn eval_crate_directives_to_mod(cx: ctx, cdirs: [@ast::crate_directive],
-                                prefix: str, suffix: option::t<str>)
+                                prefix: str, suffix: option<str>)
     -> (ast::_mod, [ast::attribute]) {
     #debug("eval crate prefix: %s", prefix);
     #debug("eval crate suffix: %s",
@@ -50,10 +50,10 @@ fn eval_crate_directives_to_mod(cx: ctx, cdirs: [@ast::crate_directive],
 We build the path to the companion mod by combining the prefix and the
 optional suffix then adding the .rs extension.
 */
-fn parse_companion_mod(cx: ctx, prefix: str, suffix: option::t<str>)
+fn parse_companion_mod(cx: ctx, prefix: str, suffix: option<str>)
     -> ([@ast::view_item], [@ast::item], [ast::attribute]) {
 
-    fn companion_file(prefix: str, suffix: option::t<str>) -> str {
+    fn companion_file(prefix: str, suffix: option<str>) -> str {
         ret alt suffix {
           option::some(s) { fs::connect(prefix, s) }
           option::none { prefix }
index d2fbe02d63ad3ed15dd91034eb0a1734d7b2e91c..00bc73baeba8006893375916bef80059c64ceee3 100644 (file)
 
 impl reader for reader {
     fn is_eof() -> bool { self.curr == -1 as char }
-    fn get_str_from(start: uint) -> str {
+    fn get_str_from(start: uint) -> str unsafe {
         // I'm pretty skeptical about this subtraction. What if there's a
         // multi-byte character before the mark?
-        ret str::slice(*self.src, start - 1u, self.pos - 1u);
+        ret str::unsafe::slice_bytes(*self.src, start - 1u, self.pos - 1u);
     }
     fn next() -> char {
         if self.pos < self.len {
@@ -148,7 +148,7 @@ fn consume_block_comment(rdr: reader) {
     be consume_whitespace_and_comments(rdr);
 }
 
-fn scan_exponent(rdr: reader) -> option::t<str> {
+fn scan_exponent(rdr: reader) -> option<str> {
     let c = rdr.curr;
     let rslt = "";
     if c == 'e' || c == 'E' {
@@ -197,31 +197,31 @@ fn scan_number(c: char, rdr: reader) -> token::token {
     c = rdr.curr;
     n = rdr.next();
     if c == 'u' || c == 'i' {
-        let signed = c == 'i', tp = signed ? either::left(ast::ty_i)
-                                           : either::right(ast::ty_u);
+        let signed = c == 'i', tp = if signed { either::left(ast::ty_i) }
+                                         else { either::right(ast::ty_u) };
         rdr.bump();
         c = rdr.curr;
         if c == '8' {
             rdr.bump();
-            tp = signed ? either::left(ast::ty_i8)
-                        : either::right(ast::ty_u8);
+            tp = if signed { either::left(ast::ty_i8) }
+                      else { either::right(ast::ty_u8) };
         }
         n = rdr.next();
         if c == '1' && n == '6' {
             rdr.bump();
             rdr.bump();
-            tp = signed ? either::left(ast::ty_i16)
-                        : either::right(ast::ty_u16);
+            tp = if signed { either::left(ast::ty_i16) }
+                      else { either::right(ast::ty_u16) };
         } else if c == '3' && n == '2' {
             rdr.bump();
             rdr.bump();
-            tp = signed ? either::left(ast::ty_i32)
-                        : either::right(ast::ty_u32);
+            tp = if signed { either::left(ast::ty_i32) }
+                      else { either::right(ast::ty_u32) };
         } else if c == '6' && n == '4' {
             rdr.bump();
             rdr.bump();
-            tp = signed ? either::left(ast::ty_i64)
-                        : either::right(ast::ty_u64);
+            tp = if signed { either::left(ast::ty_i64) }
+                      else { either::right(ast::ty_u64) };
         }
         let parsed = u64::from_str(num_str, base as u64);
         alt tp {
@@ -328,10 +328,6 @@ fn binop(rdr: reader, op: token::binop) -> token::token {
 
 
       // One-byte tokens.
-      '?' {
-        rdr.bump();
-        ret token::QUES;
-      }
       ';' { rdr.bump(); ret token::SEMI; }
       ',' { rdr.bump(); ret token::COMMA; }
       '.' {
@@ -353,6 +349,7 @@ fn binop(rdr: reader, op: token::binop) -> token::token {
       '#' {
         rdr.bump();
         if rdr.curr == '<' { rdr.bump(); ret token::POUND_LT; }
+        if rdr.curr == '(' { rdr.bump(); ret token::POUND_LPAREN; }
         if rdr.curr == '{' { rdr.bump(); ret token::POUND_LBRACE; }
         ret token::POUND;
       }
@@ -365,6 +362,24 @@ fn binop(rdr: reader, op: token::binop) -> token::token {
         } else { ret token::COLON; }
       }
 
+      '$' {
+        rdr.bump();
+        if is_dec_digit(rdr.curr) {
+            let val = dec_digit_val(rdr.curr) as uint;
+            while is_dec_digit(rdr.next()) {
+                rdr.bump();
+                val = val * 10u + (dec_digit_val(rdr.curr) as uint);
+            }
+            rdr.bump();
+            ret token::DOLLAR_NUM(val);
+        } else if rdr.curr == '(' {
+            rdr.bump();
+            ret token::DOLLAR_LPAREN;
+        } else {
+            rdr.fatal("expected digit");
+        }
+      }
+
 
 
 
@@ -583,11 +598,12 @@ fn all_whitespace(s: str, begin: uint, end: uint) -> bool {
     ret true;
 }
 
-fn trim_whitespace_prefix_and_push_line(&lines: [str], s: str, col: uint) {
+fn trim_whitespace_prefix_and_push_line(&lines: [str],
+                                        s: str, col: uint) unsafe {
     let s1;
     if all_whitespace(s, 0u, col) {
         if col < str::byte_len(s) {
-            s1 = str::slice(s, col, str::byte_len(s));
+            s1 = str::unsafe::slice_bytes(s, col, str::byte_len(s));
         } else { s1 = ""; }
     } else { s1 = s; }
     log(debug, "pushing line: " + s1);
@@ -695,9 +711,12 @@ fn gather_comments_and_literals(cm: codemap::codemap,
         }
         let tok = next_token(rdr);
         if is_lit(tok.tok) {
-            literals += [{lit: rdr.get_str_from(tok.bpos), pos: tok.chpos}];
+            let s = rdr.get_str_from(tok.bpos);
+            literals += [{lit: s, pos: tok.chpos}];
+            log(debug, "tok lit: " + s);
+        } else {
+            log(debug, "tok: " + token::to_str(rdr, tok.tok));
         }
-        log(debug, "tok: " + token::to_str(rdr, tok.tok));
         first_read = false;
     }
     ret {cmnts: comments, lits: literals};
index a7bbddfee39419db492cd3c94363b8df5bb6abc2..0b321b17b92007e5900cdc7c4dd1cf0c8d436cec 100644 (file)
@@ -113,10 +113,11 @@ fn new_parser_from_file(sess: parse_sess, cfg: ast::crate_cfg, path: str,
 }
 
 fn new_parser_from_source_str(sess: parse_sess, cfg: ast::crate_cfg,
-                              name: str, source: @str) -> parser {
+                              name: str, ss: codemap::file_substr,
+                              source: @str) -> parser {
     let ftype = SOURCE_FILE;
-    let filemap = codemap::new_filemap(name, source,
-                                       sess.chpos, sess.byte_pos);
+    let filemap = codemap::new_filemap_w_substr
+        (name, ss, source, sess.chpos, sess.byte_pos);
     sess.cm.files += [filemap];
     let itr = @interner::mk(str::hash, str::eq);
     let rdr = lexer::new_reader(sess.cm, sess.span_diagnostic,
@@ -258,7 +259,7 @@ fn check_bad_word(p: parser) {
     }
 }
 
-fn parse_ty_fn(proto: ast::proto, p: parser) -> ast::ty_ {
+fn parse_ty_fn(p: parser) -> ast::fn_decl {
     fn parse_fn_input_ty(p: parser) -> ast::arg {
         let mode = parse_arg_mode(p);
         let name = if is_plain_ident(p) && p.look_ahead(1u) == token::COLON {
@@ -275,26 +276,22 @@ fn parse_fn_input_ty(p: parser) -> ast::arg {
     //  auto constrs = parse_constrs(~[], p);
     let constrs: [@ast::constr] = [];
     let (ret_style, ret_ty) = parse_ret_ty(p);
-    ret ast::ty_fn(proto, {inputs: inputs.node, output: ret_ty,
+    ret {inputs: inputs.node, output: ret_ty,
                            purity: ast::impure_fn, cf: ret_style,
-                           constraints: constrs});
+                           constraints: constrs};
 }
 
 fn parse_ty_methods(p: parser) -> [ast::ty_method] {
     parse_seq(token::LBRACE, token::RBRACE, seq_sep_none(), {|p|
+        let attrs = parse_outer_attributes(p);
         let flo = p.span.lo;
         expect_word(p, "fn");
         let ident = parse_method_name(p);
         let tps = parse_ty_params(p);
-        let f = parse_ty_fn(ast::proto_bare, p), fhi = p.last_span.hi;
+        let d = parse_ty_fn(p), fhi = p.last_span.hi;
         expect(p, token::SEMI);
-        alt f {
-          ast::ty_fn(_, d) {
-            {ident: ident, decl: d, tps: tps,
-             span: ast_util::mk_sp(flo, fhi)}
-          }
-        }
-    }, p).node
+            {ident: ident, attrs: attrs, decl: d, tps: tps,
+                    span: ast_util::mk_sp(flo, fhi)}}, p).node
 }
 
 fn parse_mt(p: parser) -> ast::mt {
@@ -423,6 +420,13 @@ fn parse_ret_ty(p: parser) -> (ast::ret_style, @ast::ty) {
 
 fn parse_ty(p: parser, colons_before_params: bool) -> @ast::ty {
     let lo = p.span.lo;
+
+    alt have_dollar(p) {
+      some(e) {ret @spanned(lo, p.span.hi,
+                            ast::ty_mac(spanned(lo, p.span.hi, e)))}
+      none {}
+    }
+
     let t: ast::ty_;
     // FIXME: do something with this
 
@@ -505,10 +509,10 @@ fn parse_ty(p: parser, colons_before_params: bool) -> @ast::ty {
           ast::proto_bare { p.warn("fn is deprecated, use native fn"); }
           _ { /* fallthrough */ }
         }
-        t = parse_ty_fn(proto, p);
+        t = ast::ty_fn(proto, parse_ty_fn(p));
     } else if eat_word(p, "native") {
         expect_word(p, "fn");
-        t = parse_ty_fn(ast::proto_bare, p);
+        t = ast::ty_fn(ast::proto_bare, parse_ty_fn(p));
     } else if p.token == token::MOD_SEP || is_ident(p.token) {
         let path = parse_path(p);
         t = ast::ty_path(path, p.get_id());
@@ -517,14 +521,19 @@ fn parse_ty(p: parser, colons_before_params: bool) -> @ast::ty {
 }
 
 fn parse_arg_mode(p: parser) -> ast::mode {
-    if eat(p, token::BINOP(token::AND)) { ast::by_mut_ref }
-    else if eat(p, token::BINOP(token::MINUS)) { ast::by_move }
-    else if eat(p, token::ANDAND) { ast::by_ref }
-    else if eat(p, token::BINOP(token::PLUS)) {
-        if eat(p, token::BINOP(token::PLUS)) { ast::by_val }
-        else { ast::by_copy }
-    }
-    else { ast::mode_infer }
+    if eat(p, token::BINOP(token::AND)) {
+        ast::expl(ast::by_mut_ref)
+    } else if eat(p, token::BINOP(token::MINUS)) {
+        ast::expl(ast::by_move)
+    } else if eat(p, token::ANDAND) {
+        ast::expl(ast::by_ref)
+    } else if eat(p, token::BINOP(token::PLUS)) {
+        if eat(p, token::BINOP(token::PLUS)) {
+            ast::expl(ast::by_val)
+        } else {
+            ast::expl(ast::by_copy)
+        }
+    } else { ast::infer(p.get_id()) }
 }
 
 fn parse_arg(p: parser) -> ast::arg {
@@ -538,12 +547,15 @@ fn parse_arg(p: parser) -> ast::arg {
 fn parse_fn_block_arg(p: parser) -> ast::arg {
     let m = parse_arg_mode(p);
     let i = parse_value_ident(p);
-    let t = eat(p, token::COLON) ? parse_ty(p, false) :
-        @spanned(p.span.lo, p.span.hi, ast::ty_infer);
+    let t = if eat(p, token::COLON) {
+                parse_ty(p, false)
+            } else {
+                @spanned(p.span.lo, p.span.hi, ast::ty_infer)
+            };
     ret {mode: m, ty: t, ident: i, id: p.get_id()};
 }
 
-fn parse_seq_to_before_gt<T: copy>(sep: option::t<token::token>,
+fn parse_seq_to_before_gt<T: copy>(sep: option<token::token>,
                                   f: fn(parser) -> T,
                                   p: parser) -> [T] {
     let first = true;
@@ -560,7 +572,7 @@ fn parse_seq_to_before_gt<T: copy>(sep: option::t<token::token>,
     ret v;
 }
 
-fn parse_seq_to_gt<T: copy>(sep: option::t<token::token>,
+fn parse_seq_to_gt<T: copy>(sep: option<token::token>,
                            f: fn(parser) -> T, p: parser) -> [T] {
     let v = parse_seq_to_before_gt(sep, f, p);
     expect_gt(p);
@@ -568,7 +580,7 @@ fn parse_seq_to_gt<T: copy>(sep: option::t<token::token>,
     ret v;
 }
 
-fn parse_seq_lt_gt<T: copy>(sep: option::t<token::token>,
+fn parse_seq_lt_gt<T: copy>(sep: option<token::token>,
                            f: fn(parser) -> T,
                            p: parser) -> spanned<[T]> {
     let lo = p.span.lo;
@@ -587,7 +599,7 @@ fn parse_seq_to_end<T: copy>(ket: token::token, sep: seq_sep,
 }
 
 type seq_sep = {
-    sep: option::t<token::token>,
+    sep: option<token::token>,
     trailing_opt: bool   // is trailing separator optional?
 };
 
@@ -629,6 +641,24 @@ fn parse_seq<T: copy>(bra: token::token, ket: token::token,
     ret spanned(lo, hi, result);
 }
 
+fn have_dollar(p: parser) -> option::t<ast::mac_> {
+    alt p.token {
+      token::DOLLAR_NUM(num) {
+        p.bump();
+        some(ast::mac_var(num))
+      }
+      token::DOLLAR_LPAREN {
+        let lo = p.span.lo;
+        p.bump();
+        let e = parse_expr(p);
+        expect(p, token::RPAREN);
+        let hi = p.last_span.hi;
+        some(ast::mac_aq(ast_util::mk_sp(lo,hi), e))
+      }
+      _ {none}
+    }
+}
+
 fn lit_from_token(p: parser, tok: token::token) -> ast::lit_ {
     alt tok {
       token::LIT_INT(i, it) { ast::lit_int(i, it) }
@@ -676,7 +706,12 @@ fn parse_path(p: parser) -> @ast::path {
 fn parse_path_and_ty_param_substs(p: parser, colons: bool) -> @ast::path {
     let lo = p.span.lo;
     let path = parse_path(p);
-    if colons ? eat(p, token::MOD_SEP) : p.token == token::LT {
+    let b = if colons {
+                eat(p, token::MOD_SEP)
+            } else {
+                p.token == token::LT
+            };
+    if b {
         let seq = parse_seq_lt_gt(some(token::COMMA),
                                   {|p| parse_ty(p, false)}, p);
         @spanned(lo, seq.span.hi, {types: seq.node with path.node})
@@ -751,6 +786,12 @@ fn parse_bottom_expr(p: parser) -> pexpr {
     let hi = p.span.hi;
 
     let ex: ast::expr_;
+
+    alt have_dollar(p) {
+      some(x) {ret pexpr(mk_mac_expr(p, lo, p.span.hi, x));}
+      _ {}
+    }
+
     if p.token == token::LPAREN {
         p.bump();
         if p.token == token::RPAREN {
@@ -839,9 +880,15 @@ fn parse_bottom_expr(p: parser) -> pexpr {
     } else if p.token == token::ELLIPSIS {
         p.bump();
         ret pexpr(mk_mac_expr(p, lo, p.span.hi, ast::mac_ellipsis));
+    } else if p.token == token::POUND_LPAREN {
+        p.bump();
+        let e = parse_expr(p);
+        expect(p, token::RPAREN);
+        ret pexpr(mk_mac_expr(p, lo, p.span.hi,
+                              ast::mac_qq(e.span, e)));
     } else if eat_word(p, "bind") {
         let e = parse_expr_res(p, RESTRICT_NO_CALL_EXPRS);
-        fn parse_expr_opt(p: parser) -> option::t<@ast::expr> {
+        fn parse_expr_opt(p: parser) -> option<@ast::expr> {
             alt p.token {
               token::UNDERSCORE { p.bump(); ret none; }
               _ { ret some(parse_expr(p)); }
@@ -951,15 +998,38 @@ fn parse_syntax_ext_naked(p: parser, lo: uint) -> @ast::expr {
     let pth = parse_path(p);
     //temporary for a backwards-compatible cycle:
     let sep = seq_sep(token::COMMA);
-    let es =
-        if p.token == token::LPAREN {
-            parse_seq(token::LPAREN, token::RPAREN, sep, parse_expr, p)
-        } else {
-            parse_seq(token::LBRACKET, token::RBRACKET, sep, parse_expr, p)
-        };
-    let hi = es.span.hi;
-    let e = mk_expr(p, es.span.lo, hi, ast::expr_vec(es.node, ast::imm));
-    ret mk_mac_expr(p, lo, hi, ast::mac_invoc(pth, e, none));
+    let e = none;
+    if (p.token == token::LPAREN || p.token == token::LBRACKET) {
+        let es =
+            if p.token == token::LPAREN {
+                parse_seq(token::LPAREN, token::RPAREN,
+                          sep, parse_expr, p)
+            } else {
+                parse_seq(token::LBRACKET, token::RBRACKET,
+                          sep, parse_expr, p)
+            };
+        let hi = es.span.hi;
+        e = some(mk_expr(p, es.span.lo, hi,
+                         ast::expr_vec(es.node, ast::imm)));
+    }
+    let b = none;
+    if p.token == token::LBRACE {
+        p.bump();
+        let lo = p.span.lo;
+        let depth = 1u;
+        while (depth > 0u) {
+            alt (p.token) {
+              token::LBRACE {depth += 1u;}
+              token::RBRACE {depth -= 1u;}
+              token::EOF {p.fatal("unexpected EOF in macro body");}
+              _ {}
+            }
+            p.bump();
+        }
+        let hi = p.last_span.lo;
+        b = some({span: mk_sp(lo,hi)});
+    }
+    ret mk_mac_expr(p, lo, p.span.hi, ast::mac_invoc(pth, e, b));
 }
 
 fn parse_dot_or_call_expr(p: parser) -> pexpr {
@@ -1089,18 +1159,6 @@ fn parse_prefix_expr(p: parser) -> pexpr {
     ret mk_pexpr(p, lo, hi, ex);
 }
 
-fn parse_ternary(p: parser) -> @ast::expr {
-    let cond_expr = parse_binops(p);
-    if p.token == token::QUES {
-        p.bump();
-        let then_expr = parse_expr(p);
-        expect(p, token::COLON);
-        let else_expr = parse_expr(p);
-        ret mk_expr(p, cond_expr.span.lo, else_expr.span.hi,
-                    ast::expr_ternary(cond_expr, then_expr, else_expr));
-    } else { ret cond_expr; }
-}
-
 type op_spec = {tok: token::token, op: ast::binop, prec: int};
 
 
@@ -1135,7 +1193,6 @@ fn parse_binops(p: parser) -> @ast::expr {
 const unop_prec: int = 100;
 
 const as_prec: int = 5;
-const ternary_prec: int = 0;
 
 fn parse_more_binops(p: parser, plhs: pexpr, min_prec: int) ->
    @ast::expr {
@@ -1166,7 +1223,7 @@ fn parse_more_binops(p: parser, plhs: pexpr, min_prec: int) ->
 
 fn parse_assign_expr(p: parser) -> @ast::expr {
     let lo = p.span.lo;
-    let lhs = parse_ternary(p);
+    let lhs = parse_binops(p);
     alt p.token {
       token::EQ {
         p.bump();
@@ -1211,13 +1268,13 @@ fn parse_assign_expr(p: parser) -> @ast::expr {
 fn parse_if_expr_1(p: parser) ->
    {cond: @ast::expr,
     then: ast::blk,
-    els: option::t<@ast::expr>,
+    els: option<@ast::expr>,
     lo: uint,
     hi: uint} {
     let lo = p.last_span.lo;
     let cond = parse_expr(p);
     let thn = parse_block(p);
-    let els: option::t<@ast::expr> = none;
+    let els: option<@ast::expr> = none;
     let hi = thn.span.hi;
     if eat_word(p, "else") {
         let elexpr = parse_else_expr(p);
@@ -1373,7 +1430,7 @@ fn parse_expr_res(p: parser, r: restriction) -> @ast::expr {
     ret e;
 }
 
-fn parse_initializer(p: parser) -> option::t<ast::initializer> {
+fn parse_initializer(p: parser) -> option<ast::initializer> {
     alt p.token {
       token::EQ {
         p.bump();
@@ -1504,7 +1561,11 @@ fn parse_pat(p: parser) -> @ast::pat {
                         _ { true }
                       } {
             let name = parse_path(p);
-            let sub = eat(p, token::AT) ? some(parse_pat(p)) : none;
+            let sub = if eat(p, token::AT) {
+                          some(parse_pat(p))
+                      } else {
+                          none
+                      };
             pat = ast::pat_ident(name, sub);
         } else {
             let enum_path = parse_path_and_ty_param_substs(p, true);
@@ -1546,7 +1607,11 @@ fn parse_local(p: parser, allow_init: bool) -> @ast::local {
 
 fn parse_let(p: parser) -> @ast::decl {
     fn parse_let_style(p: parser) -> ast::let_style {
-        eat(p, token::BINOP(token::AND)) ? ast::let_ref : ast::let_copy
+        if eat(p, token::BINOP(token::AND)) {
+            ast::let_ref
+        } else {
+            ast::let_copy
+        }
     }
     let lo = p.span.lo;
     let locals = [(parse_let_style(p), parse_local(p, true))];
@@ -1556,6 +1621,21 @@ fn parse_let_style(p: parser) -> ast::let_style {
     ret @spanned(lo, p.last_span.hi, ast::decl_local(locals));
 }
 
+fn parse_instance_var(p:parser) -> @ast::class_member {
+    let is_mut = ast::class_immutable;
+    expect_word(p, "let");
+    if eat_word(p, "mutable") {
+            is_mut = ast::class_mutable;
+    }
+    if !is_plain_ident(p) {
+        p.fatal("expecting ident");
+    }
+    let name = parse_ident(p);
+    expect(p, token::COLON);
+    let ty = parse_ty(p, false);
+    ret @ast::instance_var(name, ty, is_mut, p.get_id());
+}
+
 fn parse_stmt(p: parser, first_item_attrs: [ast::attribute]) -> @ast::stmt {
     fn check_expected_item(p: parser, current_attrs: [ast::attribute]) {
         // If we have attributes then we should have an item
@@ -1786,11 +1866,19 @@ fn parse_fn_decl(p: parser, purity: ast::purity)
 }
 
 fn parse_fn_block_decl(p: parser) -> ast::fn_decl {
-    let inputs = eat(p, token::OROR) ? [] :
-        parse_seq(token::BINOP(token::OR), token::BINOP(token::OR),
-                  seq_sep(token::COMMA), parse_fn_block_arg, p).node;
-    let output = eat(p, token::RARROW) ? parse_ty(p, false) :
-        @spanned(p.span.lo, p.span.hi, ast::ty_infer);
+    let inputs = if eat(p, token::OROR) {
+                     []
+                 } else {
+                     parse_seq(token::BINOP(token::OR),
+                               token::BINOP(token::OR),
+                               seq_sep(token::COMMA),
+                               parse_fn_block_arg, p).node
+                 };
+    let output = if eat(p, token::RARROW) {
+                     parse_ty(p, false)
+                 } else {
+                     @spanned(p.span.lo, p.span.hi, ast::ty_infer)
+                 };
     ret {inputs: inputs,
          output: output,
          purity: ast::impure_fn,
@@ -1838,22 +1926,23 @@ fn parse_method_name(p: parser) -> ast::ident {
 }
 
 fn parse_method(p: parser) -> @ast::method {
+    let attrs = parse_outer_attributes(p);
     let lo = p.span.lo;
     expect_word(p, "fn");
     let ident = parse_method_name(p);
     let tps = parse_ty_params(p);
     let decl = parse_fn_decl(p, ast::impure_fn);
-    let body = parse_block(p);
-    @{ident: ident, tps: tps, decl: decl, body: body,
+    let (inner_attrs, body) = parse_inner_attrs_and_block(p, true);
+    let attrs = attrs + inner_attrs;
+    @{ident: ident, attrs: attrs, tps: tps, decl: decl, body: body,
       id: p.get_id(), span: ast_util::mk_sp(lo, body.span.hi)}
 }
 
 fn parse_item_iface(p: parser, attrs: [ast::attribute]) -> @ast::item {
     let lo = p.last_span.lo, ident = parse_ident(p),
-        tps = parse_ty_params(p), meths = parse_ty_methods(p),
-        self_tp = {ident: "self", id: p.get_id(), bounds: @[]};
+        tps = parse_ty_params(p), meths = parse_ty_methods(p);
     ret mk_item(p, lo, p.last_span.hi, ident,
-                ast::item_iface(tps + [self_tp], meths), attrs);
+                ast::item_iface(tps, meths), attrs);
 }
 
 // Parses three variants (with the initial params always optional):
@@ -1900,8 +1989,8 @@ fn parse_item_res(p: parser, attrs: [ast::attribute]) -> @ast::item {
     let dtor = parse_block_no_value(p);
     let decl =
         {inputs:
-             [{mode: ast::by_ref, ty: t, ident: arg_ident,
-               id: p.get_id()}],
+             [{mode: ast::expl(ast::by_ref), ty: t,
+               ident: arg_ident, id: p.get_id()}],
          output: @spanned(lo, lo, ast::ty_nil),
          purity: ast::impure_fn,
          cf: ast::return_val,
@@ -1911,6 +2000,92 @@ fn parse_item_res(p: parser, attrs: [ast::attribute]) -> @ast::item {
                 attrs);
 }
 
+fn parse_item_class(p: parser, attrs: [ast::attribute]) -> @ast::item {
+    let lo = p.last_span.lo;
+    let class_name = parse_value_ident(p);
+    let ty_params = parse_ty_params(p);
+    expect(p, token::LBRACE);
+    let items: [@ast::class_item] = [];
+    let the_ctor : option<(ast::fn_decl, ast::blk)> = none;
+    while p.token != token::RBRACE {
+       alt parse_class_item(p) {
+            ctor_decl(a_fn_decl, blk) {
+                the_ctor = some((a_fn_decl, blk));
+            }
+            plain_decl(a_decl) {
+                items += [@{node: {privacy: ast::pub, decl: a_decl},
+                            span: p.last_span}];
+            }
+            priv_decls(some_decls) {
+                items += vec::map(some_decls, {|d|
+                            @{node: {privacy: ast::priv, decl: d},
+                                span: p.last_span}});
+            }
+       }
+    }
+    p.bump();
+    alt the_ctor {
+       some((ct_d, ct_b)) { ret mk_item(p, lo, p.last_span.hi, class_name,
+                     ast::item_class(ty_params, items, ct_d, ct_b), attrs); }
+       /*
+         Is it strange for the parser to check this?
+       */
+       none { /* parse error */ fail "Class with no ctor"; }
+    }
+}
+
+// lets us identify the constructor declaration at
+// parse time
+// we don't really want just the fn_decl...
+enum class_contents { ctor_decl(ast::fn_decl, ast::blk),
+                      // assumed to be public
+                      plain_decl(@ast::class_member),
+                      // contents of a priv section --
+                      // parse_class_item ensures that
+                      // none of these are a ctor decl
+                      priv_decls([@ast::class_member])}
+
+fn parse_class_item(p:parser) -> class_contents {
+    if eat_word(p, "new") {
+        // Can ctors have attrs?
+        let decl = parse_fn_decl(p, ast::impure_fn);
+        let body = parse_block(p);
+        ret ctor_decl(decl, body);
+    }
+    // TODO: refactor
+    else if eat_word(p, "priv") {
+            expect(p, token::LBRACE);
+            let results = [];
+            while p.token != token::RBRACE {
+               alt parse_item(p, []) {
+                 some(i) {
+                     results += [@ast::class_method(i)];
+                 }
+                 _ {
+                     let a_var = parse_instance_var(p);
+                     expect(p, token::SEMI);
+                     results += [a_var];
+                 }
+               }
+            }
+            p.bump();
+            ret priv_decls(results);
+    }
+    else {
+        // Probably need to parse attrs
+        alt parse_item(p, []) {
+         some(i) {
+             ret plain_decl(@ast::class_method(i));
+         }
+         _ {
+             let a_var = parse_instance_var(p);
+             expect(p, token::SEMI);
+             ret plain_decl(a_var);
+         }
+        }
+    }
+}
+
 fn parse_mod_items(p: parser, term: token::token,
                    first_item_attrs: [ast::attribute]) -> ast::_mod {
     // Shouldn't be any view items since we've already parsed an item attr
@@ -1920,6 +2095,7 @@ fn parse_mod_items(p: parser, term: token::token,
     while p.token != term {
         let attrs = initial_attrs + parse_outer_attributes(p);
         initial_attrs = [];
+        #debug["parse_mod_items: parse_item(attrs=%?)", attrs];
         alt parse_item(p, attrs) {
           some(i) { items += [i]; }
           _ {
@@ -1927,6 +2103,7 @@ fn parse_mod_items(p: parser, term: token::token,
                     token::to_str(p.reader, p.token) + "'");
           }
         }
+        #debug["parse_mod_items: attrs=%?", attrs];
     }
     ret {view_items: view_items, items: items};
 }
@@ -1955,18 +2132,6 @@ fn parse_item_mod(p: parser, attrs: [ast::attribute]) -> @ast::item {
     ret mk_item(p, lo, hi, id, ast::item_mod(m), attrs + inner_attrs.inner);
 }
 
-fn parse_item_native_type(p: parser, attrs: [ast::attribute]) ->
-   @ast::native_item {
-    let t = parse_type_decl(p);
-    let hi = p.span.hi;
-    expect(p, token::SEMI);
-    ret @{ident: t.ident,
-          attrs: attrs,
-          node: ast::native_item_ty,
-          id: p.get_id(),
-          span: ast_util::mk_sp(t.lo, hi)};
-}
-
 fn parse_item_native_fn(p: parser, attrs: [ast::attribute],
                         purity: ast::purity) -> @ast::native_item {
     let lo = p.last_span.lo;
@@ -1983,9 +2148,7 @@ fn parse_item_native_fn(p: parser, attrs: [ast::attribute],
 
 fn parse_native_item(p: parser, attrs: [ast::attribute]) ->
    @ast::native_item {
-    if eat_word(p, "type") {
-        ret parse_item_native_type(p, attrs);
-    } else if eat_word(p, "fn") {
+    if eat_word(p, "fn") {
         ret parse_item_native_fn(p, attrs, ast::impure_fn);
     } else if eat_word(p, "pure") {
         expect_word(p, "fn");
@@ -2135,7 +2298,7 @@ fn fn_expr_lookahead(tok: token::token) -> bool {
     }
 }
 
-fn parse_item(p: parser, attrs: [ast::attribute]) -> option::t<@ast::item> {
+fn parse_item(p: parser, attrs: [ast::attribute]) -> option<@ast::item> {
     if eat_word(p, "const") {
         ret some(parse_item_const(p, attrs));
     } else if eat_word(p, "inline") {
@@ -2165,12 +2328,15 @@ fn parse_item(p: parser, attrs: [ast::attribute]) -> option::t<@ast::item> {
         ret some(parse_item_impl(p, attrs));
     } else if eat_word(p, "resource") {
         ret some(parse_item_res(p, attrs));
-    } else { ret none; }
+    } else if eat_word(p, "class") {
+        ret some(parse_item_class(p, attrs));
+    }
+else { ret none; }
 }
 
 // A type to distingush between the parsing of item attributes or syntax
 // extensions, which both begin with token.POUND
-type attr_or_ext = option::t<either::t<[ast::attribute], @ast::expr>>;
+type attr_or_ext = option<either::t<[ast::attribute], @ast::expr>>;
 
 fn parse_outer_attrs_or_ext(
     p: parser,
@@ -2284,7 +2450,7 @@ fn parse_use(p: parser) -> ast::view_item_ {
 }
 
 fn parse_rest_import_name(p: parser, first: ast::ident,
-                          def_ident: option::t<ast::ident>) ->
+                          def_ident: option<ast::ident>) ->
    ast::view_item_ {
     let identifiers: [ast::ident] = [first];
     let glob: bool = false;
@@ -2487,16 +2653,29 @@ fn parse_crate_from_source_file(input: str, cfg: ast::crate_cfg,
 
 fn parse_expr_from_source_str(name: str, source: @str, cfg: ast::crate_cfg,
                               sess: parse_sess) -> @ast::expr {
-    let p = new_parser_from_source_str(sess, cfg, name, source);
+    let p = new_parser_from_source_str(sess, cfg, name, none, source);
     let r = parse_expr(p);
     sess.chpos = p.reader.chpos;
     sess.byte_pos = sess.byte_pos + p.reader.pos;
     ret r;
 }
 
+fn parse_from_source_str<T>(f: fn (p: parser) -> T,
+                            name: str, ss: codemap::file_substr,
+                            source: @str, cfg: ast::crate_cfg,
+                            sess: parse_sess)
+    -> T
+{
+    let p = new_parser_from_source_str(sess, cfg, name, ss, source);
+    let r = f(p);
+    sess.chpos = p.reader.chpos;
+    sess.byte_pos = sess.byte_pos + p.reader.pos;
+    ret r;
+}
+
 fn parse_crate_from_source_str(name: str, source: @str, cfg: ast::crate_cfg,
                                sess: parse_sess) -> @ast::crate {
-    let p = new_parser_from_source_str(sess, cfg, name, source);
+    let p = new_parser_from_source_str(sess, cfg, name, none, source);
     let r = parse_crate_mod(p, cfg);
     sess.chpos = p.reader.chpos;
     sess.byte_pos = sess.byte_pos + p.reader.pos;
index 0965697f8c8b3876b191443d2b0723a7e2993033..37ef677b6d6b6c9c3fe11605c0a110442730566a 100644 (file)
@@ -43,7 +43,6 @@ enum token {
     SEMI,
     COLON,
     MOD_SEP,
-    QUES,
     RARROW,
     LARROW,
     DARROW,
@@ -54,9 +53,13 @@ enum token {
     LBRACE,
     RBRACE,
     POUND,
+    POUND_LPAREN,
     POUND_LBRACE,
     POUND_LT,
 
+    DOLLAR_LPAREN,
+    DOLLAR_NUM(uint),
+
     /* Literals */
     LIT_INT(i64, ast::int_ty),
     LIT_UINT(u64, ast::uint_ty),
@@ -70,6 +73,7 @@ enum token {
     UNDERSCORE,
     BRACEQUOTE(str_num),
     EOF,
+
 }
 
 fn binop_to_str(o: binop) -> str {
@@ -114,7 +118,6 @@ fn to_str(r: reader, t: token) -> str {
       SEMI { ret ";"; }
       COLON { ret ":"; }
       MOD_SEP { ret "::"; }
-      QUES { ret "?"; }
       RARROW { ret "->"; }
       LARROW { ret "<-"; }
       DARROW { ret "<->"; }
@@ -125,9 +128,15 @@ fn to_str(r: reader, t: token) -> str {
       LBRACE { ret "{"; }
       RBRACE { ret "}"; }
       POUND { ret "#"; }
+      POUND_LPAREN { ret "#("; }
       POUND_LBRACE { ret "#{"; }
       POUND_LT { ret "#<"; }
 
+      DOLLAR_LPAREN { ret "$("; }
+      DOLLAR_NUM(u) {
+        ret "$" + uint::to_str(u as uint, 10u);
+      }
+
       /* Literals */
       LIT_INT(c, ast::ty_char) {
         // FIXME: escape.
index b8d42aa4ade77d6fcbc993d248b278fc15e0dfc6..864702d2ba1d1c495a372a949265ea05153fa2ee 100644 (file)
@@ -28,9 +28,9 @@ fn ignore(_node: ann_node) { }
 
 type ps =
     @{s: pp::printer,
-      cm: option::t<codemap>,
-      comments: option::t<[lexer::cmnt]>,
-      literals: option::t<[lexer::lit]>,
+      cm: option<codemap>,
+      comments: option<[lexer::cmnt]>,
+      literals: option<[lexer::lit]>,
       mutable cur_cmnt: uint,
       mutable cur_lit: uint,
       mutable boxes: [pp::breaks],
@@ -90,6 +90,10 @@ fn print_crate(cm: codemap, span_diagnostic: diagnostic::span_handler,
 
 fn item_to_str(i: @ast::item) -> str { be to_str(i, print_item); }
 
+fn typarams_to_str(tps: [ast::ty_param]) -> str {
+    be to_str(tps, print_type_params)
+}
+
 fn path_to_str(&&p: @ast::path) -> str {
     be to_str(p, bind print_path(_, _, false));
 }
@@ -132,7 +136,7 @@ fn res_to_str(decl: ast::fn_decl, name: ast::ident,
 fn test_res_to_str() {
     let decl: ast::fn_decl = {
         inputs: [{
-            mode: ast::by_val,
+            mode: ast::expl(ast::by_val),
             ty: @ast_util::respan(ast_util::dummy_sp(), ast::ty_bool),
             ident: "b",
             id: 0
@@ -336,17 +340,6 @@ fn print_type(s: ps, &&ty: @ast::ty) {
         word(s.s, "]");
       }
       ast::ty_ptr(mt) { word(s.s, "*"); print_mt(s, mt); }
-      ast::ty_task { word(s.s, "task"); }
-      ast::ty_port(t) {
-        word(s.s, "port<");
-        print_type(s, t);
-        word(s.s, ">");
-      }
-      ast::ty_chan(t) {
-        word(s.s, "chan<");
-        print_type(s, t);
-        word(s.s, ">");
-      }
       ast::ty_rec(fields) {
         word(s.s, "{");
         fn print_field(s: ps, f: ast::ty_field) {
@@ -370,12 +363,18 @@ fn print_field(s: ps, f: ast::ty_field) {
         print_ty_fn(s, some(proto), d, none, none);
       }
       ast::ty_path(path, _) { print_path(s, path, false); }
-      ast::ty_type { word(s.s, "type"); }
       ast::ty_constr(t, cs) {
         print_type(s, t);
         space(s.s);
         word(s.s, ast_ty_constrs_str(cs));
       }
+      ast::ty_mac(_) {
+          fail "print_type doesn't know how to print a ty_mac";
+      }
+      ast::ty_infer {
+          fail "print_type shouldn't see a ty_infer";
+      }
+
     }
     end(s);
 }
@@ -385,16 +384,6 @@ fn print_native_item(s: ps, item: @ast::native_item) {
     maybe_print_comment(s, item.span.lo);
     print_outer_attributes(s, item.attrs);
     alt item.node {
-      ast::native_item_ty {
-        ibox(s, indent_unit);
-        ibox(s, 0u);
-        word_nbsp(s, "type");
-        word(s.s, item.ident);
-        end(s); // end the inner ibox
-        word(s.s, ";");
-        end(s); // end the outer ibox
-
-      }
       ast::native_item_fn(decl, typarams) {
         print_fn(s, decl, item.ident, typarams);
         end(s); // end head-ibox
@@ -490,6 +479,52 @@ fn print_item(s: ps, &&item: @ast::item) {
             bclose(s, item.span);
         }
       }
+      ast::item_class(tps,items,ctor_decl,ctor_body) {
+          head(s, "class");
+          word_nbsp(s, item.ident);
+          print_type_params(s, tps);
+          bopen(s);
+          hardbreak_if_not_bol(s);
+          head(s, "new");
+          print_fn_args_and_ret(s, ctor_decl);
+          space(s.s);
+          print_block(s, ctor_body);
+          for ci in items {
+                  /*
+                     TODO: collect all private items and print them
+                     in a single "priv" section
+                   */
+             hardbreak_if_not_bol(s);
+             alt ci.node.privacy {
+                ast::priv {
+                    head(s, "priv");
+                    bopen(s);
+                    hardbreak_if_not_bol(s);
+                }
+                _ {}
+             }
+             alt *ci.node.decl {
+                 ast::instance_var(nm, t, mt, _) {
+                    word_nbsp(s, "let");
+                    alt mt {
+                      ast::class_mutable { word_nbsp(s, "mutable"); }
+                      _ {}
+                    }
+                    word(s.s, nm);
+                    word_nbsp(s, ":");
+                    print_type(s, t);
+                    word(s.s, ";");
+                }
+                ast::class_method(i) {
+                    print_item(s, i);
+                }
+             }
+             alt ci.node.privacy {
+                 ast::priv { bclose(s, ci.span); }
+                 _ {}
+             }
+          }
+       }
       ast::item_impl(tps, ifce, ty, methods) {
         head(s, "impl");
         word(s.s, item.ident);
@@ -510,17 +545,18 @@ fn print_item(s: ps, &&item: @ast::item) {
         for meth in methods {
             hardbreak_if_not_bol(s);
             maybe_print_comment(s, meth.span.lo);
+            print_outer_attributes(s, meth.attrs);
             print_fn(s, meth.decl, meth.ident, meth.tps);
             word(s.s, " ");
-            print_block(s, meth.body);
+            print_block_with_attrs(s, meth.body, meth.attrs);
         }
         bclose(s, item.span);
       }
       ast::item_iface(tps, methods) {
         head(s, "iface");
         word(s.s, item.ident);
-        print_type_params(s, vec::slice(tps, 0u, vec::len(tps) - 1u));
-        nbsp(s);
+        print_type_params(s, tps);
+        word(s.s, " ");
         bopen(s);
         for meth in methods { print_ty_method(s, meth); }
         bclose(s, item.span);
@@ -567,11 +603,10 @@ fn print_variant_arg(s: ps, arg: ast::variant_arg) {
 
 fn print_ty_method(s: ps, m: ast::ty_method) {
     hardbreak_if_not_bol(s);
-    cbox(s, indent_unit);
     maybe_print_comment(s, m.span.lo);
+    print_outer_attributes(s, m.attrs);
     print_ty_fn(s, none, m.decl, some(m.ident), some(m.tps));
     word(s.s, ";");
-    end(s);
 }
 
 fn print_outer_attributes(s: ps, attrs: [ast::attribute]) {
@@ -652,7 +687,6 @@ fn print_possibly_embedded_block_(s: ps, blk: ast::blk, embedded: embed_type,
       ast::unsafe_blk { word(s.s, "unsafe"); }
       ast::default_blk { }
     }
-
     maybe_print_comment(s, blk.span.lo);
     let ann_node = node_block(s, blk);
     s.ann.pre(ann_node);
@@ -693,21 +727,16 @@ fn print_maybe_parens_discrim(s: ps, e: @ast::expr) {
 }
 
 fn print_if(s: ps, test: @ast::expr, blk: ast::blk,
-            elseopt: option::t<@ast::expr>, chk: bool) {
+            elseopt: option<@ast::expr>, chk: bool) {
     head(s, "if");
     if chk { word_nbsp(s, "check"); }
     print_maybe_parens_discrim(s, test);
     space(s.s);
     print_block(s, blk);
-    fn do_else(s: ps, els: option::t<@ast::expr>) {
+    fn do_else(s: ps, els: option<@ast::expr>) {
         alt els {
           some(_else) {
             alt _else.node {
-
-
-
-
-
               // "another else-if"
               ast::expr_if(i, t, e) {
                 cbox(s, indent_unit - 1u);
@@ -718,11 +747,6 @@ fn do_else(s: ps, els: option::t<@ast::expr>) {
                 print_block(s, t);
                 do_else(s, e);
               }
-
-
-
-
-
               // "final else"
               ast::expr_block(b) {
                 cbox(s, indent_unit - 1u);
@@ -730,6 +754,10 @@ fn do_else(s: ps, els: option::t<@ast::expr>) {
                 word(s.s, " else ");
                 print_block(s, b);
               }
+              // BLEAH, constraints would be great here
+              _ {
+                  fail "print_if saw if with weird alternative";
+              }
             }
           }
           _ {/* fall through */ }
@@ -743,8 +771,11 @@ fn print_mac(s: ps, m: ast::mac) {
       ast::mac_invoc(path, arg, body) {
         word(s.s, "#");
         print_path(s, path, false);
-        alt arg.node { ast::expr_vec(_, _) { } _ { word(s.s, " "); } }
-        print_expr(s, arg);
+        alt arg {
+          some(@{node: ast::expr_vec(_, _), _}) { }
+          _ { word(s.s, " "); }
+        }
+        option::may(arg, bind print_expr(s, _));
         // FIXME: extension 'body'
       }
       ast::mac_embed_type(ty) {
@@ -756,6 +787,8 @@ fn print_mac(s: ps, m: ast::mac) {
         print_possibly_embedded_block(s, blk, block_normal, indent_unit);
       }
       ast::mac_ellipsis { word(s.s, "..."); }
+      ast::mac_var(v) { word(s.s, #fmt("$%u", v)); }
+      _ { /* fixme */ }
     }
 }
 
@@ -820,7 +853,7 @@ fn print_field(s: ps, field: ast::field) {
         }
       }
       ast::expr_bind(func, args) {
-        fn print_opt(s: ps, expr: option::t<@ast::expr>) {
+        fn print_opt(s: ps, expr: option<@ast::expr>) {
             alt expr {
               some(expr) { print_expr(s, expr); }
               _ { word(s.s, "_"); }
@@ -856,15 +889,6 @@ fn print_opt(s: ps, expr: option::t<@ast::expr>) {
       ast::expr_if_check(test, blk, elseopt) {
         print_if(s, test, blk, elseopt, true);
       }
-      ast::expr_ternary(test, then, els) {
-        print_expr(s, test);
-        space(s.s);
-        word_space(s, "?");
-        print_expr(s, then);
-        space(s.s);
-        word_space(s, ":");
-        print_expr(s, els);
-      }
       ast::expr_while(test, blk) {
         head(s, "while");
         print_maybe_parens_discrim(s, test);
@@ -1031,9 +1055,7 @@ fn print_opt(s: ps, expr: option::t<@ast::expr>) {
       }
       ast::expr_assert(expr) {
         word_nbsp(s, "assert");
-        popen(s);
         print_expr(s, expr);
-        pclose(s);
       }
       ast::expr_mac(m) { print_mac(s, m); }
     }
@@ -1045,8 +1067,8 @@ fn print_expr_parens_if_not_bot(s: ps, ex: @ast::expr) {
     let parens = alt ex.node {
       ast::expr_fail(_) | ast::expr_ret(_) |
       ast::expr_binary(_, _, _) | ast::expr_unary(_, _) |
-      ast::expr_ternary(_, _, _) | ast::expr_move(_, _) |
-      ast::expr_copy(_) | ast::expr_assign(_, _) | ast::expr_be(_) |
+      ast::expr_move(_, _) | ast::expr_copy(_) |
+      ast::expr_assign(_, _) | ast::expr_be(_) |
       ast::expr_assign_op(_, _, _) | ast::expr_swap(_, _) |
       ast::expr_log(_, _, _) | ast::expr_assert(_) |
       ast::expr_call(_, _, true) |
@@ -1258,17 +1280,22 @@ fn print_arg(s: ps, x: ast::arg) {
     maybe_print_comment(s, decl.output.span.lo);
 }
 
-fn print_arg_mode(s: ps, m: ast::mode) {
+fn mode_to_str(m: ast::mode) -> str {
     alt m {
-      ast::by_mut_ref { word(s.s, "&"); }
-      ast::by_move { word(s.s, "-"); }
-      ast::by_ref { word(s.s, "&&"); }
-      ast::by_val { word(s.s, "++"); }
-      ast::by_copy { word(s.s, "+"); }
-      ast::mode_infer {}
+      ast::expl(ast::by_mut_ref) { "&" }
+      ast::expl(ast::by_move) { "-" }
+      ast::expl(ast::by_ref) { "&&" }
+      ast::expl(ast::by_val) { "++" }
+      ast::expl(ast::by_copy) { "+" }
+      ast::infer(_) { "" }
     }
 }
 
+fn print_arg_mode(s: ps, m: ast::mode) {
+    let ms = mode_to_str(m);
+    if ms != "" { word(s.s, ms); }
+}
+
 fn print_bounds(s: ps, bounds: @[ast::ty_param_bound]) {
     if vec::len(*bounds) > 0u {
         word(s.s, ":");
@@ -1283,7 +1310,7 @@ fn print_bounds(s: ps, bounds: @[ast::ty_param_bound]) {
     }
 }
 
-fn print_type_params(s: ps, params: [ast::ty_param]) {
+fn print_type_params(s: ps, &&params: [ast::ty_param]) {
     if vec::len(params) > 0u {
         word(s.s, "<");
         fn printParam(s: ps, param: ast::ty_param) {
@@ -1396,7 +1423,6 @@ fn need_parens(expr: @ast::expr, outer_prec: int) -> bool {
     alt expr.node {
       ast::expr_binary(op, _, _) { operator_prec(op) < outer_prec }
       ast::expr_cast(_, _) { parse::parser::as_prec < outer_prec }
-      ast::expr_ternary(_, _, _) { parse::parser::ternary_prec < outer_prec }
       // This may be too conservative in some cases
       ast::expr_assign(_, _) { true }
       ast::expr_move(_, _) { true }
@@ -1432,8 +1458,8 @@ fn print_mt(s: ps, mt: ast::mt) {
 }
 
 fn print_ty_fn(s: ps, opt_proto: option<ast::proto>,
-               decl: ast::fn_decl, id: option::t<ast::ident>,
-               tps: option::t<[ast::ty_param]>) {
+               decl: ast::fn_decl, id: option<ast::ident>,
+               tps: option<[ast::ty_param]>) {
     ibox(s, indent_unit);
     word(s.s, opt_proto_to_str(opt_proto));
     alt id { some(id) { word(s.s, " "); word(s.s, id); } _ { } }
@@ -1463,7 +1489,7 @@ fn print_arg(s: ps, input: ast::arg) {
 }
 
 fn maybe_print_trailing_comment(s: ps, span: codemap::span,
-                                next_pos: option::t<uint>) {
+                                next_pos: option<uint>) {
     let cm;
     alt s.cm { some(ccm) { cm = ccm; } _ { ret; } }
     alt next_comment(s) {
@@ -1516,10 +1542,20 @@ fn print_literal(s: ps, &&lit: @ast::lit) {
         word(s.s, "'" + escape_str(str::from_char(ch as char), '\'') + "'");
       }
       ast::lit_int(i, t) {
-        word(s.s, int::str(i as int) + ast_util::int_ty_to_str(t));
+        if i < 0_i64 {
+            word(s.s,
+                 "-" + u64::to_str(-i as u64, 10u)
+                 + ast_util::int_ty_to_str(t));
+        } else {
+            word(s.s,
+                 u64::to_str(i as u64, 10u)
+                 + ast_util::int_ty_to_str(t));
+        }
       }
       ast::lit_uint(u, t) {
-        word(s.s, uint::str(u as uint) + ast_util::uint_ty_to_str(t));
+        word(s.s,
+             u64::to_str(u, 10u)
+             + ast_util::uint_ty_to_str(t));
       }
       ast::lit_float(f, t) {
         word(s.s, f + ast_util::float_ty_to_str(t));
@@ -1533,7 +1569,7 @@ fn print_literal(s: ps, &&lit: @ast::lit) {
 
 fn lit_to_str(l: @ast::lit) -> str { be to_str(l, print_literal); }
 
-fn next_lit(s: ps, pos: uint) -> option::t<lexer::lit> {
+fn next_lit(s: ps, pos: uint) -> option<lexer::lit> {
     alt s.literals {
       some(lits) {
         while s.cur_lit < vec::len(lits) {
@@ -1642,7 +1678,7 @@ fn to_str<T>(t: T, f: fn@(ps, T)) -> str {
     io::mem_buffer_str(buffer)
 }
 
-fn next_comment(s: ps) -> option::t<lexer::cmnt> {
+fn next_comment(s: ps) -> option<lexer::cmnt> {
     alt s.comments {
       some(cmnts) {
         if s.cur_cmnt < vec::len(cmnts) {
@@ -1758,8 +1794,8 @@ fn ends_in_lit_int(ex: @ast::expr) -> bool {
     alt ex.node {
       ast::expr_lit(@{node: ast::lit_int(_, ast::ty_i), _}) { true }
       ast::expr_binary(_, _, sub) | ast::expr_unary(_, sub) |
-      ast::expr_ternary(_, _, sub) | ast::expr_move(_, sub) |
-      ast::expr_copy(sub) | ast::expr_assign(_, sub) | ast::expr_be(sub) |
+      ast::expr_move(_, sub) | ast::expr_copy(sub) |
+      ast::expr_assign(_, sub) | ast::expr_be(sub) |
       ast::expr_assign_op(_, _, sub) | ast::expr_swap(_, sub) |
       ast::expr_log(_, _, sub) | ast::expr_assert(sub) |
       ast::expr_check(_, sub) { ends_in_lit_int(sub) }
index ba99519285954c5ea1d1f24d77f982a1ee5ae3f3..d868b7a97aa899bdbbd8e34729ab12335797c724 100644 (file)
@@ -54,7 +54,8 @@ fn tps_of_fn(fk: fn_kind) -> [ty_param] {
       visit_ty: fn@(@ty, E, vt<E>),
       visit_ty_params: fn@([ty_param], E, vt<E>),
       visit_constr: fn@(@path, span, node_id, E, vt<E>),
-      visit_fn: fn@(fn_kind, fn_decl, blk, span, node_id, E, vt<E>)};
+      visit_fn: fn@(fn_kind, fn_decl, blk, span, node_id, E, vt<E>),
+      visit_class_item: fn@(span, privacy, @class_member, E, vt<E>)};
 
 fn default_visitor<E>() -> visitor<E> {
     ret @{visit_mod: bind visit_mod::<E>(_, _, _, _, _),
@@ -71,7 +72,8 @@ fn default_visitor<E>() -> visitor<E> {
           visit_ty: bind skip_ty::<E>(_, _, _),
           visit_ty_params: bind visit_ty_params::<E>(_, _, _),
           visit_constr: bind visit_constr::<E>(_, _, _, _, _),
-          visit_fn: bind visit_fn::<E>(_, _, _, _, _, _, _)};
+          visit_fn: bind visit_fn::<E>(_, _, _, _, _, _, _),
+          visit_class_item: bind visit_class_item::<E>(_,_,_,_,_)};
 }
 
 fn visit_crate<E>(c: crate, e: E, v: vt<E>) {
@@ -135,6 +137,14 @@ fn visit_item<E>(i: @item, e: E, v: vt<E>) {
                        m.id, e, v);
         }
       }
+      item_class(tps, members, ctor_decl, ctor_blk) {
+          v.visit_ty_params(tps, e, v);
+          for m in members {
+             v.visit_class_item(m.span, m.node.privacy, m.node.decl, e, v);
+          }
+          visit_fn_decl(ctor_decl, e, v);
+          v.visit_block(ctor_blk, e, v);
+      }
       item_iface(tps, methods) {
         v.visit_ty_params(tps, e, v);
         for m in methods {
@@ -145,6 +155,18 @@ fn visit_item<E>(i: @item, e: E, v: vt<E>) {
     }
 }
 
+fn visit_class_item<E>(_s: span, _p: privacy, cm: @class_member,
+                       e:E, v:vt<E>) {
+    alt *cm {
+        instance_var(ident, t, mt, id) {
+            v.visit_ty(t, e, v);
+        }
+        class_method(i) {
+            v.visit_item(i, e, v);
+        }
+    }
+}
+
 fn skip_ty<E>(_t: @ty, _e: E, _v: vt<E>) {}
 
 fn visit_ty<E>(t: @ty, e: E, v: vt<E>) {
@@ -165,7 +187,6 @@ fn visit_ty<E>(t: @ty, e: E, v: vt<E>) {
         v.visit_ty(decl.output, e, v);
       }
       ty_path(p, _) { visit_path(p, e, v); }
-      ty_type {/* no-op */ }
       ty_constr(t, cs) {
         v.visit_ty(t, e, v);
         for tc: @spanned<constr_general_<@path, node_id>> in cs {
@@ -212,7 +233,6 @@ fn visit_native_item<E>(ni: @native_item, e: E, v: vt<E>) {
         v.visit_ty_params(tps, e, v);
         visit_fn_decl(fd, e, v);
       }
-      native_item_ty { }
     }
 }
 
@@ -265,7 +285,7 @@ fn visit_decl<E>(d: @decl, e: E, v: vt<E>) {
     }
 }
 
-fn visit_expr_opt<E>(eo: option::t<@expr>, e: E, v: vt<E>) {
+fn visit_expr_opt<E>(eo: option<@expr>, e: E, v: vt<E>) {
     alt eo { none { } some(ex) { v.visit_expr(ex, e, v); } }
 }
 
@@ -275,10 +295,14 @@ fn visit_exprs<E>(exprs: [@expr], e: E, v: vt<E>) {
 
 fn visit_mac<E>(m: mac, e: E, v: vt<E>) {
     alt m.node {
-      ast::mac_invoc(pth, arg, body) { visit_expr(arg, e, v); }
+      ast::mac_invoc(pth, arg, body) {
+        option::map(arg) {|arg| visit_expr(arg, e, v)}; }
       ast::mac_embed_type(ty) { v.visit_ty(ty, e, v); }
       ast::mac_embed_block(blk) { v.visit_block(blk, e, v); }
       ast::mac_ellipsis { }
+      ast::mac_qq(_, e) { /* FIXME: maybe visit */ }
+      ast::mac_aq(_, e) { /* FIXME: maybe visit */ }
+      ast::mac_var(_) { }
     }
 }
 
@@ -296,7 +320,7 @@ fn visit_expr<E>(ex: @expr, e: E, v: vt<E>) {
       }
       expr_bind(callee, args) {
         v.visit_expr(callee, e, v);
-        for eo: option::t<@expr> in args { visit_expr_opt(eo, e, v); }
+        for eo: option<@expr> in args { visit_expr_opt(eo, e, v); }
       }
       expr_binary(_, a, b) { v.visit_expr(a, e, v); v.visit_expr(b, e, v); }
       expr_unary(_, a) { v.visit_expr(a, e, v); }
@@ -312,11 +336,6 @@ fn visit_expr<E>(ex: @expr, e: E, v: vt<E>) {
         v.visit_block(b, e, v);
         visit_expr_opt(eo, e, v);
       }
-      expr_ternary(c, t, el) {
-        v.visit_expr(c, e, v);
-        v.visit_expr(t, e, v);
-        v.visit_expr(el, e, v);
-      }
       expr_while(x, b) { v.visit_expr(x, e, v); v.visit_block(b, e, v); }
       expr_for(dcl, x, b) {
         v.visit_local(dcl, e, v);
@@ -390,7 +409,8 @@ fn visit_arm<E>(a: arm, e: E, v: vt<E>) {
       visit_ty: fn@(@ty),
       visit_ty_params: fn@([ty_param]),
       visit_constr: fn@(@path, span, node_id),
-      visit_fn: fn@(fn_kind, fn_decl, blk, span, node_id)};
+      visit_fn: fn@(fn_kind, fn_decl, blk, span, node_id),
+      visit_class_item: fn@(span, privacy, @class_member)};
 
 fn simple_ignore_ty(_t: @ty) {}
 
@@ -410,7 +430,8 @@ fn default_simple_visitor() -> simple_visitor {
           visit_ty_params: fn@(_ps: [ty_param]) {},
           visit_constr: fn@(_p: @path, _sp: span, _id: node_id) { },
           visit_fn: fn@(_fk: fn_kind, _d: fn_decl, _b: blk, _sp: span,
-                        _id: node_id) { }
+                        _id: node_id) { },
+          visit_class_item: fn@(_s: span, _p: privacy, _c: @class_member) {}
          };
 }
 
@@ -485,6 +506,12 @@ fn v_fn(f: fn@(fn_kind, fn_decl, blk, span, node_id),
     } else {
         bind v_ty(v.visit_ty, _, _, _)
     };
+    fn v_class_item(f: fn@(span, privacy, @class_member),
+                    s:span, p:privacy, cm: @class_member, &&e: (),
+                    v: vt<()>) {
+        f(s, p, cm);
+        visit_class_item(s, p, cm, e, v);
+    }
     ret mk_vt(@{visit_mod: bind v_mod(v.visit_mod, _, _, _, _, _),
                 visit_view_item: bind v_view_item(v.visit_view_item, _, _, _),
                 visit_native_item:
@@ -500,7 +527,9 @@ fn v_fn(f: fn@(fn_kind, fn_decl, blk, span, node_id),
                 visit_ty: visit_ty,
                 visit_ty_params: bind v_ty_params(v.visit_ty_params, _, _, _),
                 visit_constr: bind v_constr(v.visit_constr, _, _, _, _, _),
-                visit_fn: bind v_fn(v.visit_fn, _, _, _, _, _, _, _)
+                visit_fn: bind v_fn(v.visit_fn, _, _, _, _, _, _, _),
+                visit_class_item: bind v_class_item(v.visit_class_item, _, _,
+                                                    _, _, _)
                });
 }
 
index 172afa35fe91c702e3698ea5ed31baab4a26620e..b96165fb4731092b7e59a9b5a7e3d0989b622ebd 100644 (file)
@@ -89,12 +89,10 @@ fn local_rhs_span(l: @ast::local, def: span) -> span {
     alt l.node.init { some(i) { ret i.expr.span; } _ { ret def; } }
 }
 
-fn is_main_name(path: [ast::ident]) -> bool {
-    str::eq(option::get(vec::last(path)), "main")
+fn is_main_name(path: middle::ast_map::path) -> bool {
+    option::get(vec::last(path)) == middle::ast_map::path_name("main")
 }
 
-
-
 //
 // Local Variables:
 // mode: rust
index 60df64a2a35135f166a0f2a84420bb81d8164263..0e4c3671bf118d5ccaa0251253eb6f7d8268d3e1 100644 (file)
@@ -18,9 +18,9 @@
 export get_cargo_root;
 export libdir;
 
-type pick<T> = fn(path: fs::path) -> option::t<T>;
+type pick<T> = fn(path: fs::path) -> option<T>;
 
-fn pick_file(file: fs::path, path: fs::path) -> option::t<fs::path> {
+fn pick_file(file: fs::path, path: fs::path) -> option<fs::path> {
     if fs::basename(path) == file { option::some(path) }
     else { option::none }
 }
@@ -32,7 +32,7 @@ fn pick_file(file: fs::path, path: fs::path) -> option::t<fs::path> {
     fn get_target_lib_file_path(file: fs::path) -> fs::path;
 }
 
-fn mk_filesearch(maybe_sysroot: option::t<fs::path>,
+fn mk_filesearch(maybe_sysroot: option<fs::path>,
                  target_triple: str,
                  addl_lib_search_paths: [fs::path]) -> filesearch {
     type filesearch_impl = {sysroot: fs::path,
@@ -64,7 +64,7 @@ fn get_target_lib_file_path(file: fs::path) -> fs::path {
 }
 
 // FIXME #1001: This can't be an obj method
-fn search<T: copy>(filesearch: filesearch, pick: pick<T>) -> option::t<T> {
+fn search<T: copy>(filesearch: filesearch, pick: pick<T>) -> option<T> {
     for lib_search_path in filesearch.lib_search_paths() {
         #debug("searching %s", lib_search_path);
         for path in fs::list_dir(lib_search_path) {
@@ -102,7 +102,7 @@ fn get_default_sysroot() -> fs::path {
     }
 }
 
-fn get_sysroot(maybe_sysroot: option::t<fs::path>) -> fs::path {
+fn get_sysroot(maybe_sysroot: option<fs::path>) -> fs::path {
     alt maybe_sysroot {
       option::some(sr) { sr }
       option::none { get_default_sysroot() }
index 2ae8a860a2709c2fc9deb7ccc11371b84478dc98..969195a40ac9c095646ed3eabc2dfe895a75fa2f 100644 (file)
@@ -4,36 +4,29 @@
 import middle::ty::*;
 import metadata::encoder;
 import syntax::print::pprust;
-import syntax::print::pprust::{path_to_str, constr_args_to_str, proto_to_str};
+import syntax::print::pprust::{path_to_str, constr_args_to_str, proto_to_str,
+                               mode_to_str};
 import syntax::{ast, ast_util};
 import middle::ast_map;
 
-fn mode_str(m: ty::mode) -> str {
-    alt m {
-      ast::by_ref { "&&" }
-      ast::by_val { "++" }
-      ast::by_mut_ref { "&" }
-      ast::by_move { "-" }
-      ast::by_copy { "+" }
-      _ { "" }
-    }
-}
-
 fn ty_to_str(cx: ctxt, typ: t) -> str {
-    fn fn_input_to_str(cx: ctxt, input: {mode: middle::ty::mode, ty: t}) ->
+    fn fn_input_to_str(cx: ctxt, input: {mode: ast::mode, ty: t}) ->
        str {
-        let modestr = alt input.mode {
-          ast::by_ref {
-            ty::type_is_immediate(cx, input.ty) ? "&&" : ""
-          }
-          ast::by_val {
-            ty::type_is_immediate(cx, input.ty) ? "" : "++"
+        let {mode, ty} = input;
+        let modestr = alt canon_mode(cx, mode) {
+          ast::infer(_) { "" }
+          ast::expl(m) {
+            if !ty::type_contains_vars(cx, ty) &&
+                m == ty::default_arg_mode_for_ty(cx, ty) {
+                ""
+            } else {
+                mode_to_str(ast::expl(m))
+            }
           }
-          _ { mode_str(input.mode) }
         };
-        modestr + ty_to_str(cx, input.ty)
+        modestr + ty_to_str(cx, ty)
     }
-    fn fn_to_str(cx: ctxt, proto: ast::proto, ident: option::t<ast::ident>,
+    fn fn_to_str(cx: ctxt, proto: ast::proto, ident: option<ast::ident>,
                  inputs: [arg], output: t, cf: ast::ret_style,
                  constrs: [@constr]) -> str {
         let s = proto_to_str(proto);
@@ -85,7 +78,6 @@ fn mt_to_str(cx: ctxt, m: mt) -> str {
       _ { }
     }
     ret alt struct(cx, typ) {
-      ty_native(_) { "native" }
       ty_nil { "()" }
       ty_bot { "_|_" }
       ty_bool { "bool" }
index bf56dea642b262f744ea97eceacd0793d05caf73..bb5e629ef624df9cf3054087063467cb6b7a3918 100644 (file)
@@ -24,9 +24,9 @@ enum mode { mode_compile_fail, mode_run_fail, mode_run_pass, mode_pretty, }
      stage_id: str,
      mode: mode,
      run_ignored: bool,
-     filter: option::t<str>,
-     runtool: option::t<str>,
-     rustcflags: option::t<str>,
+     filter: option<str>,
+     runtool: option<str>,
+     rustcflags: option<str>,
      verbose: bool};
 
 type cx = {config: config, procsrv: procsrv::handle};
index a86a94547f736a4fe308a8b1622c3b56076aa0ae..32f8762577f04ea97437a6e4b93d181bdc4d4f8a 100644 (file)
@@ -84,11 +84,11 @@ fn log_config(config: config) {
     logv(c, #fmt["\n"]);
 }
 
-fn opt_str(maybestr: option::t<str>) -> str {
+fn opt_str(maybestr: option<str>) -> str {
     alt maybestr { option::some(s) { s } option::none { "(none)" } }
 }
 
-fn str_opt(maybestr: str) -> option::t<str> {
+fn str_opt(maybestr: str) -> option<str> {
     if maybestr != "(none)" { option::some(maybestr) } else { option::none }
 }
 
index e0c4bf6b654c7fb26952cb95990bdf88962bdc5e..3703badf52793c1eb6b4898ccb5914ff69e54f6b 100644 (file)
@@ -22,7 +22,7 @@ fn load_errors(testfile: str) -> [expected_error] {
     ret error_patterns;
 }
 
-fn parse_expected(line_num: uint, line: str) -> [expected_error] {
+fn parse_expected(line_num: uint, line: str) -> [expected_error] unsafe {
     let error_tag = "//!";
     let idx0 = str::find(line, error_tag);
     if idx0 < 0 { ret []; }
@@ -41,11 +41,11 @@ fn parse_expected(line_num: uint, line: str) -> [expected_error] {
     while idx < len && line[idx] == (' ' as u8) { idx += 1u; }
     let start_kind = idx;
     while idx < len && line[idx] != (' ' as u8) { idx += 1u; }
-    let kind = str::to_lower(str::slice(line, start_kind, idx));
+    let kind = str::to_lower(str::unsafe::slice_bytes(line, start_kind, idx));
 
     // Extract msg:
     while idx < len && line[idx] == (' ' as u8) { idx += 1u; }
-    let msg = str::slice(line, idx, len);
+    let msg = str::unsafe::slice_bytes(line, idx, len);
 
     #debug("line=%u kind=%s msg=%s", line_num - adjust_line, kind, msg);
 
index 71968abdd6db15265d077e50d6181bea83dfb6f9..e09861141c4af425527abdbfb9dd788c11fc8a2e 100644 (file)
     // Lines that should be expected, in order, on standard out
     error_patterns: [str],
     // Extra flags to pass to the compiler
-    compile_flags: option::t<str>,
+    compile_flags: option<str>,
     // If present, the name of a file that this test should match when
     // pretty-printed
-    pp_exact: option::t<str>
+    pp_exact: option<str>
 };
 
 // Load any test directives embedded in the file
@@ -78,15 +78,15 @@ fn iter_header(testfile: str, it: fn(str)) {
     }
 }
 
-fn parse_error_pattern(line: str) -> option::t<str> {
+fn parse_error_pattern(line: str) -> option<str> {
     parse_name_value_directive(line, "error-pattern")
 }
 
-fn parse_compile_flags(line: str) -> option::t<str> {
+fn parse_compile_flags(line: str) -> option<str> {
     parse_name_value_directive(line, "compile-flags")
 }
 
-fn parse_pp_exact(line: str, testfile: str) -> option::t<str> {
+fn parse_pp_exact(line: str, testfile: str) -> option<str> {
     alt parse_name_value_directive(line, "pp-exact") {
       option::some(s) { option::some(s) }
       option::none {
@@ -104,12 +104,12 @@ fn parse_name_directive(line: str, directive: str) -> bool {
 }
 
 fn parse_name_value_directive(line: str,
-                              directive: str) -> option::t<str> {
+                              directive: str) -> option<str> unsafe {
     let keycolon = directive + ":";
     if str::find(line, keycolon) >= 0 {
         let colon = str::find(line, keycolon) as uint;
         let value =
-            str::slice(line, colon + str::byte_len(keycolon),
+            str::unsafe::slice_bytes(line, colon + str::byte_len(keycolon),
                        str::byte_len(line));
         #debug("%s: %s", directive,  value);
         option::some(value)
index 6f3fd87466a6c84cb632212f00be1caaca6124d9..4d01d299548ff4dff2b808f01782ba5dc15c9818 100644 (file)
@@ -26,7 +26,7 @@
 type reqchan = chan<request>;
 
 type handle =
-    {task: option::t<(task::task, port<task::task_notification>)>,
+    {task: option<(task::task, port<task::task_notification>)>,
      chan: reqchan};
 
 enum request { exec([u8], [u8], [[u8]], chan<response>), stop, }
@@ -54,7 +54,7 @@ fn close(handle: handle) {
 }
 
 fn run(handle: handle, lib_path: str, prog: str, args: [str],
-       input: option::t<str>) -> {status: int, out: str, err: str} {
+       input: option<str>) -> {status: int, out: str, err: str} {
     let p = port();
     let ch = chan(p);
     send(handle.chan,
@@ -69,7 +69,7 @@ fn run(handle: handle, lib_path: str, prog: str, args: [str],
     ret {status: status, out: output, err: errput};
 }
 
-fn writeclose(fd: fd_t, s: option::t<str>) {
+fn writeclose(fd: fd_t, s: option<str>) {
     if option::is_some(s) {
         let writer = io::fd_writer(fd, false);
         writer.write_str(option::get(s));
index d3d02f08977cc4fe5809bf2ffb18c9f2e77b2144..2ba4517c0e42fe542d756a30d3d50a7d6d3a3cdc 100644 (file)
@@ -199,7 +199,7 @@ fn check_error_patterns(props: test_props,
 
     let next_err_idx = 0u;
     let next_err_pat = props.error_patterns[next_err_idx];
-    for line: str in str::split(procres.stdout, '\n' as u8) {
+    for line: str in str::split(procres.stderr, '\n' as u8) {
         if str::find(line, next_err_pat) > 0 {
             #debug("found error pattern %s", next_err_pat);
             next_err_idx += 1u;
@@ -246,7 +246,7 @@ fn check_expected_errors(expected_errors: [errors::expected_error],
     //    filename:line1:col1: line2:col2: *warning:* msg
     // where line1:col1: is the starting point, line2:col2:
     // is the ending point, and * represents ANSI color codes.
-    for line: str in str::split(procres.stdout, '\n' as u8) {
+    for line: str in str::split(procres.stderr, '\n' as u8) {
         let was_expected = false;
         vec::iteri(expected_errors) {|i, ee|
             if !found_flags[i] {
@@ -298,7 +298,7 @@ fn exec_compiled_test(cx: cx, props: test_props, testfile: str) -> procres {
 
 fn compose_and_run(cx: cx, testfile: str,
                    make_args: fn@(config, str) -> procargs, lib_path: str,
-                   input: option::t<str>) -> procres {
+                   input: option<str>) -> procres {
     let procargs = make_args(cx.config, testfile);
     ret program_output(cx, testfile, lib_path, procargs.prog, procargs.args,
                        input);
@@ -334,9 +334,9 @@ fn make_run_args(config: config, _props: test_props, testfile: str) ->
     ret {prog: args[0], args: vec::slice(args, 1u, vec::len(args))};
 }
 
-fn split_maybe_args(argstr: option::t<str>) -> [str] {
+fn split_maybe_args(argstr: option<str>) -> [str] {
     fn rm_whitespace(v: [str]) -> [str] {
-        fn flt(&&s: str) -> option::t<str> {
+        fn flt(&&s: str) -> option<str> {
             if !is_whitespace(s) { option::some(s) } else { option::none }
         }
 
@@ -355,7 +355,7 @@ fn is_whitespace(s: str) -> bool {
 }
 
 fn program_output(cx: cx, testfile: str, lib_path: str, prog: str,
-                  args: [str], input: option::t<str>) -> procres {
+                  args: [str], input: option<str>) -> procres {
     let cmdline =
         {
             let cmdline = make_cmdline(lib_path, prog, args);
diff --git a/src/etc/apple-darwin.supp b/src/etc/apple-darwin.supp
new file mode 100644 (file)
index 0000000..7e2598f
--- /dev/null
@@ -0,0 +1,9 @@
+{
+   issue_1333_setenv_leak
+   Memcheck:Leak
+   fun:malloc_zone_malloc
+   ...
+   fun:setenv
+   fun:setenv__c_stack_shim
+   ...
+}
index 3f9bbca469cab6fb4315e63b6ccb2b281cb43f32..213aefa32e2457193633c3c1d089245ed8b7b2e0 100644 (file)
@@ -2,6 +2,6 @@
 --langmap=rust:.rs
 --regex-rust=/[ \t]*fn[ \t]+([a-zA-Z0-9_]+)/\1/f,function/
 --regex-rust=/[ \t]*type[ \t]+([a-zA-Z0-9_]+)/\1/T,types/
---regex-rust=/[ \t]*tag[ \t]+([a-zA-Z0-9_]+)/\1/T,types/
+--regex-rust=/[ \t]*enum[ \t]+([a-zA-Z0-9_]+)/\1/T,types/
 --regex-rust=/[ \t]*resource[ \t]+([a-zA-Z0-9_]+)/\1/T,types/
 --regex-rust=/[ \t]*mod[ \t]+([a-zA-Z0-9_]+)/\1/m,modules/
index 660c367991b6d341c9c552f039bfe4de62048fce..72785bfbbf6b5bfb504e43e63b420c2cae4a851b 100755 (executable)
@@ -14,7 +14,7 @@ do
     fi
 
     clang++ -emit-llvm -S -m$BITS -O3 -Isrc/rt/isaac -Isrc/rt/uthash \
-        -Isrc/rt/arch/$ARCH -fno-stack-protector \
+        -Isrc/rt/arch/$ARCH -Isrc/rt -fno-stack-protector \
         -o src/rt/intrinsics/intrinsics.$ARCH.ll.in \
         src/rt/intrinsics/intrinsics.cpp
     sed -i .orig \
index 3e91401d189911339e79aef82bc68f11da85bacd..e64ed4f30597c036aa07884c95f68404737b61b0 100755 (executable)
@@ -2,55 +2,61 @@
 
 # This script generates rust compatible makefiles from libuv. When upgrading
 # libuv, do:
+#
 # cd $RUST_DIR
-# rm -r mk/libuv
-# cd $LIBUV_DIR
-# git archive --prefix libuv/ $REVISION > libuv.tar.gz
-# cd $RUST_DIR/src/rt
-# rm -r libuv
-# tar -xvf $LIBUV_DIR/libuv.tar.gz
-# mkdir -p libuv/build
-# svn co http://gyp.googlecode.com/svn/trunk libuv/build/gyp
+# cd src/libuv
+# git checkout master
+# git pull
+# svn co http://gyp.googlecode.com/svn/trunk build/gyp
 # cd ../..
-# ./src/etc/gyp_uv
+# rm -r mk/libuv
+# ./src/etc/gyp-uv
+#
+# Note: you must not run gyp on windows. It will get the backslashes
+# incorrect in its rules, and not work.
 
 set -e
 
 cd `dirname $0`
 cd ../..
 
+GYPFILE=src/libuv/uv.gyp
+INCLUDES="-I src/libuv/common.gypi"
+
 for ARCH in ia32 x86_64
 do
-    args="--depth . -Dlibrary=static_library -Dtarget_arch=$ARCH"
+    ARGS="$GYPFILE \
+         $INCLUDES \
+         --depth . \
+         -Dcomponent=static_library \
+         -Dlibrary=static_library \
+         -Dtarget_arch=$ARCH"
     
-    ./src/libuv/build/gyp/gyp src/libuv/uv.gyp $args \
+    ./src/libuv/build/gyp/gyp $ARGS \
         -f make-mac \
         --generator-output mk/libuv/$ARCH/mac \
         -DOS=mac
 
-    ./src/libuv/build/gyp/gyp src/libuv/uv.gyp $args \
+    ./src/libuv/build/gyp/gyp $ARGS \
         -f make-linux \
         --generator-output mk/libuv/$ARCH/unix \
         -DOS=linux
 
-    ./src/libuv/build/gyp/gyp src/libuv/uv.gyp $args \
+    ./src/libuv/build/gyp/gyp $ARGS \
         -f make-linux \
         --generator-output mk/libuv/$ARCH/win \
         -DOS=win
 
-    # Comment out the gyp auto regeneration
-    for os in mac unix win; do
-        sed -i \
-            -e 's/^\(Makefile: $(srcdir)\/src\/rt\/libuv\/uv\.gyp\)/#\1/' \
-            mk/libuv/$ARCH/$os/Makefile
-
-        sed -i \
-            -e 's/^\(  $(call do_cmd,regen_makefile)\)/#\1/' \
-            mk/libuv/$ARCH/$os/Makefile
-    done
 done
 
 # On Mac, GYP hardcodes a -arch i386 into the output. Fix that.
 sed -i \
     -e 's/-arch i386/-arch x86_64/' \
     mk/libuv/x86_64/mac/src/libuv/*.mk
+
+MKFILES=$(find mk/libuv -name \*.mk -o -name Makefile)
+
+# Comment out the gyp auto regeneration
+perl -i -p -e 's@^(Makefile:.*)@#\1@go' $MKFILES
+perl -i -p -e 's@^(Makefile:.*)@#\1@go' $MKFILES
+perl -i -p -e 's@(.*regen_makefile.*)@#\1@go' $MKFILES
diff --git a/src/etc/pkg/rust.nsi b/src/etc/pkg/rust.nsi
deleted file mode 100644 (file)
index 7410b71..0000000
+++ /dev/null
@@ -1,396 +0,0 @@
-# -*- shell-script -*-
-# (not really, but syntax is similar)
-#
-# This is a NSIS win32 installer script the Rust toolchain.
-#
-
-# FIXME: EnvVarUpdate belongs in its own file but I'm having a hard time figuring
-# out how to make !include look in the directory I want it to.
-
-/**
- *  EnvVarUpdate.nsh
- *    : Environmental Variables: append, prepend, and remove entries
- *
- *     WARNING: If you use StrFunc.nsh header then include it before this file
- *              with all required definitions. This is to avoid conflicts
- *
- *  Usage:
- *    ${EnvVarUpdate} "ResultVar" "EnvVarName" "Action" "RegLoc" "PathString"
- *
- *  Credits:
- *  Version 1.0 
- *  * Cal Turney (turnec2)
- *  * Amir Szekely (KiCHiK) and e-circ for developing the forerunners of this
- *    function: AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar,
- *    WriteEnvStr, and un.DeleteEnvStr
- *  * Diego Pedroso (deguix) for StrTok
- *  * Kevin English (kenglish_hi) for StrContains
- *  * Hendri Adriaens (Smile2Me), Diego Pedroso (deguix), and Dan Fuhry  
- *    (dandaman32) for StrReplace
- *
- *  Version 1.1 (compatibility with StrFunc.nsh)
- *  * techtonik
- *
- *  http://nsis.sourceforge.net/Environmental_Variables:_append%2C_prepend%2C_and_remove_entries
- *
- */
-!ifndef ENVVARUPDATE_FUNCTION
-!define ENVVARUPDATE_FUNCTION
-!verbose push
-!verbose 3
-!include "LogicLib.nsh"
-!include "WinMessages.NSH"
-!include "StrFunc.nsh"
-; ---- Fix for conflict if StrFunc.nsh is already includes in main file -----------------------
-!macro _IncludeStrFunction StrFuncName
-  !ifndef ${StrFuncName}_INCLUDED
-    ${${StrFuncName}}
-  !endif
-  !ifndef Un${StrFuncName}_INCLUDED
-    ${Un${StrFuncName}}
-  !endif
-  !define un.${StrFuncName} "${Un${StrFuncName}}"
-!macroend
-!insertmacro _IncludeStrFunction StrTok
-!insertmacro _IncludeStrFunction StrStr
-!insertmacro _IncludeStrFunction StrRep
-; ---------------------------------- Macro Definitions ----------------------------------------
-!macro _EnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString
-  Push "${EnvVarName}"
-  Push "${Action}"
-  Push "${RegLoc}"
-  Push "${PathString}"
-    Call EnvVarUpdate
-  Pop "${ResultVar}"
-!macroend
-!define EnvVarUpdate '!insertmacro "_EnvVarUpdateConstructor"'
-!macro _unEnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString
-  Push "${EnvVarName}"
-  Push "${Action}"
-  Push "${RegLoc}"
-  Push "${PathString}"
-    Call un.EnvVarUpdate
-  Pop "${ResultVar}"
-!macroend
-!define un.EnvVarUpdate '!insertmacro "_unEnvVarUpdateConstructor"'
-; ---------------------------------- Macro Definitions end-------------------------------------
-;----------------------------------- EnvVarUpdate start----------------------------------------
-!define hklm_all_users     'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"'
-!define hkcu_current_user  'HKCU "Environment"'
-!macro EnvVarUpdate UN
-Function ${UN}EnvVarUpdate
-  Push $0
-  Exch 4
-  Exch $1
-  Exch 3
-  Exch $2
-  Exch 2
-  Exch $3
-  Exch
-  Exch $4
-  Push $5
-  Push $6
-  Push $7
-  Push $8
-  Push $9
-  Push $R0
-  /* After this point:
-  -------------------------
-     $0 = ResultVar     (returned)
-     $1 = EnvVarName    (input)
-     $2 = Action        (input)
-     $3 = RegLoc        (input)
-     $4 = PathString    (input)
-     $5 = Orig EnvVar   (read from registry)
-     $6 = Len of $0     (temp)
-     $7 = tempstr1      (temp)
-     $8 = Entry counter (temp)
-     $9 = tempstr2      (temp)
-     $R0 = tempChar     (temp)  */
-  ; Step 1:  Read contents of EnvVarName from RegLoc
-  ;
-  ; Check for empty EnvVarName
-  ${If} $1 == ""
-    SetErrors
-    DetailPrint "ERROR: EnvVarName is blank"
-    Goto EnvVarUpdate_Restore_Vars
-  ${EndIf}
-  ; Check for valid Action
-  ${If}    $2 != "A"
-  ${AndIf} $2 != "P"
-  ${AndIf} $2 != "R"
-    SetErrors
-    DetailPrint "ERROR: Invalid Action - must be A, P, or R"
-    Goto EnvVarUpdate_Restore_Vars
-  ${EndIf}
-  ${If} $3 == HKLM
-    ReadRegStr $5 ${hklm_all_users} $1     ; Get EnvVarName from all users into $5
-  ${ElseIf} $3 == HKCU
-    ReadRegStr $5 ${hkcu_current_user} $1  ; Read EnvVarName from current user into $5
-  ${Else}
-    SetErrors
-    DetailPrint 'ERROR: Action is [$3] but must be "HKLM" or HKCU"'
-    Goto EnvVarUpdate_Restore_Vars
-  ${EndIf}
-  ; Check for empty PathString
-  ${If} $4 == ""
-    SetErrors
-    DetailPrint "ERROR: PathString is blank"
-    Goto EnvVarUpdate_Restore_Vars
-  ${EndIf}
-  ; Make sure we've got some work to do
-  ${If} $5 == ""
-  ${AndIf} $2 == "R"
-    SetErrors
-    DetailPrint "$1 is empty - Nothing to remove"
-    Goto EnvVarUpdate_Restore_Vars
-  ${EndIf}
-  ; Step 2: Scrub EnvVar
-  ;
-  StrCpy $0 $5                             ; Copy the contents to $0
-  ; Remove spaces around semicolons (NOTE: spaces before the 1st entry or
-  ; after the last one are not removed here but instead in Step 3)
-  ${If} $0 != ""                           ; If EnvVar is not empty ...
-    ${Do}
-      ${${UN}StrStr} $7 $0 " ;"
-      ${If} $7 == ""
-        ${ExitDo}
-      ${EndIf}
-      ${${UN}StrRep} $0  $0 " ;" ";"         ; Remove '<space>;'
-    ${Loop}
-    ${Do}
-      ${${UN}StrStr} $7 $0 "; "
-      ${If} $7 == ""
-        ${ExitDo}
-      ${EndIf}
-      ${${UN}StrRep} $0  $0 "; " ";"         ; Remove ';<space>'
-    ${Loop}
-    ${Do}
-      ${${UN}StrStr} $7 $0 ";;" 
-      ${If} $7 == ""
-        ${ExitDo}
-      ${EndIf}
-      ${${UN}StrRep} $0  $0 ";;" ";"
-    ${Loop}
-    ; Remove a leading or trailing semicolon from EnvVar
-    StrCpy  $7  $0 1 0
-    ${If} $7 == ";"
-      StrCpy $0  $0 "" 1                   ; Change ';<EnvVar>' to '<EnvVar>'
-    ${EndIf}
-    StrLen $6 $0
-    IntOp $6 $6 - 1
-    StrCpy $7  $0 1 $6
-    ${If} $7 == ";"
-     StrCpy $0  $0 $6                      ; Change ';<EnvVar>' to '<EnvVar>'
-    ${EndIf}
-    ; DetailPrint "Scrubbed $1: [$0]"      ; Uncomment to debug
-  ${EndIf}
-  /* Step 3. Remove all instances of the target path/string (even if "A" or "P")
-     $6 = bool flag (1 = found and removed PathString)
-     $7 = a string (e.g. path) delimited by semicolon(s)
-     $8 = entry counter starting at 0
-     $9 = copy of $0
-     $R0 = tempChar      */
-  ${If} $5 != ""                           ; If EnvVar is not empty ...
-    StrCpy $9 $0
-    StrCpy $0 ""
-    StrCpy $8 0
-    StrCpy $6 0
-    ${Do}
-      ${${UN}StrTok} $7 $9 ";" $8 "0"      ; $7 = next entry, $8 = entry counter
-      ${If} $7 == ""                       ; If we've run out of entries,
-        ${ExitDo}                          ;    were done
-      ${EndIf}                             ;
-      ; Remove leading and trailing spaces from this entry (critical step for Action=Remove)
-      ${Do}
-        StrCpy $R0  $7 1
-        ${If} $R0 != " "
-          ${ExitDo}
-        ${EndIf}
-        StrCpy $7   $7 "" 1                ;  Remove leading space
-      ${Loop}
-      ${Do}
-        StrCpy $R0  $7 1 -1
-        ${If} $R0 != " "
-          ${ExitDo}
-        ${EndIf}
-        StrCpy $7   $7 -1                  ;  Remove trailing space
-      ${Loop}
-      ${If} $7 == $4                       ; If string matches, remove it by not appending it
-        StrCpy $6 1                        ; Set 'found' flag
-      ${ElseIf} $7 != $4                   ; If string does NOT match
-      ${AndIf}  $0 == ""                   ;    and the 1st string being added to $0,
-        StrCpy $0 $7                       ;    copy it to $0 without a prepended semicolon
-      ${ElseIf} $7 != $4                   ; If string does NOT match
-      ${AndIf}  $0 != ""                   ;    and this is NOT the 1st string to be added to $0,
-        StrCpy $0 $0;$7                    ;    append path to $0 with a prepended semicolon
-      ${EndIf}                             ;
-      IntOp $8 $8 + 1                      ; Bump counter
-    ${Loop}                                ; Check for duplicates until we run out of paths
-  ${EndIf}
-  ; Step 4:  Perform the requested Action
-  ;
-  ${If} $2 != "R"                          ; If Append or Prepend
-    ${If} $6 == 1                          ; And if we found the target
-      DetailPrint "Target is already present in $1. It will be removed and"
-    ${EndIf}
-    ${If} $0 == ""                         ; If EnvVar is (now) empty
-      StrCpy $0 $4                         ;   just copy PathString to EnvVar
-      ${If} $6 == 0                        ; If found flag is either 0
-      ${OrIf} $6 == ""                     ; or blank (if EnvVarName is empty)
-        DetailPrint "$1 was empty and has been updated with the target"
-      ${EndIf}
-    ${ElseIf} $2 == "A"                    ;  If Append (and EnvVar is not empty),
-      StrCpy $0 $0;$4                      ;     append PathString
-      ${If} $6 == 1
-        DetailPrint "appended to $1"
-      ${Else}
-        DetailPrint "Target was appended to $1"
-      ${EndIf}
-    ${Else}                                ;  If Prepend (and EnvVar is not empty),
-      StrCpy $0 $4;$0                      ;     prepend PathString
-      ${If} $6 == 1
-        DetailPrint "prepended to $1"
-      ${Else}
-        DetailPrint "Target was prepended to $1"
-      ${EndIf}
-    ${EndIf}
-  ${Else}                                  ; If Action = Remove
-    ${If} $6 == 1                          ;   and we found the target
-      DetailPrint "Target was found and removed from $1"
-    ${Else}
-      DetailPrint "Target was NOT found in $1 (nothing to remove)"
-    ${EndIf}
-    ${If} $0 == ""
-      DetailPrint "$1 is now empty"
-    ${EndIf}
-  ${EndIf}
-  ; Step 5:  Update the registry at RegLoc with the updated EnvVar and announce the change
-  ;
-  ClearErrors
-  ${If} $3  == HKLM
-    WriteRegExpandStr ${hklm_all_users} $1 $0     ; Write it in all users section
-  ${ElseIf} $3 == HKCU
-    WriteRegExpandStr ${hkcu_current_user} $1 $0  ; Write it to current user section
-  ${EndIf}
-  IfErrors 0 +4
-    MessageBox MB_OK|MB_ICONEXCLAMATION "Could not write updated $1 to $3"
-    DetailPrint "Could not write updated $1 to $3"
-    Goto EnvVarUpdate_Restore_Vars
-  ; "Export" our change
-  SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
-  EnvVarUpdate_Restore_Vars:
-  ;
-  ; Restore the user's variables and return ResultVar
-  Pop $R0
-  Pop $9
-  Pop $8
-  Pop $7
-  Pop $6
-  Pop $5
-  Pop $4
-  Pop $3
-  Pop $2
-  Pop $1
-  Push $0  ; Push my $0 (ResultVar)
-  Exch
-  Pop $0   ; Restore his $0
-FunctionEnd
-!macroend   ; EnvVarUpdate UN
-!insertmacro EnvVarUpdate ""
-!insertmacro EnvVarUpdate "un."
-;----------------------------------- EnvVarUpdate end----------------------------------------
-!verbose pop
-!endif
-
-
-Name "Rust"
-ShowInstDetails "show"
-ShowUninstDetails "show"
-SetCompressor "lzma"
-LicenseForceSelection checkbox
-
-InstallDir $PROGRAMFILES\Rust
-
-Page license
-Page directory
-Page instfiles
-UninstPage uninstConfirm
-UninstPage instfiles
-
-Section "Compiler"
-    SetOutPath $INSTDIR
-    File /nonfatal /r i686-pc-mingw32\stage3\*.*
-SectionEnd
-
-Section "Documentation"
-    SetOutPath $INSTDIR\doc
-    File /nonfatal /oname=rust.html doc\rust.html
-    File /nonfatal /oname=rust.pdf  doc\rust.pdf
-SectionEnd
-
-Section "SystemPath"
-    ${EnvVarUpdate} $0 "PATH" "A" "HKLM" "$INSTDIR\bin"
-SectionEnd
-
-Section "Uninstall"
-    Delete $INSTDIR\uninstall.exe
-    Delete $INSTDIR\bin\*.*
-    Delete $INSTDIR\bin\rustc\i686-pc-mingw32\bin\*.*
-    Delete $INSTDIR\doc\rust.html
-    Delete $INSTDIR\doc\rust.pdf
-    RMDir $INSTDIR\bin\rustc\i686-pc-mingw32\bin
-    RMDir $INSTDIR\bin\rustc\i686-pc-mingw32
-    RMDir $INSTDIR\bin\rustc
-    RMDir $INSTDIR\bin
-    RMDir $INSTDIR\doc
-    RMDir $INSTDIR
-    DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Rust"
-    ${un.EnvVarUpdate} $0 "PATH" "R" "HKLM" "$INSTDIR\bin"
-SectionEnd
-
-Section
-    WriteUninstaller $INSTDIR\uninstall.exe
-    WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Rust" \
-                     "DisplayName" "Rust"
-    WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Rust" \
-                     "Publisher" "Mozilla"
-    WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Rust" \
-                       "NoModify" 1
-    WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Rust" \
-                     "UninstallString" "$\"$INSTDIR\uninstall.exe$\""
-    WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Rust" \
-                     "QuietUninstallString" "$\"$INSTDIR\uninstall.exe$\" /S"
-SectionEnd
index 7c9e611c9c1e3288cc36a077f25e7cabbf59c777..7748f8f3261086f924c2278b2bb90ed38a4af9bd 100644 (file)
    libuv-0-byte-realloc1
    Memcheck:Leak
    fun:malloc
-   fun:realloc
-   fun:ev_realloc_emul
-   fun:ev_realloc
-   fun:epoll_destroy
-   fun:ev_loop_destroy
+   ...
    fun:uv_loop_delete
 }
 
    libuv-0-byte-realloc2
    Memcheck:Leak
    fun:malloc
-   fun:realloc
-   fun:ev_realloc_emul
-   fun:ev_realloc
-   fun:ev_loop_destroy
+   ...
    fun:uv_loop_delete
 }
index 7d5156a95a00503bf127d195815a4b3843ba1fee..a5cfb8db3f7cf966d73814c1ea39b426abd60d00 100644 (file)
@@ -283,10 +283,10 @@ fn check_variants_T<T: copy>(
     }
 }
 
-fn last_part(filename: str) -> str {
+fn last_part(filename: str) -> str unsafe {
   let ix = str::rindex(filename, 47u8 /* '/' */);
   assert ix >= 0;
-  str::slice(filename, ix as uint + 1u, str::byte_len(filename) - 3u)
+  str::unsafe::slice_bytes(filename, ix as uint + 1u, str::byte_len(filename) - 3u)
 }
 
 enum happiness { passed, cleanly_rejected(str), known_bug(str), failed(str), }
index 3d7fa5ec3e8a74b29f00a465a6892f2ce3689a55..21028655626c55c617ea4aaec3f1d4aeee16feb0 100644 (file)
   brief = "Convert a char to the corresponding digit. Returns none when \
            character is not a valid hexadecimal digit."
 )]
-pure fn maybe_digit(c: char) -> option::t<u8> {
+pure fn maybe_digit(c: char) -> option<u8> {
     alt c {
       '0' to '9' { option::some(c as u8 - ('0' as u8)) }
       'a' to 'z' { option::some(c as u8 + 10u8 - ('a' as u8)) }
index ef0f4bb8d8659cf57f8b32759fdb26f8197b2f58..81548f445d901b39815e5854be5093d2b1fcd8bf 100644 (file)
 export chan::{};
 export port::{};
 
+enum rust_port {}
+
 #[abi = "cdecl"]
 native mod rustrt {
-    type rust_port;
-
     fn chan_id_send<T: send>(t: *sys::type_desc,
                             target_task: task::task, target_port: port_id,
                             data: T) -> ctypes::uintptr_t;
@@ -72,7 +72,7 @@ enum chan<T: send> {
     chan_t(task::task, port_id)
 }
 
-resource port_ptr<T: send>(po: *rustrt::rust_port) {
+resource port_ptr<T: send>(po: *rust_port) {
     // Once the port is detached it's guaranteed not to receive further
     // messages
     rustrt::rust_port_detach(po);
@@ -127,13 +127,13 @@ fn recv<T: send>(p: port<T>) -> T { recv_(***p) }
 #[doc(
   brief = "Receive on a raw port pointer"
 )]
-fn recv_<T: send>(p: *rustrt::rust_port) -> T {
+fn recv_<T: send>(p: *rust_port) -> T {
     // FIXME: Due to issue 1185 we can't use a return pointer when
     // calling C code, and since we can't create our own return
     // pointer on the stack, we're going to call a little intrinsic
     // that will grab the value of the return pointer, then call this
     // function, which we will then use to call the runtime.
-    fn recv(dptr: *uint, port: *rustrt::rust_port,
+    fn recv(dptr: *uint, port: *rust_port,
             yield: *ctypes::uintptr_t,
             killed: *ctypes::uintptr_t) unsafe {
         rustrt::port_recv(dptr, port, yield, killed);
index b90c1c16d1a8a589ab9c04188dc9534af1f4b1af..3bc5a031949371d0f0faf6b02ee74baa40747db3 100644 (file)
@@ -30,7 +30,7 @@ This behavior can be disabled with the `no_core` crate attribute."
 
 export box, char, float, bessel, f32, f64, int, str, ptr;
 export uint, u8, u32, u64, vec, bool;
-export either, option, result;
+export either, option, result, iter;
 export ctypes, sys, unsafe, comm, task, logging;
 export extfmt;
 export math;
@@ -64,7 +64,7 @@ mod either;
 mod option;
 mod result;
 mod tuple;
-
+mod iter;
 
 // Runtime and language-primitive support
 
index dc9a24785c3f2b6b31ab9cec853c8d91e6792ff6..23ac02b75849c45719d54db73d08279a7473f1c9 100644 (file)
@@ -1,6 +1,6 @@
 // Top-level, visible-everywhere definitions.
 
-// Export type option as a synonym for option::t and export the some and none
+// Export type option as a synonym for option and export the some and none
 // enum constructors.
 
 import option::{some,  none};
index f583bb646d06047bcf9392608ba0bb6c2e19e307..22428e41ca3dbf2d6dc8238df1ed7c445e325c8e 100644 (file)
@@ -5,7 +5,7 @@
 which are not obviously correct for all potential platforms.
 */
 
-export c_int, c_uint, long, longlong, unsigned, ulong, ulonglong;
+export c_char, c_int, c_uint, long, longlong, unsigned, ulong, ulonglong;
 export intptr_t, uintptr_t;
 export uint32_t;
 export void::{};
@@ -16,6 +16,9 @@
 
 // PORT adapt to architecture
 
+#[doc = "A signed integer with the same size as a C `char`."]
+type c_char = i8;
+
 #[doc(
   brief = "A signed integer with the same size as a C `int`."
 )]
          but using pointers to this type when interoperating \
          with C void pointers can help in documentation."
 )]
-enum void {
-    // Making the only variant reference itself makes it impossible to
-    // construct. Not exporting it makes it impossible to destructure.
-    void_private(@void),
-    // FIXME: #881
-    void_private2(@void),
-}
+enum void {}
 
 #[doc(
   brief = "A float value with the same size as a C `float`."
index eb91c2cb5d517e60d588e8606549d4ea9dbe7f57..3f58548684c5806c0706652bf5c121ac652f65e0 100644 (file)
@@ -69,7 +69,7 @@ enum count {
 
     // A formatted conversion from an expression to a string
     type conv =
-        {param: option::t<int>,
+        {param: option<int>,
          flags: [flag],
          width: count,
          precision: count,
@@ -115,7 +115,7 @@ fn flush_buf(buf: str, &pieces: [piece]) -> str {
         ret pieces;
     }
     fn peek_num(s: str, i: uint, lim: uint) ->
-       option::t<{num: uint, next: uint}> {
+       option<{num: uint, next: uint}> {
         if i >= lim { ret none; }
         let c = s[i];
         if !('0' as u8 <= c && c <= '9' as u8) { ret option::none; }
@@ -145,7 +145,7 @@ fn parse_conversion(s: str, i: uint, lim: uint, error: error_fn) ->
              next: ty.next};
     }
     fn parse_parameter(s: str, i: uint, lim: uint) ->
-       {param: option::t<int>, next: uint} {
+       {param: option<int>, next: uint} {
         if i >= lim { ret {param: none, next: i}; }
         let num = peek_num(s, i, lim);
         ret alt num {
index 4023c65b118d9028d53a12e39a31b2931666867a..ffa56129d4f5ac13057fd8a98e5d88dfa1a28daa 100644 (file)
@@ -46,7 +46,7 @@
 */
 fn to_str_common(num: float, digits: uint, exact: bool) -> str {
     if is_NaN(num) { ret "NaN"; }
-    let (num, accum) = num < 0.0 ? (-num, "-") : (num, "");
+    let (num, accum) = if num < 0.0 { (-num, "-") } else { (num, "") };
     let trunc = num as uint;
     let frac = num - (trunc as float);
     accum += uint::str(trunc);
diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs
new file mode 100644 (file)
index 0000000..7aa08a6
--- /dev/null
@@ -0,0 +1,171 @@
+iface iterable<A> {
+    fn iter(blk: fn(A));
+}
+
+impl<A> of iterable<A> for fn@(fn(A)) {
+    fn iter(blk: fn(A)) {
+        self(blk);
+    }
+}
+
+// accomodate the fact that int/uint are passed by value by default:
+impl of iterable<int> for fn@(fn(int)) {
+    fn iter(blk: fn(&&int)) {
+        self {|i| blk(i)}
+    }
+}
+
+impl of iterable<uint> for fn@(fn(uint)) {
+    fn iter(blk: fn(&&uint)) {
+        self {|i| blk(i)}
+    }
+}
+
+impl<A> of iterable<A> for [A] {
+    fn iter(blk: fn(A)) {
+        vec::iter(self, blk)
+    }
+}
+
+impl<A> of iterable<A> for option<A> {
+    fn iter(blk: fn(A)) {
+        option::may(self, blk)
+    }
+}
+
+fn enumerate<A,IA:iterable<A>>(self: IA, blk: fn(uint, A)) {
+    let i = 0u;
+    self.iter {|a|
+        blk(i, a);
+        i += 1u;
+    }
+}
+
+// Here: we have to use fn@ for predicates and map functions, because
+// we will be binding them up into a closure.  Disappointing.  A true
+// region type system might be able to do better than this.
+
+fn filter<A,IA:iterable<A>>(self: IA, prd: fn@(A) -> bool, blk: fn(A)) {
+    self.iter {|a|
+        if prd(a) { blk(a) }
+    }
+}
+
+fn map<A,B,IA:iterable<A>>(self: IA, cnv: fn@(A) -> B, blk: fn(B)) {
+    self.iter {|a|
+        let b = cnv(a);
+        blk(b);
+    }
+}
+
+fn flat_map<A,B,IA:iterable<A>,IB:iterable<B>>(
+    self: IA, cnv: fn@(A) -> IB, blk: fn(B)) {
+    self.iter {|a|
+        cnv(a).iter(blk)
+    }
+}
+
+fn foldl<A,B:copy,IA:iterable<A>>(self: IA, b0: B, blk: fn(B, A) -> B) -> B {
+    let b = b0;
+    self.iter {|a|
+        b = blk(b, a);
+    }
+    ret b;
+}
+
+fn to_list<A:copy,IA:iterable<A>>(self: IA) -> [A] {
+    foldl::<A,[A],IA>(self, [], {|r, a| r + [a]})
+}
+
+fn repeat(times: uint, blk: fn()) {
+    let i = 0u;
+    while i < times {
+        blk();
+        i += 1u;
+    }
+}
+
+
+#[test]
+fn test_enumerate() {
+    enumerate(["0", "1", "2"]) {|i,j|
+        assert #fmt["%u",i] == j;
+    }
+}
+
+#[test]
+fn test_map_and_to_list() {
+    let a = bind vec::iter([0, 1, 2], _);
+    let b = bind map(a, {|i| i*2}, _);
+    let c = to_list(b);
+    assert c == [0, 2, 4];
+}
+
+#[test]
+fn test_map_directly_on_vec() {
+    let b = bind map([0, 1, 2], {|i| i*2}, _);
+    let c = to_list(b);
+    assert c == [0, 2, 4];
+}
+
+#[test]
+fn test_filter_on_int_range() {
+    fn is_even(&&i: int) -> bool {
+        ret (i % 2) == 0;
+    }
+
+    let l = to_list(bind filter(bind int::range(0, 10, _), is_even, _));
+    assert l == [0, 2, 4, 6, 8];
+}
+
+#[test]
+fn test_filter_on_uint_range() {
+    fn is_even(&&i: uint) -> bool {
+        ret (i % 2u) == 0u;
+    }
+
+    let l = to_list(bind filter(bind uint::range(0u, 10u, _), is_even, _));
+    assert l == [0u, 2u, 4u, 6u, 8u];
+}
+
+#[test]
+fn test_flat_map_with_option() {
+    fn if_even(&&i: int) -> option<int> {
+        if (i % 2) == 0 { some(i) }
+        else { none }
+    }
+
+    let a = bind vec::iter([0, 1, 2], _);
+    let b = bind flat_map(a, if_even, _);
+    let c = to_list(b);
+    assert c == [0, 2];
+}
+
+#[test]
+fn test_flat_map_with_list() {
+    fn repeat(&&i: int) -> [int] {
+        let r = [];
+        int::range(0, i) {|_j| r += [i]; }
+        r
+    }
+
+    let a = bind vec::iter([0, 1, 2, 3], _);
+    let b = bind flat_map(a, repeat, _);
+    let c = to_list(b);
+    #debug["c = %?", c];
+    assert c == [1, 2, 2, 3, 3, 3];
+}
+
+#[test]
+fn test_repeat() {
+    let c = [],
+        i = 0u;
+    repeat(5u) {||
+        c += [(i * i)];
+        i += 1u;
+    };
+    #debug["c = %?", c];
+    assert c == [0u, 1u, 4u, 9u, 16u];
+}
+
+
index c2982cf918a807b00084eab9925ec94812174b65..2552d58b4a2d6ff78ada202af8cbac422d6cefea 100644 (file)
@@ -7,14 +7,14 @@
 
 Returns the minimum of two values
 */
-pure fn min<T: copy>(x: T, y: T) -> T { x < y ? x : y }
+pure fn min<T: copy>(x: T, y: T) -> T { if x < y { x } else { y} }
 
 /*
 Function: max
 
 Returns the maximum of two values
 */
-pure fn max<T: copy>(x: T, y: T) -> T { x < y ? y : x }
+pure fn max<T: copy>(x: T, y: T) -> T { if x < y { y } else { x } }
 
 #[test]
 fn test_max_min() {
@@ -310,4 +310,4 @@ fn test_log_functions() {
     assert ln1p(float::infinity) == float::infinity;
 }
 
-*/
\ No newline at end of file
+*/
index dad10eced7f2b96492348c9abfc7aba5cba96b4f..618fa04a314319003105180f72e200b097778970 100644 (file)
@@ -12,9 +12,7 @@
 export
    // Creating a string
    from_bytes,
-   unsafe_from_bytes,
    from_byte,
-   unsafe_from_byte,
    //push_utf8_bytes,
    from_char,
    from_chars,
 
    // Transforming strings
    bytes,
-   to_chars,
+   chars,
    substr,
-   char_slice,
    slice,
-   safe_slice,
    split,
    splitn,
    split_str,
 
    // Comparing strings
    eq,
-   lteq,
+   le,
    hash,
 
    // Iterating through strings
-   loop_chars,
    all,
    any,
    map,
    bytes_iter,
-   iter_chars,
    chars_iter,
+   split_chars_iter,
+   splitn_chars_iter,
    words_iter,
    lines_iter,
 
    utf8_char_width,
    char_range_at,
    char_at,
-   loop_chars_sub,
+   substr_all,
    escape_char,
    as_buf,
    //buf,
-   sbuf;
+   sbuf,
+   reserve,
+
+   unsafe;
 
 
 
 #[abi = "cdecl"]
 native mod rustrt {
     fn rust_str_push(&s: str, ch: u8);
+    fn str_reserve_shared(&ss: str, nn: ctypes::size_t);
 }
 
 // FIXME: add pure to a lot of functions
 
 Convert a vector of bytes to a UTF-8 string.  Fails if invalid UTF-8.
 */
-fn from_bytes(vv: [u8]) -> str {
+fn from_bytes(vv: [u8]) -> str unsafe {
    assert is_utf8(vv);
-   ret unsafe_from_bytes(vv);
-}
-
-/*
-Function: unsafe_from_bytes
-
-Converts a vector of bytes to a string. Does not verify that the
-vector contains valid UTF-8.
-
-FIXME: stop exporting
-*/
-fn unsafe_from_bytes(v: [const u8]) -> str unsafe {
-    let vcopy: [u8] = v + [0u8];
-    let scopy: str = unsafe::reinterpret_cast(vcopy);
-    unsafe::leak(vcopy);
-    ret scopy;
+   ret unsafe::from_bytes(vv);
 }
 
-/*
-Function: unsafe_from_byte
-
-Converts a byte to a string. Does not verify that the byte is
-valid UTF-8.
-
-FIXME: stop exporting
-*/
-fn unsafe_from_byte(u: u8) -> str { unsafe_from_bytes([u]) }
-
-
 /*
 Function: from_byte
 
@@ -370,7 +344,7 @@ fn count_whities(s: [char]) -> uint {
         }
         ret i;
     }
-    let chars = to_chars(s);
+    let chars = chars(s);
     let whities = count_whities(chars);
     ret from_chars(vec::slice(chars, whities, vec::len(chars)));
 }
@@ -389,7 +363,7 @@ fn count_whities(s: [char]) -> uint {
         }
         ret i;
     }
-    let chars = to_chars(s);
+    let chars = chars(s);
     let whities = count_whities(chars);
     ret from_chars(vec::slice(chars, 0u, whities));
 }
@@ -413,20 +387,20 @@ fn trim(s: str) -> str { trim_left(trim_right(s)) }
 null-terminated.
 */
 fn bytes(s: str) -> [u8] unsafe {
-    let v = unsafe::reinterpret_cast(s);
+    let v = ::unsafe::reinterpret_cast(s);
     let vcopy = vec::slice(v, 0u, vec::len(v) - 1u);
-    unsafe::leak(v);
+    ::unsafe::leak(v);
     ret vcopy;
 }
 
 /*
-Function: to_chars
+Function: chars
 
 Convert a string to a vector of characters
 
 FIXME: rename to 'chars'
 */
-fn to_chars(s: str) -> [char] {
+fn chars(s: str) -> [char] {
     let buf: [char] = [];
     let i = 0u;
     let len = byte_len(s);
@@ -450,12 +424,12 @@ fn to_chars(s: str) -> [char] {
 
 If `begin` + `len` is is greater than the byte length of the string
 */
-fn substr(s: str, begin: uint, len: uint) -> str {
-    ret slice(s, begin, begin + len);
+fn substr(s: str, begin: uint, len: uint) -> str unsafe {
+    ret unsafe::slice_bytes(s, begin, begin + len);
 }
 
 /*
-Function: char_slice
+Function: slice
 
 Unicode-safe slice. Returns a slice of the given string containing
 the characters in the range [`begin`..`end`). `begin` and `end` are
@@ -466,52 +440,10 @@ fn substr(s: str, begin: uint, len: uint) -> str {
 - If begin is greater than end
 - If end is greater than the character length of the string
 
-FIXME: rename to slice(), make faster by avoiding char conversion
-*/
-fn char_slice(s: str, begin: uint, end: uint) -> str {
-    from_chars(vec::slice(to_chars(s), begin, end))
-}
-
-/*
-Function: slice
-
-Takes a bytewise slice from a string. Returns the substring from
-[`begin`..`end`).
-
-This function is not unicode-safe.
-
-Failure:
-
-- If begin is greater than end.
-- If end is greater than the length of the string.
-
-FIXME: rename to slice_byte or slice_byte_unsafe
-*/
-fn slice(s: str, begin: uint, end: uint) -> str unsafe {
-    // FIXME: Typestate precondition
-    assert (begin <= end);
-    assert (end <= byte_len(s));
-
-    let v: [u8] = unsafe::reinterpret_cast(s);
-    let v2 = vec::slice(v, begin, end);
-    unsafe::leak(v);
-    v2 += [0u8];
-    let s2: str = unsafe::reinterpret_cast(v2);
-    unsafe::leak(v2);
-    ret s2;
-}
-
-/*
-Function: safe_slice
-
-FIXME: make sure char_slice / slice / byte_slice
-       have these preconditions and assertions
-FIXME: this shouldn't be mistaken for a UTF-8 safe slice
+FIXME: make faster by avoiding char conversion
 */
-fn safe_slice(s: str, begin: uint, end: uint) : uint::le(begin, end) -> str {
-    // would need some magic to make this a precondition
-    assert (end <= byte_len(s));
-    ret slice(s, begin, end);
+fn slice(s: str, begin: uint, end: uint) -> str {
+    from_chars(vec::slice(chars(s), begin, end))
 }
 
 /*
@@ -620,7 +552,7 @@ fn split_func(ss: str, sepfn: fn(cc: char)->bool) -> [str] {
     let accum: str = "";
     let ends_with_sep: bool = false;
 
-    str::iter_chars(ss, {|cc| if sepfn(cc) {
+    chars_iter(ss, {|cc| if sepfn(cc) {
             vv += [accum];
             accum = "";
             ends_with_sep = true;
@@ -690,7 +622,7 @@ fn windowed(nn: uint, ss: str) -> [str] {
 
     let ii = 0u;
     while ii+nn <= len {
-        let w = char_slice( ss, ii, ii+nn );
+        let w = slice( ss, ii, ii+nn );
         vec::push(ww,w);
         ii += 1u;
     }
@@ -702,30 +634,18 @@ fn windowed(nn: uint, ss: str) -> [str] {
 Function: to_lower
 
 Convert a string to lowercase
-
-FIXME: rewrite with map
 */
 fn to_lower(s: str) -> str {
-    let outstr = "";
-    iter_chars(s) { |c|
-        push_char(outstr, char::to_lower(c));
-    }
-    ret outstr;
+    map(s, char::to_lower)
 }
 
 /*
 Function: to_upper
 
 Convert a string to uppercase
-
-FIXME: rewrite with map
 */
 fn to_upper(s: str) -> str {
-    let outstr = "";
-    iter_chars(s) { |c|
-        push_char(outstr, char::to_upper(c));
-    }
-    ret outstr;
+    map(s, char::to_upper)
 }
 
 // FIXME: This is super-inefficient
@@ -744,20 +664,21 @@ fn to_upper(s: str) -> str {
 
 The original string with all occurances of `from` replaced with `to`
 */
-fn replace(s: str, from: str, to: str) : is_not_empty(from) -> str {
+fn replace(s: str, from: str, to: str) : is_not_empty(from) -> str unsafe {
     // FIXME (694): Shouldn't have to check this
     check (is_not_empty(from));
     if byte_len(s) == 0u {
         ret "";
     } else if starts_with(s, from) {
-        ret to + replace(slice(s, byte_len(from), byte_len(s)), from, to);
+        ret to + replace(unsafe::slice_bytes(s, byte_len(from), byte_len(s)),
+                                       from, to);
     } else {
         let idx = find(s, from);
         if idx == -1 {
             ret s;
         }
-        ret char_slice(s, 0u, idx as uint) + to +
-            replace(char_slice(s, idx as uint + char_len(from), char_len(s)),
+        ret slice(s, 0u, idx as uint) + to +
+            replace(slice(s, idx as uint + char_len(from), char_len(s)),
                     from, to);
     }
 }
@@ -769,7 +690,7 @@ fn replace(s: str, from: str, to: str) : is_not_empty(from) -> str {
 */
 fn escape(s: str) -> str {
     let r = "";
-    loop_chars(s, { |c| r += escape_char(c); true });
+    all(s, { |c| r += escape_char(c); true });
     r
 }
 
@@ -785,11 +706,11 @@ fn escape(s: str) -> str {
 pure fn eq(&&a: str, &&b: str) -> bool { a == b }
 
 /*
-Function: lteq
+Function: le
 
 Bytewise less than or equal
 */
-pure fn lteq(&&a: str, &&b: str) -> bool { a <= b }
+pure fn le(&&a: str, &&b: str) -> bool { a <= b }
 
 /*
 Function: hash
@@ -809,37 +730,14 @@ fn hash(&&s: str) -> uint {
 Section: Iterating through strings
 */
 
-/*
-Function: loop_chars
-
-Loop through a string, char by char
-
-Parameters:
-s  - A string to traverse. It may be empty.
-it - A block to execute with each consecutive character of `s`.
-Return `true` to continue, `false` to stop.
-
-Returns:
-
-`true` If execution proceeded correctly, `false` if it was interrupted,
-that is if `it` returned `false` at any point.
-
-FIXME: rename to 'chars_loop' (change? currently a synonym to 'all')
- */
-fn loop_chars(s: str, it: fn(char) -> bool) -> bool{
-    ret loop_chars_sub(s, 0u, byte_len(s), it);
-}
-
 /*
 Function: all
 
 Return true if a predicate matches all characters or
 if the string contains no characters
-
-// FIXME: a synonym to loop_chars
 */
-fn all(ss: str, ff: fn(char) -> bool) -> bool {
-    str::loop_chars(ss, ff)
+fn all(s: str, it: fn(char) -> bool) -> bool{
+    ret substr_all(s, 0u, byte_len(s), it);
 }
 
 /*
@@ -859,8 +757,9 @@ fn any(ss: str, pred: fn(char) -> bool) -> bool {
 */
 fn map(ss: str, ff: fn(char) -> char) -> str {
     let result = "";
+    reserve(result, byte_len(ss));
 
-    str::iter_chars(ss, {|cc|
+    chars_iter(ss, {|cc|
         str::push_char(result, ff(cc));
     });
 
@@ -871,8 +770,6 @@ fn map(ss: str, ff: fn(char) -> char) -> str {
 Function: bytes_iter
 
 Iterate over the bytes in a string
-
-FIXME: Should it really include the last byte '\0'?
 */
 fn bytes_iter(ss: str, it: fn(u8)) {
     let pos = 0u;
@@ -885,13 +782,11 @@ fn bytes_iter(ss: str, it: fn(u8)) {
 }
 
 /*
-Function: iter_chars
+Function: chars_iter
 
 Iterate over the characters in a string
-
-FIXME: rename to 'chars_iter'
 */
-fn iter_chars(s: str, it: fn(char)) {
+fn chars_iter(s: str, it: fn(char)) {
     let pos = 0u, len = byte_len(s);
     while (pos < len) {
         let {ch, next} = char_range_at(s, pos);
@@ -901,14 +796,25 @@ fn iter_chars(s: str, it: fn(char)) {
 }
 
 /*
-Function: chars_iter
+Function: split_chars_iter
 
-Iterate over the characters in a string
+Apply a function to each substring after splitting
+by character
+*/
+fn split_chars_iter(ss: str, cc: char, ff: fn(&&str)) {
+   vec::iter(split_char(ss, cc), ff)
+}
+
+/*
+Function: splitn_chars_iter
 
-FIXME: A synonym to iter_chars
+Apply a function to each substring after splitting
+by character, up to nn times
+
+FIXME: make this use chars when splitn/splitn_char is fixed
 */
-fn chars_iter(ss: str, it: fn(char)) {
-    iter_chars(ss, it)
+fn splitn_chars_iter(ss: str, sep: u8, count: uint, ff: fn(&&str)) {
+   vec::iter(splitn(ss, sep, count), ff)
 }
 
 /*
@@ -929,9 +835,6 @@ fn lines_iter(ss: str, ff: fn(&&str)) {
     vec::iter(lines(ss), ff)
 }
 
-// FIXME: ADD split_char_iter
-// FIXME: ADD splitn_char_iter
-
 /*
 Section: Searching
 */
@@ -941,6 +844,8 @@ fn lines_iter(ss: str, ff: fn(&&str)) {
 
 Returns the index of the first matching byte. Returns -1 if
 no match is found.
+
+FIXME: UTF-8
 */
 fn index(s: str, c: u8) -> int {
     let i: int = 0;
@@ -953,6 +858,8 @@ fn index(s: str, c: u8) -> int {
 
 Returns the index of the last matching byte. Returns -1
 if no match is found.
+
+FIXME: UTF-8
 */
 fn rindex(s: str, c: u8) -> int {
     let n: int = byte_len(s) as int;
@@ -974,6 +881,8 @@ fn rindex(s: str, c: u8) -> int {
 Returns:
 
 The index of the first occurance of `needle`, or -1 if not found.
+
+FIXME: UTF-8?
 */
 fn find(haystack: str, needle: str) -> int {
     let haystack_len: int = byte_len(haystack) as int;
@@ -1082,7 +991,7 @@ fn is_ascii(s: str) -> bool {
 Returns true if the string contains only whitespace
 */
 fn is_whitespace(s: str) -> bool {
-    ret loop_chars(s, char::is_whitespace);
+    ret all(s, char::is_whitespace);
 }
 
 /*
@@ -1093,9 +1002,9 @@ fn is_whitespace(s: str) -> bool {
 FIXME: rename to 'len_bytes'?
 */
 pure fn byte_len(s: str) -> uint unsafe {
-    let v: [u8] = unsafe::reinterpret_cast(s);
+    let v: [u8] = ::unsafe::reinterpret_cast(s);
     let vlen = vec::len(v);
-    unsafe::leak(v);
+    ::unsafe::leak(v);
     // There should always be a null terminator
     assert (vlen > 0u);
     ret vlen - 1u;
@@ -1160,15 +1069,15 @@ fn is_utf8(v: [u8]) -> bool {
 FIXME: rename to 'substr_len_chars'
 */
 fn char_len_range(s: str, byte_start: uint, byte_len: uint) -> uint {
-    let i     = byte_start;
+    let i         = byte_start;
+    let byte_stop = i + byte_len;
     let len   = 0u;
-    while i < byte_len {
+    while i < byte_stop {
         let chsize = utf8_char_width(s[i]);
         assert (chsize > 0u);
         len += 1u;
         i += chsize;
     }
-    assert (i == byte_len);
     ret len;
 }
 
@@ -1298,7 +1207,7 @@ fn char_range_at(s: str, i: uint) -> {ch: char, next: uint} {
 fn char_at(s: str, i: uint) -> char { ret char_range_at(s, i).ch; }
 
 /*
-Function: loop_chars_sub
+Function: substr_all
 
 Loop through a substring, char by char
 
@@ -1318,10 +1227,8 @@ fn char_range_at(s: str, i: uint) -> {ch: char, next: uint} {
 - This function does not check whether the substring is valid.
 - This function fails if `byte_offset` or `byte_len` do not
  represent valid positions inside `s`
-
-FIXME: rename to 'substr_all'
  */
-fn loop_chars_sub(s: str, byte_offset: uint, byte_len: uint,
+fn substr_all(s: str, byte_offset: uint, byte_len: uint,
               it: fn(char) -> bool) -> bool {
    let i = byte_offset;
    let result = true;
@@ -1371,7 +1278,7 @@ fn escape_char(c: char) -> str {
 // no guarantee that the string is rooted). Instead, use as_buf below.
 unsafe fn buf(s: str) -> sbuf {
     let saddr = ptr::addr_of(s);
-    let vaddr: *[u8] = unsafe::reinterpret_cast(saddr);
+    let vaddr: *[u8] = ::unsafe::reinterpret_cast(saddr);
     let buf = vec::to_ptr(*vaddr);
     ret buf;
 }
@@ -1398,6 +1305,80 @@ fn as_buf<T>(s: str, f: fn(sbuf) -> T) -> T unsafe {
 */
 type sbuf = *u8;
 
+// Function: reserve
+//
+// Allocate more memory for a string, up to `nn` + 1 bytes
+fn reserve(&ss: str, nn: uint) {
+    rustrt::str_reserve_shared(ss, nn);
+}
+
+// Module: unsafe
+//
+// These functions may create invalid UTF-8 strings and eat your baby.
+mod unsafe {
+   export
+      // UNSAFE
+      from_bytes,
+      from_byte,
+      slice_bytes,
+      slice_bytes_safe_range;
+
+   // Function: unsafe::from_bytes
+   //
+   // Converts a vector of bytes to a string. Does not verify that the
+   // vector contains valid UTF-8.
+   unsafe fn from_bytes(v: [const u8]) -> str unsafe {
+       let vcopy: [u8] = v + [0u8];
+       let scopy: str = ::unsafe::reinterpret_cast(vcopy);
+       ::unsafe::leak(vcopy);
+       ret scopy;
+   }
+
+   // Function: unsafe::from_byte
+   //
+   // Converts a byte to a string. Does not verify that the byte is
+   // valid UTF-8.
+   unsafe fn from_byte(u: u8) -> str { unsafe::from_bytes([u]) }
+
+   /*
+   Function: slice
+
+   Takes a bytewise (not UTF-8) slice from a string.
+   Returns the substring from [`begin`..`end`).
+
+   Failure:
+
+   - If begin is greater than end.
+   - If end is greater than the length of the string.
+   */
+   unsafe fn slice_bytes(s: str, begin: uint, end: uint) -> str unsafe {
+       // FIXME: Typestate precondition
+       assert (begin <= end);
+       assert (end <= byte_len(s));
+
+       let v: [u8] = ::unsafe::reinterpret_cast(s);
+       let v2 = vec::slice(v, begin, end);
+       ::unsafe::leak(v);
+       v2 += [0u8];
+       let s2: str = ::unsafe::reinterpret_cast(v2);
+       ::unsafe::leak(v2);
+       ret s2;
+   }
+
+   /*
+   Function: slice_bytes_safe_range
+
+   Like slice_bytes, with a precondition
+   */
+   unsafe fn slice_bytes_safe_range(s: str, begin: uint, end: uint)
+       : uint::le(begin, end) -> str {
+       // would need some magic to make this a precondition
+       assert (end <= byte_len(s));
+       ret slice_bytes(s, begin, end);
+   }
+
+}
+
 
 #[cfg(test)]
 mod tests {
@@ -1410,10 +1391,10 @@ fn test_eq() {
     }
 
     #[test]
-    fn test_lteq() {
-        assert (lteq("", ""));
-        assert (lteq("", "foo"));
-        assert (lteq("foo", "foo"));
+    fn test_le() {
+        assert (le("", ""));
+        assert (le("", "foo"));
+        assert (le("foo", "foo"));
         assert (!eq("foo", "bar"));
     }
 
@@ -1605,8 +1586,9 @@ fn t(v: [str], sep: str, s: str) {
 
     #[test]
     fn test_to_upper() {
-        // to_upper doesn't understand unicode yet,
-        // but we need to at least preserve it
+        // char::to_upper, and hence str::to_upper
+        // are culturally insensitive: I'm not sure they
+        // really work for anything but English ASCII, but YMMV
 
         let unicode = "\u65e5\u672c";
         let input = "abcDEF" + unicode + "xyz:.;";
@@ -1616,10 +1598,16 @@ fn test_to_upper() {
     }
 
     #[test]
-    fn test_slice() {
-        assert (eq("ab", slice("abc", 0u, 2u)));
-        assert (eq("bc", slice("abc", 1u, 3u)));
-        assert (eq("", slice("abc", 1u, 1u)));
+    fn test_to_lower() {
+        assert "" == map("", char::to_lower);
+        assert "ymca" == map("YMCA", char::to_lower);
+    }
+
+    #[test]
+    fn test_unsafe_slice() unsafe {
+        assert (eq("ab", unsafe::slice_bytes("abc", 0u, 2u)));
+        assert (eq("bc", unsafe::slice_bytes("abc", 1u, 3u)));
+        assert (eq("", unsafe::slice_bytes("abc", 1u, 1u)));
         fn a_million_letter_a() -> str {
             let i = 0;
             let rs = "";
@@ -1633,7 +1621,7 @@ fn half_a_million_letter_a() -> str {
             ret rs;
         }
         assert (eq(half_a_million_letter_a(),
-                        slice(a_million_letter_a(), 0u, 500000u)));
+               unsafe::slice_bytes(a_million_letter_a(), 0u, 500000u)));
     }
 
     #[test]
@@ -1680,17 +1668,17 @@ fn test_replace() {
     }
 
     #[test]
-    fn test_char_slice() {
-        assert (eq("ab", char_slice("abc", 0u, 2u)));
-        assert (eq("bc", char_slice("abc", 1u, 3u)));
-        assert (eq("", char_slice("abc", 1u, 1u)));
-        assert (eq("\u65e5", char_slice("\u65e5\u672c", 0u, 1u)));
+    fn test_slice() {
+        assert (eq("ab", slice("abc", 0u, 2u)));
+        assert (eq("bc", slice("abc", 1u, 3u)));
+        assert (eq("", slice("abc", 1u, 1u)));
+        assert (eq("\u65e5", slice("\u65e5\u672c", 0u, 1u)));
 
         let data = "ประเทศไทย中华";
-        assert (eq("ป", char_slice(data, 0u, 1u)));
-        assert (eq("ร", char_slice(data, 1u, 2u)));
-        assert (eq("华", char_slice(data, 10u, 11u)));
-        assert (eq("", char_slice(data, 1u, 1u)));
+        assert (eq("ป", slice(data, 0u, 1u)));
+        assert (eq("ร", slice(data, 1u, 2u)));
+        assert (eq("华", slice(data, 10u, 11u)));
+        assert (eq("", slice(data, 1u, 1u)));
 
         fn a_million_letter_X() -> str {
             let i = 0;
@@ -1705,7 +1693,7 @@ fn half_a_million_letter_X() -> str {
             ret rs;
         }
         assert (eq(half_a_million_letter_X(),
-                        char_slice(a_million_letter_X(), 0u, 500000u)));
+                        slice(a_million_letter_X(), 0u, 500000u)));
     }
 
     #[test]
@@ -1771,9 +1759,9 @@ fn test_pop_byte() {
     }
 
     #[test]
-    fn test_unsafe_from_bytes() {
+    fn test_unsafe_from_bytes() unsafe {
         let a = [65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 65u8];
-        let b = unsafe_from_bytes(a);
+        let b = unsafe::from_bytes(a);
         assert (b == "AAAAAAA");
     }
 
@@ -1796,6 +1784,7 @@ fn test_from_bytes() {
 
     #[test]
     #[should_fail]
+    #[ignore(cfg(target_os = "win32"))]
     fn test_from_bytes_fail() {
         let bb = [0xff_u8, 0xb8_u8, 0xa8_u8,
                   0xe0_u8, 0xb9_u8, 0x84_u8,
@@ -1872,21 +1861,6 @@ fn test_contains() {
         assert !contains("", "a");
     }
 
-    #[test]
-    fn test_iter_chars() {
-        let i = 0;
-        iter_chars("x\u03c0y") {|ch|
-            alt i {
-              0 { assert ch == 'x'; }
-              1 { assert ch == '\u03c0'; }
-              2 { assert ch == 'y'; }
-            }
-            i += 1;
-        }
-
-        iter_chars("") {|_ch| fail; } // should not fail
-    }
-
     #[test]
     fn test_chars_iter() {
         let i = 0;
@@ -1918,6 +1892,41 @@ fn test_bytes_iter() {
         bytes_iter("") {|bb| assert bb == 0u8; }
     }
 
+    #[test]
+    fn test_split_chars_iter() {
+        let data = "\nMary had a little lamb\nLittle lamb\n";
+
+        let ii = 0;
+
+        split_chars_iter(data, ' ') {|xx|
+            alt ii {
+              0 { assert "\nMary" == xx; }
+              1 { assert "had"    == xx; }
+              2 { assert "a"      == xx; }
+              3 { assert "little" == xx; }
+              _ { () }
+            }
+            ii += 1;
+        }
+    }
+
+    #[test]
+    fn test_splitn_chars_iter() {
+        let data = "\nMary had a little lamb\nLittle lamb\n";
+
+        let ii = 0;
+
+        splitn_chars_iter(data, ' ' as u8, 2u) {|xx|
+            alt ii {
+              0 { assert "\nMary" == xx; }
+              1 { assert "had"    == xx; }
+              2 { assert "a little lamb\nLittle lamb\n" == xx; }
+              _ { () }
+            }
+            ii += 1;
+        }
+    }
+
     #[test]
     fn test_words_iter() {
         let data = "\nMary had a little lamb\nLittle lamb\n";
@@ -2002,7 +2011,15 @@ fn test_windowed() {
 
     #[test]
     #[should_fail]
+    #[ignore(cfg(target_os = "win32"))]
     fn test_windowed_() {
         let _x = windowed(0u, "abcd");
     }
+
+    #[test]
+    fn test_chars() {
+        let ss = "ศไทย中华Việt Nam";
+        assert ['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m']
+            == chars(ss);
+    }
 }
index a099644985507dc24c55c2e38c5aab7dc428f01a..40b50c1ad4be6779a8f983acb077a8f29f973e3c 100644 (file)
@@ -17,11 +17,9 @@ enum type_desc = {
     // visible-in-crate, but not re-exported.
     fn last_os_error() -> str;
     fn refcount<T>(t: @T) -> ctypes::intptr_t;
-    fn do_gc();
     fn unsupervise();
     fn shape_log_str<T>(t: *sys::type_desc, data: T) -> str;
     fn rust_set_exit_status(code: ctypes::intptr_t);
-    fn set_min_stack(size: ctypes::uintptr_t);
 }
 
 #[abi = "rust-intrinsic"]
@@ -75,15 +73,6 @@ fn refcount<T>(t: @T) -> uint {
     ret rustrt::refcount::<T>(t);
 }
 
-/*
-Function: do_gc
-
-Force a garbage collection
-*/
-fn do_gc() -> () {
-    ret rustrt::do_gc();
-}
-
 // FIXME: There's a wrapper for this in the task module and this really
 // just belongs there
 fn unsupervise() -> () {
@@ -106,22 +95,6 @@ fn set_exit_status(code: int) {
     rustrt::rust_set_exit_status(code as ctypes::intptr_t);
 }
 
-// FIXME: #1495 - This shouldn't exist
-#[doc(
-    brief =
-    "Globally set the minimum size, in bytes, of a stack segment",
-    desc =
-    "Rust tasks have segmented stacks that are connected in a linked list \
-     allowing them to start very small and grow very large. In some \
-     situations this can result in poor performance. Calling this function \
-     will set the minimum size of all stack segments allocated in the \
-     future, for all tasks."
-)]
-#[deprecated]
-fn set_min_stack(size: uint) {
-    rustrt::set_min_stack(size);
-}
-
 #[cfg(test)]
 mod tests {
 
index b56425159533ce43b1774764b997bc27e3c67498..0b8abdc36a7db78dae90c9737e635b140400b54e 100644 (file)
 
 export task;
 export joinable_task;
-export sleep;
 export yield;
 export task_notification;
 export join;
 export unsupervise;
-export pin;
-export unpin;
 export task_result;
 export tr_success;
 export tr_failure;
@@ -55,7 +52,7 @@
 #[abi = "rust-intrinsic"]
 native mod rusti {
     // these must run on the Rust stack so that they can swap stacks etc:
-    fn task_sleep(task: *rust_task, time_in_us: c::size_t, &killed: bool);
+    fn task_yield(task: *rust_task, &killed: bool);
 }
 
 type rust_closure = {
@@ -65,9 +62,6 @@
 #[link_name = "rustrt"]
 #[abi = "cdecl"]
 native mod rustrt {
-    // these can run on the C stack:
-    fn pin_task();
-    fn unpin_task();
     fn get_task_id() -> task_id;
     fn rust_get_task() -> *rust_task;
 
@@ -75,8 +69,6 @@
     fn drop_task(task_id: *rust_task);
     fn get_task_pointer(id: task_id) -> *rust_task;
 
-    fn migrate_alloc(alloc: *u8, target: task_id);
-
     fn start_task(id: task, closure: *rust_closure);
 
     fn rust_task_is_unwinding(rt: *rust_task) -> bool;
@@ -122,7 +114,7 @@ fn spawn(+f: fn~()) -> task {
 }
 
 fn spawn_inner(-f: fn~(),
-               notify: option<comm::chan<task_notification>>) -> task unsafe {
+            notify: option<comm::chan<task_notification>>) -> task unsafe {
     let closure: *rust_closure = unsafe::reinterpret_cast(ptr::addr_of(f));
     #debug("spawn: closure={%x,%x}", (*closure).fnptr, (*closure).envptr);
     let id = rustrt::new_task();
@@ -260,35 +252,21 @@ fn spawn_connected<ToCh:send, FrCh:send>(+f: connected_fn<ToCh, FrCh>)
 fn get_task() -> task { rustrt::get_task_id() }
 
 /*
-Function: sleep
-
-Hints the scheduler to yield this task for a specified ammount of time.
+Function: yield
 
-Parameters:
+Yield control to the task scheduler
 
-time_in_us - maximum number of microseconds to yield control for
+The scheduler may schedule another task to execute.
 */
-fn sleep(time_in_us: uint) {
+fn yield() {
     let task = rustrt::rust_get_task();
     let killed = false;
-    // FIXME: uncomment this when extfmt is moved to core
-    // in a snapshot.
-    // #debug("yielding for %u us", time_in_us);
-    rusti::task_sleep(task, time_in_us, killed);
+    rusti::task_yield(task, killed);
     if killed && !currently_unwinding() {
         fail "killed";
     }
 }
 
-/*
-Function: yield
-
-Yield control to the task scheduler
-
-The scheduler may schedule another task to execute.
-*/
-fn yield() { sleep(1u) }
-
 /*
 Function: join
 
@@ -327,20 +305,6 @@ fn join(task_port: joinable_task) -> task_result {
 */
 fn unsupervise() { ret sys::unsupervise(); }
 
-/*
-Function: pin
-
-Pins the current task and future child tasks to a single scheduler thread
-*/
-fn pin() { rustrt::pin_task(); }
-
-/*
-Function: unpin
-
-Unpin the current task and future child tasks
-*/
-fn unpin() { rustrt::unpin_task(); }
-
 /*
 Function: currently_unwinding()
 
@@ -376,9 +340,6 @@ fn try<T:send>(+f: fn~() -> T) -> result::t<T,()> {
 
 #[cfg(test)]
 mod tests {
-    #[test]
-    fn test_sleep() { sleep(1000000u); }
-
     // FIXME: Leaks on windows
     #[test]
     #[ignore(cfg(target_os = "win32"))]
index dd256af1d6f56ef664069e0e9e99134be4b0a7bf..0dc5dea59bcd8050d036f3f69ecd865462a40411 100644 (file)
@@ -230,7 +230,7 @@ fn init<T: copy>(v: [const T]) -> [T] {
 An option containing the last element of `v` if `v` is not empty, or
 none if `v` is empty.
 */
-pure fn last<T: copy>(v: [const T]) -> option::t<T> {
+pure fn last<T: copy>(v: [const T]) -> option<T> {
     if len(v) == 0u { ret none; }
     ret some(v[len(v) - 1u]);
 }
@@ -398,27 +398,18 @@ fn shift<T: copy>(&v: [const T]) -> T {
     ret e;
 }
 
-// TODO: Write this, unsafely, in a way that's not O(n).
 /*
 Function: pop
 
 Remove the last element from a vector and return it
 */
-fn pop<T: copy>(&v: [const T]) -> T {
+fn pop<T>(&v: [const T]) -> T unsafe {
     let ln = len(v);
-    assert (ln > 0u);
-    ln -= 1u;
-    let e = v[ln];
-    v = slice(v, 0u, ln);
-    ret e;
-// FIXME use this implementation after the next snapshot (27.01.2012)
-/*  let new_ln = len(v) - 1u;
-    assert (new_ln > 0u);
-    let valptr = ptr::mut_addr_of(v[new_ln]);
+    assert ln > 0u;
+    let valptr = ptr::mut_addr_of(v[ln - 1u]);
     let val <- *valptr;
-    unsafe::set_len(v, new_ln);
+    unsafe::set_len(v, ln - 1u);
     val
-*/
 }
 
 /*
@@ -558,7 +549,7 @@ fn map2<T: copy, U: copy, V>(v0: [T], v1: [U], f: fn(T, U) -> V) -> [V] {
 If function `f` returns `none` then that element is excluded from
 the resulting vector.
 */
-fn filter_map<T: copy, U: copy>(v: [const T], f: fn(T) -> option::t<U>)
+fn filter_map<T: copy, U: copy>(v: [const T], f: fn(T) -> option<U>)
     -> [U] {
     let result = [];
     for elem: T in v {
@@ -727,7 +718,7 @@ fn count<T>(x: T, v: [const T]) -> uint {
 When function `f` returns true then an option containing the element
 is returned. If `f` matches no elements then none is returned.
 */
-fn find<T: copy>(v: [T], f: fn(T) -> bool) -> option::t<T> {
+fn find<T: copy>(v: [T], f: fn(T) -> bool) -> option<T> {
     find_from(v, 0u, len(v), f)
 }
 
@@ -741,7 +732,7 @@ fn find<T: copy>(v: [T], f: fn(T) -> bool) -> option::t<T> {
 is returned. If `f` matches no elements then none is returned.
 */
 fn find_from<T: copy>(v: [T], start: uint, end: uint, f: fn(T) -> bool) ->
-  option::t<T> {
+  option<T> {
     option::map(position_from(v, start, end, f)) { |i| v[i] }
 }
 
@@ -754,7 +745,7 @@ fn find_from<T: copy>(v: [T], start: uint, end: uint, f: fn(T) -> bool) ->
 returns true then an option containing the element is returned. If `f`
 matches no elements then none is returned.
 */
-fn rfind<T: copy>(v: [T], f: fn(T) -> bool) -> option::t<T> {
+fn rfind<T: copy>(v: [T], f: fn(T) -> bool) -> option<T> {
     rfind_from(v, 0u, len(v), f)
 }
 
@@ -768,7 +759,7 @@ fn rfind<T: copy>(v: [T], f: fn(T) -> bool) -> option::t<T> {
 the element is returned. If `f` matches no elements then none is returned.
 */
 fn rfind_from<T: copy>(v: [T], start: uint, end: uint, f: fn(T) -> bool) ->
-  option::t<T> {
+  option<T> {
     option::map(rposition_from(v, start, end, f)) { |i| v[i] }
 }
 
@@ -782,7 +773,7 @@ fn rfind_from<T: copy>(v: [T], start: uint, end: uint, f: fn(T) -> bool) ->
 option::some(uint) - The first index containing a matching value
 option::none - No elements matched
 */
-fn position_elt<T>(v: [T], x: T) -> option::t<uint> {
+fn position_elt<T>(v: [T], x: T) -> option<uint> {
     position(v) { |y| x == y }
 }
 
@@ -795,7 +786,7 @@ fn position_elt<T>(v: [T], x: T) -> option::t<uint> {
 then an option containing the index is returned. If `f` matches no elements
 then none is returned.
 */
-fn position<T>(v: [T], f: fn(T) -> bool) -> option::t<uint> {
+fn position<T>(v: [T], f: fn(T) -> bool) -> option<uint> {
     position_from(v, 0u, len(v), f)
 }
 
@@ -809,7 +800,7 @@ fn position<T>(v: [T], f: fn(T) -> bool) -> option::t<uint> {
 returned. If `f` matches no elements then none is returned.
 */
 fn position_from<T>(v: [T], start: uint, end: uint, f: fn(T) -> bool) ->
-  option::t<uint> {
+  option<uint> {
     assert start <= end;
     assert end <= len(v);
     let i = start;
@@ -827,7 +818,7 @@ fn position_from<T>(v: [T], start: uint, end: uint, f: fn(T) -> bool) ->
 option::some(uint) - The last index containing a matching value
 option::none - No elements matched
 */
-fn rposition_elt<T>(v: [T], x: T) -> option::t<uint> {
+fn rposition_elt<T>(v: [T], x: T) -> option<uint> {
     rposition(v) { |y| x == y }
 }
 
@@ -840,7 +831,7 @@ fn rposition_elt<T>(v: [T], x: T) -> option::t<uint> {
 `f` returns true then an option containing the index is returned. If `f`
 matches no elements then none is returned.
 */
-fn rposition<T>(v: [T], f: fn(T) -> bool) -> option::t<uint> {
+fn rposition<T>(v: [T], f: fn(T) -> bool) -> option<uint> {
     rposition_from(v, 0u, len(v), f)
 }
 
@@ -854,7 +845,7 @@ fn rposition<T>(v: [T], f: fn(T) -> bool) -> option::t<uint> {
 the index is returned. If `f` matches no elements then none is returned.
 */
 fn rposition_from<T>(v: [T], start: uint, end: uint, f: fn(T) -> bool) ->
-  option::t<uint> {
+  option<uint> {
     assert start <= end;
     assert end <= len(v);
     let i = end;
@@ -1244,7 +1235,7 @@ mod tests {
 
     pure fn is_equal(&&x: uint, &&y:uint) -> bool { ret x == y; }
 
-    fn square_if_odd(&&n: uint) -> option::t<uint> {
+    fn square_if_odd(&&n: uint) -> option<uint> {
         ret if n % 2u == 1u { some(n * n) } else { none };
     }
 
@@ -1501,7 +1492,7 @@ fn test_filter_map() {
         assert (w[1] == 9u);
         assert (w[2] == 25u);
 
-        fn halve(&&i: int) -> option::t<int> {
+        fn halve(&&i: int) -> option<int> {
             if i % 2 == 0 {
                 ret option::some::<int>(i / 2);
             } else { ret option::none::<int>; }
@@ -1962,6 +1953,7 @@ fn test_windowed () {
 
     #[test]
     #[should_fail]
+    #[ignore(cfg(target_os = "win32"))]
     fn test_windowed_() {
         let _x = windowed (0u, [1u,2u,3u,4u,5u,6u]);
     }
index b2154bc61b4b4fa36b369e9f826aff2b6a4f2fd0..53dccda3f15dff4069b27234f652bf2eece114a0 100644 (file)
@@ -46,7 +46,7 @@ enum t<T> {
     t({ base: *mutable T, len: uint, rsrc: @dtor_res})
 }
 
-resource dtor_res(dtor: option::t<fn@()>) {
+resource dtor_res(dtor: option<fn@()>) {
     alt dtor {
       option::none { }
       option::some(f) { f(); }
index 290b981306f6744512653c998d56ee009bd0da34..e6c30f67302ece860375cbbf3a5515ed2edbf4a5 100644 (file)
@@ -38,7 +38,7 @@
 // FIXME eventually, a proper datatype plus an exported impl would be
 // preferrable
 fn create<T: copy>() -> t<T> {
-    type cell<T> = option::t<T>;
+    type cell<T> = option<T>;
 
     let initial_capacity: uint = 32u; // 2^5
      /**
index b76ba4ad9b822b459121001539800155804f3f7d..19cf97624ab5257d27a9524dcf2748cce6f72c78 100644 (file)
@@ -50,7 +50,7 @@ fn doc_at(data: @[u8], start: uint) -> doc {
     ret {data: data, start: elt_size.next, end: end};
 }
 
-fn maybe_get_doc(d: doc, tg: uint) -> option::t<doc> {
+fn maybe_get_doc(d: doc, tg: uint) -> option<doc> {
     let pos = d.start;
     while pos < d.end {
         let elt_tag = vint_at(*d.data, pos);
index 89aad5d7777856e632d2715c8b742a9a69a4f0d1..315813c0848b71f8dfac89b0b40324a880891153 100644 (file)
@@ -10,7 +10,7 @@
 export libc;
 export libc_constants;
 export pipe;
-export fd_FILE;
+export FILE, fd_FILE;
 export close;
 export fclose;
 export waitpid;
 // FIXME Somehow merge stuff duplicated here and macosx_os.rs. Made difficult
 // by https://github.com/graydon/rust/issues#issue/268
 
+enum FILE_opaque {}
+type FILE = *FILE_opaque;
+enum dir {}
+enum dirent {}
+
 #[nolink]
 #[abi = "cdecl"]
 native mod libc {
     fn read(fd: fd_t, buf: *u8, count: size_t) -> ssize_t;
     fn write(fd: fd_t, buf: *u8, count: size_t) -> ssize_t;
-    fn fread(buf: *u8, size: size_t, n: size_t, f: libc::FILE) -> size_t;
-    fn fwrite(buf: *u8, size: size_t, n: size_t, f: libc::FILE) -> size_t;
+    fn fread(buf: *u8, size: size_t, n: size_t, f: FILE) -> size_t;
+    fn fwrite(buf: *u8, size: size_t, n: size_t, f: FILE) -> size_t;
     fn open(s: str::sbuf, flags: c_int, mode: unsigned) -> fd_t;
     fn close(fd: fd_t) -> c_int;
-    type FILE;
     fn fopen(path: str::sbuf, mode: str::sbuf) -> FILE;
     fn fdopen(fd: fd_t, mode: str::sbuf) -> FILE;
     fn fclose(f: FILE);
     fn feof(f: FILE) -> c_int;
     fn fseek(f: FILE, offset: long, whence: c_int) -> c_int;
     fn ftell(f: FILE) -> long;
-    type dir;
-    fn opendir(d: str::sbuf) -> dir;
-    fn closedir(d: dir) -> c_int;
-    type dirent;
-    fn readdir(d: dir) -> dirent;
+    fn opendir(d: str::sbuf) -> *dir;
+    fn closedir(d: *dir) -> c_int;
+    fn readdir(d: *dir) -> *dirent;
     fn getenv(n: str::sbuf) -> str::sbuf;
     fn setenv(n: str::sbuf, v: str::sbuf, overwrite: c_int) -> c_int;
     fn unsetenv(n: str::sbuf) -> c_int;
@@ -90,7 +92,7 @@ fn pipe() -> {in: fd_t, out: fd_t} {
     ret {in: fds.in, out: fds.out};
 }
 
-fn fd_FILE(fd: fd_t) -> libc::FILE {
+fn fd_FILE(fd: fd_t) -> FILE {
     ret str::as_buf("r", {|modebuf| libc::fdopen(fd, modebuf) });
 }
 
@@ -98,7 +100,7 @@ fn close(fd: fd_t) -> c_int {
     libc::close(fd)
 }
 
-fn fclose(file: libc::FILE) {
+fn fclose(file: FILE) {
     libc::fclose(file)
 }
 
@@ -127,7 +129,7 @@ fn waitpid(pid: pid_t) -> i32 {
 
 /// Returns the directory containing the running program
 /// followed by a path separator
-fn get_exe_path() -> option::t<fs::path> unsafe {
+fn get_exe_path() -> option<fs::path> unsafe {
     let bufsize = 1023u;
     // FIXME: path "strings" will likely need fixing...
     let path = str::from_bytes(vec::init_elt(bufsize, 0u8));
index cbfca163c1838b417d7adcdfd511363ac31c1120..1e5c9657d1e0fc5a79d6c49c81e941f3fa020520 100644 (file)
@@ -63,7 +63,7 @@ fn dirname(p: path) -> path {
 the provided path. If an empty path is provided or the path ends
 with a path separator then an empty path is returned.
 */
-fn basename(p: path) -> path {
+fn basename(p: path) -> path unsafe {
     let i: int = str::rindex(p, os_fs::path_sep as u8);
     if i == -1 {
         i = str::rindex(p, os_fs::alt_path_sep as u8);
@@ -71,7 +71,7 @@ fn basename(p: path) -> path {
     }
     let len = str::byte_len(p);
     if i + 1 as uint >= len { ret p; }
-    ret str::slice(p, i + 1 as uint, len);
+    ret str::unsafe::slice_bytes(p, i + 1 as uint, len);
 }
 
 
index a2f6b8c225f4285a252ab7287025d6e83ede3a0f..d497b2a4963b89fcae419133b8894be4a1496bed 100644 (file)
@@ -13,7 +13,7 @@
 */
 
 import option::{some, none};
-import option = option::t;
+import option = option;
 
 export treemap;
 export init;
@@ -87,12 +87,17 @@ fn find<K, V: copy>(m: treemap<K, V>, k: K) -> option<V> {
 fn traverse<K, V: copy>(m: treemap<K, V>, f: fn(K, V)) {
     alt *m {
       empty { }
-      node(@k, @v, _, _) {
+      /*
+        Previously, this had what looked like redundant
+        matches to me, so I changed it. but that may be a
+        de-optimization -- tjc
+       */
+      node(@k, @v, left, right) {
         // copy v to make aliases work out
         let v1 = v;
-        alt *m { node(_, _, left, _) { traverse(left, f); } }
+        traverse(left, f);
         f(k, v1);
-        alt *m { node(_, _, _, right) { traverse(right, f); } }
+        traverse(right, f);
       }
     }
 }
index 934352e7788445897651ede08f0d401426f52b35..f41e83fa5fbe5aeac3273ce2e479a1f538d256c7 100644 (file)
@@ -16,7 +16,7 @@
 
 Get the value of an environment variable
 */
-fn getenv(n: str) -> option::t<str> { }
+fn getenv(n: str) -> option<str> { }
 
 #[cfg(bogus)]
 /*
@@ -29,7 +29,7 @@ fn setenv(n: str, v: str) { }
 #[cfg(target_os = "linux")]
 #[cfg(target_os = "macos")]
 #[cfg(target_os = "freebsd")]
-fn getenv(n: str) -> option::t<str> unsafe {
+fn getenv(n: str) -> option<str> unsafe {
     let s = str::as_buf(n, {|buf| os::libc::getenv(buf) });
     ret if unsafe::reinterpret_cast(s) == 0 {
             option::none::<str>
@@ -55,7 +55,7 @@ fn setenv(n: str, v: str) {
 }
 
 #[cfg(target_os = "win32")]
-fn getenv(n: str) -> option::t<str> {
+fn getenv(n: str) -> option<str> {
     let nsize = 256u;
     while true {
         let v: [u8] = [];
index c517a2f996df708ba81ccbb3c8615de6d3f681c7..48d83f0e5c2c825f452db3d15ca2382160ab2101 100644 (file)
@@ -148,7 +148,7 @@ fn name_str(nm: name) -> str {
     ret alt nm { short(ch) { str::from_char(ch) } long(s) { s } };
 }
 
-fn find_opt(opts: [opt], nm: name) -> option::t<uint> {
+fn find_opt(opts: [opt], nm: name) -> option<uint> {
     vec::position(opts, { |opt| opt.name == nm })
 }
 
@@ -209,7 +209,7 @@ fn fail_str(f: fail_) -> str {
             <opt_str>, etc. to interrogate results.
 err(fail_) - On failure. Use <fail_str> to get an error message.
 */
-fn getopts(args: [str], opts: [opt]) -> result {
+fn getopts(args: [str], opts: [opt]) -> result unsafe {
     let n_opts = vec::len::<opt>(opts);
     fn f(_x: uint) -> [optval] { ret []; }
     let vals = vec::init_fn_mut::<[optval]>(n_opts, f);
@@ -229,14 +229,15 @@ fn getopts(args: [str], opts: [opt]) -> result {
             let names;
             let i_arg = option::none::<str>;
             if cur[1] == '-' as u8 {
-                let tail = str::slice(cur, 2u, curlen);
+                let tail = str::unsafe::slice_bytes(cur, 2u, curlen);
                 let eq = str::index(tail, '=' as u8);
                 if eq == -1 {
                     names = [long(tail)];
                 } else {
-                    names = [long(str::slice(tail, 0u, eq as uint))];
+                    names =
+                        [long(str::unsafe::slice_bytes(tail,0u,eq as uint))];
                     i_arg =
-                        option::some::<str>(str::slice(tail,
+                        option::some::<str>(str::unsafe::slice_bytes(tail,
                                                        (eq as uint) + 1u,
                                                        curlen - 2u));
                 }
@@ -354,7 +355,7 @@ fn opt_strs(m: match, nm: str) -> [str] {
 
 Returns the string argument supplied to a matching option or none
 */
-fn opt_maybe_str(m: match, nm: str) -> option::t<str> {
+fn opt_maybe_str(m: match, nm: str) -> option<str> {
     let vals = opt_vals(m, nm);
     if vec::len::<optval>(vals) == 0u { ret none::<str>; }
     ret alt vals[0] { val(s) { some::<str>(s) } _ { none::<str> } };
@@ -370,7 +371,7 @@ fn opt_maybe_str(m: match, nm: str) -> option::t<str> {
 present but no argument was provided, and the argument if the option was
 present and an argument was provided.
 */
-fn opt_default(m: match, nm: str, def: str) -> option::t<str> {
+fn opt_default(m: match, nm: str, def: str) -> option<str> {
     let vals = opt_vals(m, nm);
     if vec::len::<optval>(vals) == 0u { ret none::<str>; }
     ret alt vals[0] { val(s) { some::<str>(s) } _ { some::<str>(def) } }
index 5cc08813d6abc344a746b90922796b5caead633a..8f77a804892bf2c0b0ad040f05603cfe972c1c66 100644 (file)
@@ -9,9 +9,9 @@
 
 #[abi = "cdecl"]
 native mod rustrt {
-    fn rust_get_stdin() -> os::libc::FILE;
-    fn rust_get_stdout() -> os::libc::FILE;
-    fn rust_get_stderr() -> os::libc::FILE;
+    fn rust_get_stdin() -> os::FILE;
+    fn rust_get_stdout() -> os::FILE;
+    fn rust_get_stderr() -> os::FILE;
 }
 
 // Reading
@@ -166,7 +166,7 @@ fn convert_whence(whence: seek_style) -> i32 {
     };
 }
 
-impl of reader for os::libc::FILE {
+impl of reader for os::FILE {
     fn read_bytes(len: uint) -> [u8] unsafe {
         let buf = [];
         vec::reserve(buf, len);
@@ -195,9 +195,9 @@ fn seek(off: int, whence: seek_style) { self.base.seek(off, whence) }
     fn tell() -> uint { self.base.tell() }
 }
 
-resource FILE_res(f: os::libc::FILE) { os::libc::fclose(f); }
+resource FILE_res(f: os::FILE) { os::libc::fclose(f); }
 
-fn FILE_reader(f: os::libc::FILE, cleanup: bool) -> reader {
+fn FILE_reader(f: os::FILE, cleanup: bool) -> reader {
     if cleanup {
         {base: f, cleanup: FILE_res(f)} as reader
     } else {
@@ -282,7 +282,7 @@ fn tell() -> uint { self.base.tell() }
     fn flush() -> int { self.base.flush() }
 }
 
-impl of writer for os::libc::FILE {
+impl of writer for os::FILE {
     fn write(v: [const u8]) unsafe {
         let len = vec::len(v);
         let vbuf = vec::unsafe::to_ptr(v);
@@ -296,7 +296,7 @@ fn tell() -> uint { os::libc::ftell(self) as uint }
     fn flush() -> int { os::libc::fflush(self) as int }
 }
 
-fn FILE_writer(f: os::libc::FILE, cleanup: bool) -> writer {
+fn FILE_writer(f: os::FILE, cleanup: bool) -> writer {
     if cleanup {
         {base: f, cleanup: FILE_res(f)} as writer
     } else {
@@ -525,24 +525,24 @@ enum level {
 
     type arg<t> = {
         val: t,
-        opt_level: option::t<level>,
+        opt_level: option<level>,
         fsync_fn: fn@(t, level) -> int
     };
 
     // fsync file after executing blk
     // FIXME find better way to create resources within lifetime of outer res
-    fn FILE_res_sync(&&file: FILE_res, opt_level: option::t<level>,
-                  blk: fn(&&res<os::libc::FILE>)) {
+    fn FILE_res_sync(&&file: FILE_res, opt_level: option<level>,
+                  blk: fn(&&res<os::FILE>)) {
         blk(res({
             val: *file, opt_level: opt_level,
-            fsync_fn: fn@(&&file: os::libc::FILE, l: level) -> int {
+            fsync_fn: fn@(&&file: os::FILE, l: level) -> int {
                 ret os::fsync_fd(os::libc::fileno(file), l) as int;
             }
         }));
     }
 
     // fsync fd after executing blk
-    fn fd_res_sync(&&fd: fd_res, opt_level: option::t<level>,
+    fn fd_res_sync(&&fd: fd_res, opt_level: option<level>,
                    blk: fn(&&res<fd_t>)) {
         blk(res({
             val: *fd, opt_level: opt_level,
@@ -556,7 +556,7 @@ fn fd_res_sync(&&fd: fd_res, opt_level: option::t<level>,
     iface t { fn fsync(l: level) -> int; }
 
     // Call o.fsync after executing blk
-    fn obj_sync(&&o: t, opt_level: option::t<level>, blk: fn(&&res<t>)) {
+    fn obj_sync(&&o: t, opt_level: option<level>, blk: fn(&&res<t>)) {
         blk(res({
             val: o, opt_level: opt_level,
             fsync_fn: fn@(&&o: t, l: level) -> int { ret o.fsync(l); }
index 0229b4d1b2280cfc2c0a7e36f02cf1af8cb557be..bb1d0fb64b6b214b660898848a77452ad0f11696 100644 (file)
@@ -71,10 +71,10 @@ fn to_str(j: json) -> str {
 
 fn rest(s: str) -> str {
     assert(str::char_len(s) >= 1u);
-    str::char_slice(s, 1u, str::char_len(s))
+    str::slice(s, 1u, str::char_len(s))
 }
 
-fn from_str_str(s: str) -> (option::t<json>, str) {
+fn from_str_str(s: str) -> (option<json>, str) {
     let pos = 0u;
     let len = str::byte_len(s);
     let escape = false;
@@ -99,7 +99,7 @@ fn from_str_str(s: str) -> (option::t<json>, str) {
             cont;
         } else if (c == '"') {
             ret (some(string(res)),
-                 str::char_slice(s, pos, str::char_len(s)));
+                 str::slice(s, pos, str::char_len(s)));
         }
         res = res + str::from_char(c);
     }
@@ -107,7 +107,7 @@ fn from_str_str(s: str) -> (option::t<json>, str) {
     ret (none, s);
 }
 
-fn from_str_list(s: str) -> (option::t<json>, str) {
+fn from_str_list(s: str) -> (option<json>, str) {
     if str::char_at(s, 0u) != '[' { ret (none, s); }
     let s0 = str::trim_left(rest(s));
     let vals = [];
@@ -133,7 +133,7 @@ fn from_str_list(s: str) -> (option::t<json>, str) {
     ret (none, s0);
 }
 
-fn from_str_dict(s: str) -> (option::t<json>, str) {
+fn from_str_dict(s: str) -> (option<json>, str) {
     if str::char_at(s, 0u) != '{' { ret (none, s); }
     let s0 = str::trim_left(rest(s));
     let vals = map::new_str_hash::<json>();
@@ -170,7 +170,7 @@ fn from_str_dict(s: str) -> (option::t<json>, str) {
     (none, s)
 }
 
-fn from_str_float(s: str) -> (option::t<json>, str) {
+fn from_str_float(s: str) -> (option<json>, str) {
     let pos = 0u;
     let len = str::byte_len(s);
     let res = 0f;
@@ -200,12 +200,12 @@ fn from_str_float(s: str) -> (option::t<json>, str) {
             }
             '.' { break; }
             _ { ret (some(num(neg * res)),
-                     str::char_slice(s, opos, str::char_len(s))); }
+                     str::slice(s, opos, str::char_len(s))); }
         }
     }
 
     if pos == len {
-        ret (some(num(neg * res)), str::char_slice(s, pos, str::char_len(s)));
+        ret (some(num(neg * res)), str::slice(s, pos, str::char_len(s)));
     }
 
     let dec = 1f;
@@ -220,31 +220,31 @@ fn from_str_float(s: str) -> (option::t<json>, str) {
                 res += (((c as int) - ('0' as int)) as float) * dec;
             }
             _ { ret (some(num(neg * res)),
-                     str::char_slice(s, opos, str::char_len(s))); }
+                     str::slice(s, opos, str::char_len(s))); }
         }
     }
-    ret (some(num(neg * res)), str::char_slice(s, pos, str::char_len(s)));
+    ret (some(num(neg * res)), str::slice(s, pos, str::char_len(s)));
 }
 
-fn from_str_bool(s: str) -> (option::t<json>, str) {
+fn from_str_bool(s: str) -> (option<json>, str) {
     if (str::starts_with(s, "true")) {
-        (some(boolean(true)), str::slice(s, 4u, str::byte_len(s)))
+        (some(boolean(true)), str::slice(s, 4u, str::char_len(s)))
     } else if (str::starts_with(s, "false")) {
-        (some(boolean(false)), str::slice(s, 5u, str::byte_len(s)))
+        (some(boolean(false)), str::slice(s, 5u, str::char_len(s)))
     } else {
         (none, s)
     }
 }
 
-fn from_str_null(s: str) -> (option::t<json>, str) {
+fn from_str_null(s: str) -> (option<json>, str) {
     if (str::starts_with(s, "null")) {
-        (some(null), str::slice(s, 4u, str::byte_len(s)))
+        (some(null), str::slice(s, 4u, str::char_len(s)))
     } else {
         (none, s)
     }
 }
 
-fn from_str_helper(s: str) -> (option::t<json>, str) {
+fn from_str_helper(s: str) -> (option<json>, str) {
     let s = str::trim_left(s);
     if str::is_empty(s) { ret (none, s); }
     let start = str::char_at(s, 0u);
@@ -264,7 +264,7 @@ fn from_str_helper(s: str) -> (option::t<json>, str) {
 
 Deserializes a json value from a string.
 */
-fn from_str(s: str) -> option::t<json> {
+fn from_str(s: str) -> option<json> {
     let (j, _) = from_str_helper(s);
     j
 }
index 82b1197a51fbd226d96aaa9fe4a1c5a959ac9a39..05722333df8aa3b7d2369b3cea36d1205667bed1 100644 (file)
@@ -10,7 +10,7 @@
 export libc;
 export libc_constants;
 export pipe;
-export fd_FILE;
+export FILE, fd_FILE;
 export close;
 export fclose;
 export waitpid;
 // FIXME Somehow merge stuff duplicated here and macosx_os.rs. Made difficult
 // by https://github.com/graydon/rust/issues#issue/268
 
+enum FILE_opaque {}
+type FILE = *FILE_opaque;
+enum dir {}
+enum dirent {}
+
 #[nolink]
 #[abi = "cdecl"]
 native mod libc {
     fn read(fd: fd_t, buf: *u8, count: size_t) -> ssize_t;
     fn write(fd: fd_t, buf: *u8, count: size_t) -> ssize_t;
-    fn fread(buf: *u8, size: size_t, n: size_t, f: libc::FILE) -> size_t;
-    fn fwrite(buf: *u8, size: size_t, n: size_t, f: libc::FILE) -> size_t;
+    fn fread(buf: *u8, size: size_t, n: size_t, f: FILE) -> size_t;
+    fn fwrite(buf: *u8, size: size_t, n: size_t, f: FILE) -> size_t;
     fn open(s: str::sbuf, flags: c_int, mode: unsigned) -> fd_t;
     fn close(fd: fd_t) -> c_int;
-    type FILE;
     fn fopen(path: str::sbuf, mode: str::sbuf) -> FILE;
     fn fdopen(fd: fd_t, mode: str::sbuf) -> FILE;
     fn fclose(f: FILE);
     fn feof(f: FILE) -> c_int;
     fn fseek(f: FILE, offset: long, whence: c_int) -> c_int;
     fn ftell(f: FILE) -> long;
-    type dir;
-    fn opendir(d: str::sbuf) -> dir;
-    fn closedir(d: dir) -> c_int;
-    type dirent;
-    fn readdir(d: dir) -> dirent;
+    fn opendir(d: str::sbuf) -> *dir;
+    fn closedir(d: *dir) -> c_int;
+    fn readdir(d: *dir) -> *dirent;
     fn getenv(n: str::sbuf) -> str::sbuf;
     fn setenv(n: str::sbuf, v: str::sbuf, overwrite: c_int) -> c_int;
     fn unsetenv(n: str::sbuf) -> c_int;
@@ -83,7 +85,7 @@ fn pipe() -> {in: fd_t, out: fd_t} {
     ret {in: fds.in, out: fds.out};
 }
 
-fn fd_FILE(fd: fd_t) -> libc::FILE {
+fn fd_FILE(fd: fd_t) -> FILE {
     ret str::as_buf("r", {|modebuf| libc::fdopen(fd, modebuf) });
 }
 
@@ -91,7 +93,7 @@ fn close(fd: fd_t) -> c_int {
     libc::close(fd)
 }
 
-fn fclose(file: libc::FILE) {
+fn fclose(file: FILE) {
     libc::fclose(file)
 }
 
@@ -123,7 +125,7 @@ fn waitpid(pid: pid_t) -> i32 {
 
 /// Returns the directory containing the running program
 /// followed by a path separator
-fn get_exe_path() -> option::t<fs::path> {
+fn get_exe_path() -> option<fs::path> {
     let bufsize = 1023u;
     // FIXME: path "strings" will likely need fixing...
     let path = str::from_bytes(vec::init_elt(bufsize, 0u8));
index e393b42b9f25c02335939c7ec625b7aee597e293..be6ce7338a3f55bdd82f4ced400cdc3692969489 100644 (file)
@@ -61,8 +61,8 @@ fn foldl<T: copy, U>(ls: list<U>, z: T, f: fn(T, U) -> T) -> T {
 When function `f` returns true then an option containing the element
 is returned. If `f` matches no elements then none is returned.
 */
-fn find<T: copy, U: copy>(ls: list<T>, f: fn(T) -> option::t<U>)
-    -> option::t<U> {
+fn find<T: copy, U: copy>(ls: list<T>, f: fn(T) -> option<U>)
+    -> option<U> {
     let ls = ls;
     while true {
         alt ls {
@@ -259,7 +259,7 @@ fn sub(&&a: int, &&b: int) -> int {
 
     #[test]
     fn test_find_success() {
-        fn match(&&i: int) -> option::t<int> {
+        fn match(&&i: int) -> option<int> {
             ret if i == 2 { option::some(i) } else { option::none::<int> };
         }
         let l = from_vec([0, 1, 2]);
@@ -268,7 +268,7 @@ fn match(&&i: int) -> option::t<int> {
 
     #[test]
     fn test_find_fail() {
-        fn match(&&_i: int) -> option::t<int> { ret option::none::<int>; }
+        fn match(&&_i: int) -> option<int> { ret option::none::<int>; }
         let l = from_vec([0, 1, 2]);
         let empty = list::nil::<int>;
         assert (list::find(l, match) == option::none::<int>);
index cd984870781cb0cab0f32ab3eb91f358646f5dcb..920061cfd3175d9ee2047e4ba5e7905319644b0f 100644 (file)
@@ -4,7 +4,7 @@
 export libc;
 export libc_constants;
 export pipe;
-export fd_FILE;
+export FILE, fd_FILE;
 export close;
 export fclose;
 export waitpid;
 // FIXME Refactor into unix_os module or some such. Doesn't
 // seem to work right now.
 
+enum FILE_opaque {}
+type FILE = *FILE_opaque;
+enum dir {}
+enum dirent {}
+
 #[nolink]
 #[abi = "cdecl"]
 native mod libc {
     fn read(fd: fd_t, buf: *u8, count: size_t) -> ssize_t;
     fn write(fd: fd_t, buf: *u8, count: size_t) -> ssize_t;
-    fn fread(buf: *u8, size: size_t, n: size_t, f: libc::FILE) -> size_t;
-    fn fwrite(buf: *u8, size: size_t, n: size_t, f: libc::FILE) -> size_t;
+    fn fread(buf: *u8, size: size_t, n: size_t, f: FILE) -> size_t;
+    fn fwrite(buf: *u8, size: size_t, n: size_t, f: FILE) -> size_t;
     fn open(s: str::sbuf, flags: c_int, mode: unsigned) -> fd_t;
     fn close(fd: fd_t) -> c_int;
-    type FILE;
     fn fopen(path: str::sbuf, mode: str::sbuf) -> FILE;
     fn fdopen(fd: fd_t, mode: str::sbuf) -> FILE;
     fn fflush(f: FILE) -> c_int;
     fn feof(f: FILE) -> c_int;
     fn fseek(f: FILE, offset: long, whence: c_int) -> c_int;
     fn ftell(f: FILE) -> long;
-    type dir;
-    fn opendir(d: str::sbuf) -> dir;
-    fn closedir(d: dir) -> c_int;
-    type dirent;
-    fn readdir(d: dir) -> dirent;
+    fn opendir(d: str::sbuf) -> *dir;
+    fn closedir(d: *dir) -> c_int;
+    fn readdir(d: *dir) -> *dirent;
     fn getenv(n: str::sbuf) -> str::sbuf;
     fn setenv(n: str::sbuf, v: str::sbuf, overwrite: c_int) -> c_int;
     fn unsetenv(n: str::sbuf) -> c_int;
@@ -80,7 +82,7 @@ fn pipe() -> {in: fd_t, out: fd_t} {
     ret {in: fds.in, out: fds.out};
 }
 
-fn fd_FILE(fd: fd_t) -> libc::FILE {
+fn fd_FILE(fd: fd_t) -> FILE {
     ret str::as_buf("r", {|modebuf| libc::fdopen(fd, modebuf) });
 }
 
@@ -88,7 +90,7 @@ fn close(fd: fd_t) -> c_int {
     libc::close(fd)
 }
 
-fn fclose(file: libc::FILE) {
+fn fclose(file: FILE) {
     libc::fclose(file)
 }
 
@@ -131,7 +133,7 @@ fn _NSGetExecutablePath(buf: str::sbuf,
 
 fn dylib_filename(base: str) -> str { ret "lib" + base + ".dylib"; }
 
-fn get_exe_path() -> option::t<fs::path> {
+fn get_exe_path() -> option<fs::path> {
     // FIXME: This doesn't handle the case where the buffer is too small
     // FIXME: path "strings" will likely need fixing...
     let bufsize = 1023u32;
index 09eb1534f937c7767f6139d94c7ecd15c3ee20cc..8da3d78552d5f452336db0cdc2cb34220bb683bc 100644 (file)
     Get the value for the specified key. If the key does not exist
     in the map then returns none.
     */
-    fn find(K) -> option::t<V>;
+    fn find(K) -> option<V>;
     /*
     Method: remove
 
     Remove and return a value from the map. If the key does not exist
     in the map then returns none.
     */
-    fn remove(K) -> option::t<V>;
+    fn remove(K) -> option<V>;
     /*
     Method: items
 
@@ -206,7 +206,7 @@ fn insert<K: copy, V: copy>(tbl: t<K,V>, k: K, v: V) -> bool {
         }
     }
 
-    fn get<K: copy, V: copy>(tbl: t<K,V>, k: K) -> core::option::t<V> {
+    fn get<K: copy, V: copy>(tbl: t<K,V>, k: K) -> core::option<V> {
         alt search_tbl(tbl, k, tbl.hasher(k)) {
           not_found {
             ret core::option::none;
@@ -222,7 +222,7 @@ fn get<K: copy, V: copy>(tbl: t<K,V>, k: K) -> core::option::t<V> {
         }
     }
 
-    fn remove<K: copy, V: copy>(tbl: t<K,V>, k: K) -> core::option::t<V> {
+    fn remove<K: copy, V: copy>(tbl: t<K,V>, k: K) -> core::option<V> {
         alt search_tbl(tbl, k, tbl.hasher(k)) {
           not_found {
             ret core::option::none;
@@ -307,9 +307,9 @@ fn contains_key(k: K) -> bool { option::is_some(get(self, k)) }
 
         fn get(k: K) -> V { option::get(get(self, k)) }
 
-        fn find(k: K) -> option::t<V> { get(self, k) }
+        fn find(k: K) -> option<V> { get(self, k) }
 
-        fn remove(k: K) -> option::t<V> { remove(self, k) }
+        fn remove(k: K) -> option<V> { remove(self, k) }
 
         fn items(blk: fn(K, V)) { items(self, blk); }
 
index 7b5320a5dfc29e87521d5710b86aa3264f3cd3ad..1d6540f04e88ad69a811d6eaae370c89a109cc9d 100644 (file)
@@ -65,7 +65,7 @@ fn rot(r: int, x: u32) -> u32 {
 
         let j = 0u, q = 0x6ed9eba1u32;
         while j < 8u {
-            let jj = j > 2u ? j - 3u : j;
+            let jj = if j > 2u { j - 3u } else { j };
             a = rot(3, a + (b ^ c ^ d) + x[jj] + q);
             d = rot(9, d + (a ^ b ^ c) + x[jj + 8u] + q);
             c = rot(11, c + (d ^ a ^ b) + x[jj + 4u] + q);
index 85f3d99c6c8a708c62c87e3b5724156e979ccf24..c288189216d2ba8f7185170f7f99c005387eb7b6 100644 (file)
@@ -3,12 +3,14 @@
 
 Random number generation
 */
+
+enum rctx {}
+
 #[abi = "cdecl"]
 native mod rustrt {
-    type rctx;
-    fn rand_new() -> rctx;
-    fn rand_next(c: rctx) -> u32;
-    fn rand_free(c: rctx);
+    fn rand_new() -> *rctx;
+    fn rand_next(c: *rctx) -> u32;
+    fn rand_free(c: *rctx);
 }
 
 /* Section: Types */
@@ -48,7 +50,7 @@
     fn gen_bytes(len: uint) -> [u8];
 }
 
-resource rand_res(c: rustrt::rctx) { rustrt::rand_free(c); }
+resource rand_res(c: *rctx) { rustrt::rand_free(c); }
 
 /* Section: Operations */
 
index 5e856ff5e0e0b7e8ccc612e1b0e89aaac4763df9..28cdbfa3d4055ed0b54cd4f53b831256ae984893 100644 (file)
@@ -481,7 +481,7 @@ fn start(rope: rope) -> node::leaf_iterator::t {
               node::content(x) { ret node::leaf_iterator::start(x) }
             }
         }
-        fn next(it: node::leaf_iterator::t) -> option::t<node::leaf> {
+        fn next(it: node::leaf_iterator::t) -> option<node::leaf> {
             ret node::leaf_iterator::next(it);
         }
     }
@@ -492,7 +492,7 @@ fn start(rope: rope) -> node::char_iterator::t {
               node::content(x) { ret node::char_iterator::start(x) }
             }
         }
-        fn next(it: node::char_iterator::t) -> option::t<char> {
+        fn next(it: node::char_iterator::t) -> option<char> {
             ret node::char_iterator::next(it)
         }
     }
@@ -952,7 +952,7 @@ fn flatten(node: @node) -> @node unsafe {
     - `option::some(x)` otherwise, in which case `x` has the same contents
        as `node` bot lower height and/or fragmentation.
     */
-    fn bal(node: @node) -> option::t<@node> {
+    fn bal(node: @node) -> option<@node> {
         if height(node) < hint_max_node_height { ret option::none; }
         //1. Gather all leaves as a forest
         let forest = [mutable];
@@ -1137,7 +1137,7 @@ fn cmp(a: @node, b: @node) -> int {
 
     fn loop_chars(node: @node, it: fn(char) -> bool) -> bool {
         ret loop_leaves(node, {|leaf|
-            ret str::loop_chars_sub(*leaf.content,
+            ret str::substr_all(*leaf.content,
                                     leaf.byte_offset,
                                     leaf.byte_len, it)
         })
@@ -1230,7 +1230,7 @@ fn start(node: @node) -> t {
             }
         }
 
-        fn next(it: t) -> option::t<leaf> {
+        fn next(it: t) -> option<leaf> {
             if it.stackpos < 0 { ret option::none; }
             while true {
                 let current = it.stack[it.stackpos];
@@ -1254,7 +1254,7 @@ fn next(it: t) -> option::t<leaf> {
     mod char_iterator {
         type t = {
             leaf_iterator: leaf_iterator::t,
-            mutable leaf:  option::t<leaf>,
+            mutable leaf:  option<leaf>,
             mutable leaf_byte_pos: uint
         };
 
@@ -1274,7 +1274,7 @@ fn empty() -> t {
             }
         }
 
-        fn next(it: t) -> option::t<char> {
+        fn next(it: t) -> option<char> {
             while true {
                 alt(get_current_or_next_leaf(it)) {
                   option::none { ret option::none; }
@@ -1294,7 +1294,7 @@ fn next(it: t) -> option::t<char> {
             fail;//unreachable
         }
 
-        fn get_current_or_next_leaf(it: t) -> option::t<leaf> {
+        fn get_current_or_next_leaf(it: t) -> option<leaf> {
             alt(it.leaf) {
               option::some(_) { ret it.leaf }
               option::none {
@@ -1311,7 +1311,7 @@ fn get_current_or_next_leaf(it: t) -> option::t<leaf> {
             }
         }
 
-        fn get_next_char_in_leaf(it: t) -> option::t<char> {
+        fn get_next_char_in_leaf(it: t) -> option<char> {
             alt(it.leaf) {
               option::none { ret option::none }
               option::some(aleaf) {
@@ -1494,4 +1494,4 @@ fn concat1() {
 
         assert eq(r, r2);
     }
-}
\ No newline at end of file
+}
index 5b2de1e57d0c880358f8cb54c606babdcd82744f..f81eda3aeeb501b69248ed626539008bba2e5e9c 100644 (file)
@@ -171,8 +171,8 @@ fn start_program(prog: str, args: [str]) -> program {
 
     type prog_repr = {pid: pid_t,
                       mutable in_fd: fd_t,
-                      out_file: os::libc::FILE,
-                      err_file: os::libc::FILE,
+                      out_file: os::FILE,
+                      err_file: os::FILE,
                       mutable finished: bool};
 
     fn close_repr_input(r: prog_repr) {
index dada53f355bca1485b8f2ddec3b2e077b61a1558..d76e37e5071432f67769e00cd75be54738414905 100644 (file)
@@ -12,7 +12,7 @@
 /*
 Type: smallintmap
 */
-type smallintmap<T> = @{mutable v: [mutable option::t<T>]};
+type smallintmap<T> = @{mutable v: [mutable option<T>]};
 
 /*
 Function: mk
@@ -20,7 +20,7 @@
 Create a smallintmap
 */
 fn mk<T>() -> smallintmap<T> {
-    let v: [mutable option::t<T>] = [mutable];
+    let v: [mutable option<T>] = [mutable];
     ret @{mutable v: v};
 }
 
@@ -31,7 +31,7 @@ fn mk<T>() -> smallintmap<T> {
 the specified key then the original value is replaced.
 */
 fn insert<T: copy>(m: smallintmap<T>, key: uint, val: T) {
-    vec::grow_set::<option::t<T>>(m.v, key, none::<T>, some::<T>(val));
+    vec::grow_set::<option<T>>(m.v, key, none::<T>, some::<T>(val));
 }
 
 /*
@@ -40,8 +40,8 @@ fn insert<T: copy>(m: smallintmap<T>, key: uint, val: T) {
 Get the value for the specified key. If the key does not exist
 in the map then returns none
 */
-fn find<T: copy>(m: smallintmap<T>, key: uint) -> option::t<T> {
-    if key < vec::len::<option::t<T>>(m.v) { ret m.v[key]; }
+fn find<T: copy>(m: smallintmap<T>, key: uint) -> option<T> {
+    if key < vec::len::<option<T>>(m.v) { ret m.v[key]; }
     ret none::<T>;
 }
 
@@ -73,11 +73,11 @@ fn contains_key<T: copy>(m: smallintmap<T>, key: uint) -> bool {
 // FIXME: Are these really useful?
 
 fn truncate<T: copy>(m: smallintmap<T>, len: uint) {
-    m.v = vec::slice_mut::<option::t<T>>(m.v, 0u, len);
+    m.v = vec::slice_mut::<option<T>>(m.v, 0u, len);
 }
 
 fn max_key<T>(m: smallintmap<T>) -> uint {
-    ret vec::len::<option::t<T>>(m.v);
+    ret vec::len::<option<T>>(m.v);
 }
 
 /*
@@ -98,7 +98,7 @@ fn insert(&&key: uint, value: V) -> bool {
         insert(self, key, value);
         ret !exists;
     }
-    fn remove(&&key: uint) -> option::t<V> {
+    fn remove(&&key: uint) -> option<V> {
         if key >= vec::len(self.v) { ret none; }
         let old = self.v[key];
         self.v[key] = none;
@@ -108,7 +108,7 @@ fn contains_key(&&key: uint) -> bool {
         contains_key(self, key)
     }
     fn get(&&key: uint) -> V { get(self, key) }
-    fn find(&&key: uint) -> option::t<V> { find(self, key) }
+    fn find(&&key: uint) -> option<V> { find(self, key) }
     fn rehash() { fail }
     fn items(it: fn(&&uint, V)) {
         let idx = 0u;
index f7f6812d7defef6da20424cc98ef312a4e456a63..8c4ac9240552eca581c2ebf28ede011cff2eb9b3 100644 (file)
@@ -9,8 +9,8 @@
 export quick_sort;
 export quick_sort3;
 
-/* Type: lteq */
-type lteq<T> = fn(T, T) -> bool;
+/* Type: le */
+type le<T> = fn(T, T) -> bool;
 
 /*
 Function: merge_sort
@@ -20,8 +20,8 @@
 Has worst case O(n log n) performance, best case O(n), but
 is not space efficient. This is a stable sort.
 */
-fn merge_sort<T: copy>(le: lteq<T>, v: [const T]) -> [T] {
-    fn merge<T: copy>(le: lteq<T>, a: [T], b: [T]) -> [T] {
+fn merge_sort<T: copy>(le: le<T>, v: [const T]) -> [T] {
+    fn merge<T: copy>(le: le<T>, a: [T], b: [T]) -> [T] {
         let rs: [T] = [];
         let a_len: uint = len::<T>(a);
         let a_ix: uint = 0u;
@@ -46,7 +46,7 @@ fn merge<T: copy>(le: lteq<T>, a: [T], b: [T]) -> [T] {
     ret merge::<T>(le, merge_sort::<T>(le, a), merge_sort::<T>(le, b));
 }
 
-fn part<T: copy>(compare_func: lteq<T>, arr: [mutable T], left: uint,
+fn part<T: copy>(compare_func: le<T>, arr: [mutable T], left: uint,
                 right: uint, pivot: uint) -> uint {
     let pivot_value = arr[pivot];
     arr[pivot] <-> arr[right];
@@ -63,7 +63,7 @@ fn part<T: copy>(compare_func: lteq<T>, arr: [mutable T], left: uint,
     ret storage_index;
 }
 
-fn qsort<T: copy>(compare_func: lteq<T>, arr: [mutable T], left: uint,
+fn qsort<T: copy>(compare_func: le<T>, arr: [mutable T], left: uint,
              right: uint) {
     if right > left {
         let pivot = (left + right) / 2u;
@@ -84,12 +84,12 @@ fn qsort<T: copy>(compare_func: lteq<T>, arr: [mutable T], left: uint,
 Has worst case O(n^2) performance, average case O(n log n).
 This is an unstable sort.
 */
-fn quick_sort<T: copy>(compare_func: lteq<T>, arr: [mutable T]) {
+fn quick_sort<T: copy>(compare_func: le<T>, arr: [mutable T]) {
     if len::<T>(arr) == 0u { ret; }
     qsort::<T>(compare_func, arr, 0u, len::<T>(arr) - 1u);
 }
 
-fn qsort3<T: copy>(compare_func_lt: lteq<T>, compare_func_eq: lteq<T>,
+fn qsort3<T: copy>(compare_func_lt: le<T>, compare_func_eq: le<T>,
                   arr: [mutable T], left: int, right: int) {
     if right <= left { ret; }
     let v: T = arr[right];
@@ -150,7 +150,7 @@ fn qsort3<T: copy>(compare_func_lt: lteq<T>, compare_func_eq: lteq<T>,
 
 This is an unstable sort.
 */
-fn quick_sort3<T: copy>(compare_func_lt: lteq<T>, compare_func_eq: lteq<T>,
+fn quick_sort3<T: copy>(compare_func_lt: le<T>, compare_func_eq: le<T>,
                        arr: [mutable T]) {
     if len::<T>(arr) == 0u { ret; }
     qsort3::<T>(compare_func_lt, compare_func_eq, arr, 0,
@@ -204,8 +204,8 @@ fn test() {
 mod test_qsort {
     fn check_sort(v1: [mutable int], v2: [mutable int]) {
         let len = vec::len::<int>(v1);
-        fn ltequal(&&a: int, &&b: int) -> bool { ret a <= b; }
-        let f = ltequal;
+        fn leual(&&a: int, &&b: int) -> bool { ret a <= b; }
+        let f = leual;
         quick_sort::<int>(f, v1);
         let i = 0u;
         while i < len {
@@ -247,8 +247,8 @@ fn test_simple() {
 
         let expected = [1, 2, 3];
 
-        fn lteq(&&a: int, &&b: int) -> bool { int::le(a, b) }
-        sort::quick_sort(lteq, names);
+        fn le(&&a: int, &&b: int) -> bool { int::le(a, b) }
+        sort::quick_sort(le, names);
 
         let immut_names = vec::from_mut(names);
 
@@ -264,8 +264,8 @@ mod tests {
 
     fn check_sort(v1: [int], v2: [int]) {
         let len = vec::len::<int>(v1);
-        fn lteq(&&a: int, &&b: int) -> bool { ret a <= b; }
-        let f = lteq;
+        fn le(&&a: int, &&b: int) -> bool { ret a <= b; }
+        let f = le;
         let v3 = merge_sort::<int>(f, v1);
         let i = 0u;
         while i < len {
@@ -294,9 +294,9 @@ fn test() {
 
     #[test]
     fn test_merge_sort_mutable() {
-        fn lteq(&&a: int, &&b: int) -> bool { ret a <= b; }
+        fn le(&&a: int, &&b: int) -> bool { ret a <= b; }
         let v1 = [mutable 3, 2, 1];
-        let v2 = merge_sort(lteq, v1);
+        let v2 = merge_sort(le, v1);
         assert v2 == [1, 2, 3];
     }
 }
index 197c1a71cb02d384d622289c5a932ff47419e1fc..eaf1409da1d77b1130a8100cdb5438f94c5e9ff9 100644 (file)
@@ -12,7 +12,7 @@
 /*
 Function: mkdtemp
 */
-fn mkdtemp(prefix: str, suffix: str) -> option::t<str> {
+fn mkdtemp(prefix: str, suffix: str) -> option<str> {
     let r = rand::mk_rng();
     let i = 0u;
     while (i < 1000u) {
index 707e4cf153fb21a61bff36d1ecdb0bb162d31002..6d7273ff0b19398845f754781f57fa45b566cd57 100644 (file)
@@ -56,7 +56,7 @@ fn test_main(args: [str], tests: [test_desc]) {
     if !run_tests_console(opts, tests) { fail "Some tests failed"; }
 }
 
-type test_opts = {filter: option::t<str>, run_ignored: bool};
+type test_opts = {filter: option<str>, run_ignored: bool};
 
 type opt_res = either::t<test_opts, str>;
 
@@ -248,7 +248,7 @@ fn filter_tests(opts: test_opts,
         };
 
         fn filter_fn(test: test_desc, filter_str: str) ->
-            option::t<test_desc> {
+            option<test_desc> {
             if str::find(test.name, filter_str) >= 0 {
                 ret option::some(test);
             } else { ret option::none; }
@@ -263,7 +263,7 @@ fn filter_fn(test: test_desc, filter_str: str) ->
     filtered = if !opts.run_ignored {
         filtered
     } else {
-        fn filter(test: test_desc) -> option::t<test_desc> {
+        fn filter(test: test_desc) -> option<test_desc> {
             if test.ignore {
                 ret option::some({name: test.name,
                                   fn: test.fn,
@@ -279,7 +279,7 @@ fn filter(test: test_desc) -> option::t<test_desc> {
     filtered =
         {
             fn lteq(t1: test_desc, t2: test_desc) -> bool {
-                str::lteq(t1.name, t2.name)
+                str::le(t1.name, t2.name)
             }
             sort::merge_sort(bind lteq(_, _), filtered)
         };
@@ -398,7 +398,8 @@ fn f() { }
     fn first_free_arg_should_be_a_filter() {
         let args = ["progname", "filter"];
         check (vec::is_not_empty(args));
-        let opts = alt parse_opts(args) { either::left(o) { o } };
+        let opts = alt parse_opts(args) { either::left(o) { o }
+          _ { fail "Malformed arg in first_free_arg_should_be_a_filter"; } };
         assert (str::eq("filter", option::get(opts.filter)));
     }
 
@@ -406,7 +407,8 @@ fn first_free_arg_should_be_a_filter() {
     fn parse_ignored_flag() {
         let args = ["progname", "filter", "--ignored"];
         check (vec::is_not_empty(args));
-        let opts = alt parse_opts(args) { either::left(o) { o } };
+        let opts = alt parse_opts(args) { either::left(o) { o }
+          _ { fail "Malformed arg in parse_ignored_flag"; } };
         assert (opts.run_ignored);
     }
 
index 4771bc3196bd56394f6f76d8d98bbefab6ef77be..bcea14df37720465fb17e31bd2c36112a2eef56e 100644 (file)
@@ -10,7 +10,7 @@
 */
 
 import core::option::{some, none};
-import option = core::option::t;
+import option = core::option;
 
 export treemap;
 export init;
@@ -66,14 +66,13 @@ fn insert<K: copy, V: copy>(m: treemap<K, V>, k: K, v: V) {
 fn find<K: copy, V: copy>(m: treemap<K, V>, k: K) -> option<V> {
     alt *m {
       empty { none }
-      node(@kk, @v, _, _) {
+      // TODO: was that an optimization?
+      node(@kk, @v, left, right) {
         if k == kk {
             some(v)
         } else if k < kk {
-
-            // Again, ugliness to unpack left and right individually.
-            alt *m { node(_, _, left, _) { find(left, k) } }
-        } else { alt *m { node(_, _, _, right) { find(right, k) } } }
+            find(left, k)
+        } else { find(right, k) }
       }
     }
 }
@@ -86,11 +85,16 @@ fn find<K: copy, V: copy>(m: treemap<K, V>, k: K) -> option<V> {
 fn traverse<K, V>(m: treemap<K, V>, f: fn(K, V)) {
     alt *m {
       empty { }
-      node(k, v, _, _) {
+      /*
+        Previously, this had what looked like redundant
+        matches to me, so I changed it. but that may be a
+        de-optimization -- tjc
+       */
+      node(k, v, left, right) {
         let k1 = k, v1 = v;
-        alt *m { node(_, _, left, _) { traverse(left, f); } }
+        traverse(left, f);
         f(*k1, *v1);
-        alt *m { node(_, _, _, right) { traverse(right, f); } }
+        traverse(right, f);
       }
     }
 }
index 322e3bf40c27a83e021ce0c50cb0b0916f0d6bf0..eee4c836277a872782489f95270a4a278a3c7194 100644 (file)
@@ -6,7 +6,7 @@
 // A very naive implementation of union-find with unsigned integer nodes.
 // Maintains the invariant that the root of a node is always equal to or less
 // than the node itself.
-type node = option::t<uint>;
+type node = option<uint>;
 
 type ufind = {mutable nodes: [mutable node]};
 
index c7f6baf14a216648766cd6352686bad1fd7c922d..27f2a3c54a85ca6fbcf7c9dc1db8a9378921a567 100644 (file)
@@ -3,10 +3,6 @@
 the C libuv API. Does very little right now pending scheduler improvements.
 */
 
-#[cfg(target_os = "linux")];
-#[cfg(target_os = "macos")];
-#[cfg(target_os = "freebsd")];
-
 export sanity_check;
 export loop_t, idle_t;
 export loop_new, loop_delete, default_loop, run, unref;
@@ -38,9 +34,6 @@
 type close_cb = opaque_cb;
 type idle_cb = opaque_cb;
 
-#[cfg(target_os = "linux")]
-#[cfg(target_os = "macos")]
-#[cfg(target_os = "freebsd")]
 type handle_private_fields = {
     a00: ctypes::c_int,
     a01: ctypes::c_int,
@@ -114,16 +107,13 @@ fn unref(loop: *loop_t) {
 fn sanity_check() {
     fn check_size(t: str, uv: ctypes::size_t, rust: ctypes::size_t) {
         #debug("size of %s: uv: %u, rust: %u", t, uv, rust);
-        assert uv == rust;
+        assert uv <= rust;
     }
     check_size("idle_t",
                helpers::rust_uv_size_of_idle_t(),
                sys::size_of::<idle_t>());
 }
 
-#[cfg(target_os = "linux")]
-#[cfg(target_os = "macos")]
-#[cfg(target_os = "freebsd")]
 fn handle_fields_new() -> handle_fields {
     {
         loop: ptr::null(),
@@ -196,4 +186,3 @@ fn async_ref() {
         }
     }
 }
-
index ae08cd5ed5e013b7dd3767675376d0a2d36d6eae..d18a59031eaf66e41a86cc743365caed8c5bd67e 100644 (file)
@@ -1,10 +1,5 @@
 // Some temporary libuv hacks for servo
 
-#[cfg(target_os = "linux")];
-#[cfg(target_os = "macos")];
-#[cfg(target_os = "freebsd")];
-
-
 #[nolink]
 native mod rustrt {
     fn rust_uvtmp_create_thread() -> thread;
@@ -120,6 +115,7 @@ fn test_connect() {
       connected(cd) {
         close_connection(thread, 0u32);
       }
+      _ { fail "test_connect: port isn't connected"; }
     }
     join_thread(thread);
     delete_thread(thread);
@@ -149,19 +145,23 @@ fn test_http() {
                   read(_, buf, len) {
                     unsafe {
                         log(error, len);
-                        let buf = vec::unsafe::from_buf(buf, len as uint);
+                        let buf = vec::unsafe::from_buf(buf,
+                                                        len as uint);
                         let str = str::from_bytes(buf);
                         #error("read something");
                         io::println(str);
                     }
                     delete_buf(buf);
                   }
+                  _ { fail "test_http: protocol error"; }
                 }
             }
             close_connection(thread, 0u32);
           }
+          _ { fail "test_http: expected `wrote`"; }
         }
       }
+      _ { fail "test_http: port not connected"; }
     }
     join_thread(thread);
     delete_thread(thread);
index 83306c757a4dd9bbad46fcfbc77be85449915223..ddc1ebd7a356185c62f044dfb90a4e2a4554e08d 100644 (file)
@@ -1,18 +1,20 @@
 import core::option;
 import core::ctypes::*;
 
+enum FILE_opaque {}
+type FILE = *FILE_opaque;
+
 #[abi = "cdecl"]
 #[nolink]
 native mod libc {
     fn read(fd: fd_t, buf: *u8, count: size_t) -> ssize_t;
     fn write(fd: fd_t, buf: *u8, count: size_t) -> ssize_t;
-    fn fread(buf: *u8, size: size_t, n: size_t, f: libc::FILE) -> size_t;
-    fn fwrite(buf: *u8, size: size_t, n: size_t, f: libc::FILE) -> size_t;
+    fn fread(buf: *u8, size: size_t, n: size_t, f: FILE) -> size_t;
+    fn fwrite(buf: *u8, size: size_t, n: size_t, f: FILE) -> size_t;
     #[link_name = "_open"]
     fn open(s: str::sbuf, flags: c_int, mode: unsigned) -> c_int;
     #[link_name = "_close"]
     fn close(fd: fd_t) -> c_int;
-    type FILE;
     fn fopen(path: str::sbuf, mode: str::sbuf) -> FILE;
     fn _fdopen(fd: fd_t, mode: str::sbuf) -> FILE;
     fn fclose(f: FILE);
@@ -42,16 +44,17 @@ mod libc_constants {
 }
 
 type DWORD = u32;
-type HMODULE = uint;
+type HMODULE = c_uint;
 type LPTSTR = str::sbuf;
 type LPCTSTR = str::sbuf;
 
+type LPSECURITY_ATTRIBUTES = *ctypes::void;
+
 #[abi = "stdcall"]
 native mod kernel32 {
-    type LPSECURITY_ATTRIBUTES;
-    fn GetEnvironmentVariableA(n: str::sbuf, v: str::sbuf, nsize: uint) ->
-       uint;
-    fn SetEnvironmentVariableA(n: str::sbuf, v: str::sbuf) -> int;
+    fn GetEnvironmentVariableA(n: str::sbuf, v: str::sbuf, nsize: c_uint) ->
+       c_uint;
+    fn SetEnvironmentVariableA(n: str::sbuf, v: str::sbuf) -> c_int;
     fn GetModuleFileNameA(hModule: HMODULE,
                           lpFilename: LPTSTR,
                           nSize: DWORD) -> DWORD;
@@ -84,7 +87,7 @@ fn pipe() -> {in: fd_t, out: fd_t} {
     ret {in: fds.in, out: fds.out};
 }
 
-fn fd_FILE(fd: fd_t) -> libc::FILE {
+fn fd_FILE(fd: fd_t) -> FILE {
     ret str::as_buf("r", {|modebuf| libc::_fdopen(fd, modebuf) });
 }
 
@@ -92,11 +95,11 @@ fn close(fd: fd_t) -> c_int {
     libc::close(fd)
 }
 
-fn fclose(file: libc::FILE) {
+fn fclose(file: FILE) {
     libc::fclose(file)
 }
 
-fn fsync_fd(fd: fd_t, level: io::fsync::level) -> c_int {
+fn fsync_fd(_fd: fd_t, _level: io::fsync::level) -> c_int {
     // FIXME (1253)
     fail;
 }
@@ -111,7 +114,7 @@ fn fsync_fd(fd: fd_t, level: io::fsync::level) -> c_int {
 
 fn getcwd() -> str { ret rustrt::rust_getcwd(); }
 
-fn get_exe_path() -> option::t<fs::path> {
+fn get_exe_path() -> option<fs::path> {
     // FIXME: This doesn't handle the case where the buffer is too small
     // FIXME: path "strings" will likely need fixing...
     let bufsize = 1023u;
index f1859eb841be2fe48512bc10e64556383f408b01..1170ffba3ac5191930b40c897d4569a9d8a296a3 160000 (submodule)
--- a/src/libuv
+++ b/src/libuv
@@ -1 +1 @@
-Subproject commit f1859eb841be2fe48512bc10e64556383f408b01
+Subproject commit 1170ffba3ac5191930b40c897d4569a9d8a296a3
diff --git a/src/rt/boxed_region.cpp b/src/rt/boxed_region.cpp
new file mode 100644 (file)
index 0000000..937069b
--- /dev/null
@@ -0,0 +1,59 @@
+#include <assert.h>
+#include "boxed_region.h"
+#include "rust_internal.h"
+
+// #define DUMP_BOXED_REGION
+
+rust_opaque_box *boxed_region::malloc(type_desc *td) {
+    size_t header_size = sizeof(rust_opaque_box);
+    size_t body_size = td->size;
+    size_t body_align = td->align;
+    size_t total_size = align_to(header_size, body_align) + body_size;
+    rust_opaque_box *box =
+      (rust_opaque_box*)backing_region->malloc(total_size, "@");
+    box->td = td;
+    box->ref_count = 1;
+    box->prev = NULL;
+    box->next = live_allocs;
+    if (live_allocs) live_allocs->prev = box;
+    live_allocs = box;
+
+#   ifdef DUMP_BOXED_REGION
+    fprintf(stderr, "Allocated box %p with td %p,"
+            " size %lu==%lu+%lu, align %lu, prev %p, next %p\n",
+            box, td, total_size, header_size, body_size, body_align,
+            box->prev, box->next);
+#   endif
+
+    return box;
+}
+
+rust_opaque_box *boxed_region::calloc(type_desc *td) {
+    rust_opaque_box *box = malloc(td);
+    memset(box_body(box), 0, td->size);
+    return box;
+}
+
+void boxed_region::free(rust_opaque_box *box) {
+    // This turns out to not be true in various situations,
+    // like when we are unwinding after a failure.
+    //
+    // assert(box->ref_count == 0);
+
+    // This however should always be true.  Helps to detect
+    // double frees (kind of).
+    assert(box->td != NULL);
+
+#   ifdef DUMP_BOXED_REGION
+    fprintf(stderr, "Freed box %p with td %p, prev %p, next %p\n",
+            box, box->td, box->prev, box->next);
+#   endif
+
+    if (box->prev) box->prev->next = box->next;
+    if (box->next) box->next->prev = box->prev;
+    if (live_allocs == box) live_allocs = box->next;
+    box->prev = NULL;
+    box->next = NULL;
+    box->td = NULL;
+    backing_region->free(box);
+}
diff --git a/src/rt/boxed_region.h b/src/rt/boxed_region.h
new file mode 100644 (file)
index 0000000..bd5312f
--- /dev/null
@@ -0,0 +1,39 @@
+#ifndef BOXED_REGION_H
+#define BOXED_REGION_H
+
+#include <stdlib.h>
+
+struct type_desc;
+class memory_region;
+struct rust_opaque_box;
+
+/* Tracks the data allocated by a particular task in the '@' region.
+ * Currently still relies on the standard malloc as a backing allocator, but
+ * this could be improved someday if necessary. Every allocation must provide
+ * a type descr which describes the payload (what follows the header). */
+class boxed_region {
+private:
+    memory_region *backing_region;
+    rust_opaque_box *live_allocs;
+
+    size_t align_to(size_t v, size_t align) {
+        size_t alignm1 = align - 1;
+        v += alignm1;
+        v &= ~alignm1;
+        return v;
+    }
+
+public:
+    boxed_region(memory_region *br)
+        : backing_region(br)
+        , live_allocs(NULL)
+    {}
+
+    rust_opaque_box *first_live_alloc() { return live_allocs; }
+
+    rust_opaque_box *malloc(type_desc *td);
+    rust_opaque_box *calloc(type_desc *td);
+    void free(rust_opaque_box *box);
+};
+
+#endif /* BOXED_REGION_H */
index 2e897bce797656d358bbdca2f62064d009ff59d9..090279d83e3ae3ca0fe291b0bf3be4b54185ba04 100644 (file)
@@ -4,12 +4,12 @@
 // Build with the script in src/etc/gen-intrinsics
 
 #include "../rust_internal.h"
-#include "../rust_scheduler.h"
+#include "../rust_util.h"
 #include <cstdlib>
 #include <cstring>
 
 extern "C" CDECL void
-rust_task_sleep(rust_task *task, size_t time_in_us, bool *killed);
+rust_task_yield(rust_task *task, bool *killed);
 
 extern "C" void
 rust_intrinsic_vec_len(size_t *retptr,
@@ -76,11 +76,10 @@ rust_intrinsic_get_type_desc(void **retptr,
 }
 
 extern "C" void
-rust_intrinsic_task_sleep(void **retptr,
+rust_intrinsic_task_yield(void **retptr,
                           void *env,
                          rust_task *task,
-                          size_t time_in_us,
                          bool *killed) {
-    rust_task_sleep(task, time_in_us, killed);
+    rust_task_yield(task, killed);
 }
 
index 0edf3d3ddf01ff92f35a26f612226217af64bcfc..3bb9e8aae1262db4de2945376ef0bf571c8755e5 100644 (file)
@@ -10,109 +10,115 @@ target triple = "@CFG_TARGET_TRIPLE@"
 %struct.rust_vec = type { i32, i32, [0 x i8] }
 %struct.rust_fn = type { i32*, %struct.rust_box* }
 %struct.rust_box = type opaque
-%struct.rust_task = type { %struct.rust_task_user, i32, %class.context, %struct.stk_seg*, i32, %struct.rust_scheduler*, %class.rust_crate_cache*, %class.rust_kernel*, i8*, %class.rust_task_list*, %struct.rust_cond*, i8*, %struct.rust_task*, i32, i32, %class.timer, i32*, i32, i32, %class.memory_region, i8, i8, i8, %class.lock_and_signal, %class.hash_map.4, %class.rust_obstack, %"class.std::map", i32, %"class.debug::task_debug_info" }
+%struct.rust_task = type { %struct.rust_task_user, i32, [8 x i8], %class.context, %struct.stk_seg*, i32, %struct.rust_task_thread*, %class.rust_crate_cache*, %class.rust_kernel*, i8*, %class.rust_task_list*, %struct.rust_cond*, i8*, %struct.rust_task*, i32, i32, i32*, %class.memory_region, %class.boxed_region, i8, i8, i8, %class.lock_and_signal, %class.hash_map.4, %class.rust_obstack, i32, %"class.debug::task_debug_info", i32, [4 x i8] }
 %struct.rust_task_user = type { i32, i32, %struct.chan_handle, i32 }
 %struct.chan_handle = type { i32, i32 }
-%class.context = type { %struct.registers_t, %class.context* }
-%struct.registers_t = type { i32, i32, i32, i32, i32, i32, i32, i32, i16, i16, i16, i16, i16, i16, i32, i32 }
-%struct.stk_seg = type { %struct.stk_seg*, i32, i32, i32, [0 x i8] }
-%struct.rust_scheduler = type { %class.rust_thread, i32, i32, %class.rust_log, i32, %class.rust_srv*, i8*, %class.rust_task_list, %class.rust_task_list, %class.rust_task_list, %class.rust_task_list, %class.rust_crate_cache, %struct.randctx, %class.rust_kernel*, i32, i32, %class.lock_and_signal, i32, %union.pthread_attr_t, %struct.rust_env*, %class.context }
+%class.context = type { %struct.registers_t, %class.context*, [12 x i8] }
+%struct.registers_t = type { i32, i32, i32, i32, i32, i32, i32, i32, i16, i16, i16, i16, i16, i16, i32, i32, [12 x i8] }
+%struct.stk_seg = type { %struct.stk_seg*, %struct.stk_seg*, i32, i32, i32, [0 x i8] }
+%struct.rust_task_thread = type { %class.rust_thread, i32, %class.rust_log, i32, %class.rust_srv*, i8*, %class.rust_task_list, %class.rust_task_list, %class.rust_task_list, %class.rust_task_list, %class.rust_crate_cache, %struct.randctx, %class.rust_kernel*, i32, i32, %class.lock_and_signal, i32, %union.pthread_attr_t, %struct.rust_env*, [12 x i8], %class.context, i8, [15 x i8] }
 %class.rust_thread = type { i32 (...)**, i8, i32 }
-%class.rust_log = type { i32 (...)**, %class.rust_srv*, %struct.rust_scheduler*, i8 }
+%class.rust_log = type { i32 (...)**, %class.rust_srv*, %struct.rust_task_thread*, i8 }
 %class.rust_srv = type { i32 (...)**, %struct.rust_env*, %class.memory_region }
-%struct.rust_env = type { i32, i32, i8*, i8, i8, i8* }
+%struct.rust_env = type { i32, i32, i32, i8*, i8, i8, i8* }
 %class.memory_region = type { i32 (...)**, %class.rust_srv*, %class.memory_region*, i32, %class.array_list, i8, i8, %class.lock_and_signal }
 %class.array_list = type { i32, %"struct.memory_region::alloc_header"**, i32 }
 %"struct.memory_region::alloc_header" = type { i8 }
-%class.lock_and_signal = type { i32 (...)**, %union.pthread_cond_t, %union.pthread_mutex_t, i32, i8, i8 }
+%class.lock_and_signal = type { i32 (...)**, %union.pthread_cond_t, %union.pthread_mutex_t, i32 }
 %union.pthread_cond_t = type { %struct.anon, [4 x i8] }
 %struct.anon = type { i32, i32, i64, i64, i64, i8*, i32, i32 }
 %union.pthread_mutex_t = type { %"struct.<anonymous union>::__pthread_mutex_s" }
 %"struct.<anonymous union>::__pthread_mutex_s" = type { i32, i32, i32, i32, i32, %union.anon }
 %union.anon = type { i32 }
-%class.rust_task_list = type { %class.indexed_list, %struct.rust_scheduler*, i8* }
+%class.rust_task_list = type { %class.indexed_list, %struct.rust_task_thread*, i8* }
 %class.indexed_list = type { i32 (...)**, %class.array_list.1 }
 %class.array_list.1 = type { i32, %struct.rust_task**, i32 }
-%class.rust_crate_cache = type { %struct.type_desc*, %struct.rust_scheduler*, i32 }
+%class.rust_crate_cache = type { %struct.type_desc*, %struct.rust_hashable_dict*, %struct.rust_task_thread*, i32 }
+%struct.rust_hashable_dict = type { %struct.UT_hash_handle, [0 x i8*] }
 %struct.randctx = type { i32, [256 x i32], [256 x i32], i32, i32, i32 }
 %class.rust_kernel = type { i32 (...)**, %class.memory_region, %class.rust_log, %class.rust_srv*, %class.lock_and_signal, %class.array_list.3, %struct.randctx, i32, %class.hash_map, i32, i32, i32, %struct.rust_env* }
-%class.array_list.3 = type { i32, %struct.rust_scheduler**, i32 }
+%class.array_list.3 = type { i32, %struct.rust_task_thread**, i32 }
 %class.hash_map = type { %"struct.hash_map<int, rust_task *>::map_entry"* }
 %"struct.hash_map<int, rust_task *>::map_entry" = type opaque
 %union.pthread_attr_t = type { i32, [32 x i8] }
 %struct.rust_cond = type { i8 }
-%class.timer = type { i32 (...)**, i64, i64 }
+%class.boxed_region = type { %class.memory_region*, %struct.rust_opaque_box* }
+%struct.rust_opaque_box = type { i32, %struct.type_desc*, %struct.rust_opaque_box*, %struct.rust_opaque_box* }
 %class.hash_map.4 = type { %"struct.hash_map<int, rust_port *>::map_entry"* }
 %"struct.hash_map<int, rust_port *>::map_entry" = type opaque
 %class.rust_obstack = type { %struct.rust_obstack_chunk*, %struct.rust_task* }
 %struct.rust_obstack_chunk = type { %struct.rust_obstack_chunk*, i32, i32, i32, [0 x i8] }
+%"class.debug::task_debug_info" = type { %"class.std::map" }
 %"class.std::map" = type { %"class.std::_Rb_tree" }
-%"class.std::_Rb_tree" = type { %"struct.std::_Rb_tree<void *, std::pair<void *const, const type_desc *>, std::_Select1st<std::pair<void *const, const type_desc *> >, std::less<void *>, std::allocator<std::pair<void *const, const type_desc *> > >::_Rb_tree_impl" }
-%"struct.std::_Rb_tree<void *, std::pair<void *const, const type_desc *>, std::_Select1st<std::pair<void *const, const type_desc *> >, std::less<void *>, std::allocator<std::pair<void *const, const type_desc *> > >::_Rb_tree_impl" = type { %"struct.std::less", %"struct.std::_Rb_tree_node_base", i32 }
+%"class.std::_Rb_tree" = type { %"struct.std::_Rb_tree<void *, std::pair<void *const, std::basic_string<char> >, std::_Select1st<std::pair<void *const, std::basic_string<char> > >, std::less<void *>, std::allocator<std::pair<void *const, std::basic_string<char> > > >::_Rb_tree_impl" }
+%"struct.std::_Rb_tree<void *, std::pair<void *const, std::basic_string<char> >, std::_Select1st<std::pair<void *const, std::basic_string<char> > >, std::less<void *>, std::allocator<std::pair<void *const, std::basic_string<char> > > >::_Rb_tree_impl" = type { %"struct.std::less", %"struct.std::_Rb_tree_node_base", i32 }
 %"struct.std::less" = type { i8 }
 %"struct.std::_Rb_tree_node_base" = type { i32, %"struct.std::_Rb_tree_node_base"*, %"struct.std::_Rb_tree_node_base"*, %"struct.std::_Rb_tree_node_base"* }
-%"class.debug::task_debug_info" = type { %"class.std::map.5" }
-%"class.std::map.5" = type { %"class.std::_Rb_tree.6" }
-%"class.std::_Rb_tree.6" = type { %"struct.std::_Rb_tree<void *, std::pair<void *const, std::basic_string<char> >, std::_Select1st<std::pair<void *const, std::basic_string<char> > >, std::less<void *>, std::allocator<std::pair<void *const, std::basic_string<char> > > >::_Rb_tree_impl" }
-%"struct.std::_Rb_tree<void *, std::pair<void *const, std::basic_string<char> >, std::_Select1st<std::pair<void *const, std::basic_string<char> > >, std::less<void *>, std::allocator<std::pair<void *const, std::basic_string<char> > > >::_Rb_tree_impl" = type { %"struct.std::less", %"struct.std::_Rb_tree_node_base", i32 }
 
 define void @rust_intrinsic_vec_len(i32* nocapture %retptr, i8* nocapture %env, %struct.type_desc* nocapture %ty, %struct.rust_vec** nocapture %vp) nounwind {
-  %1 = load %struct.rust_vec** %vp, align 4, !tbaa !0
-  %2 = getelementptr inbounds %struct.rust_vec* %1, i32 0, i32 0
-  %3 = load i32* %2, align 4, !tbaa !3
-  %4 = getelementptr inbounds %struct.type_desc* %ty, i32 0, i32 1
-  %5 = load i32* %4, align 4, !tbaa !3
-  %6 = udiv i32 %3, %5
-  store i32 %6, i32* %retptr, align 4, !tbaa !3
+entry:
+  %0 = load %struct.rust_vec** %vp, align 4, !tbaa !0
+  %fill = getelementptr inbounds %struct.rust_vec* %0, i32 0, i32 0
+  %1 = load i32* %fill, align 4, !tbaa !3
+  %size = getelementptr inbounds %struct.type_desc* %ty, i32 0, i32 1
+  %2 = load i32* %size, align 4, !tbaa !3
+  %div = udiv i32 %1, %2
+  store i32 %div, i32* %retptr, align 4, !tbaa !3
   ret void
 }
 
 define void @rust_intrinsic_ptr_offset(i8** nocapture %retptr, i8* nocapture %env, %struct.type_desc* nocapture %ty, i8* %ptr, i32 %count) nounwind {
-  %1 = getelementptr inbounds %struct.type_desc* %ty, i32 0, i32 1
-  %2 = load i32* %1, align 4, !tbaa !3
-  %3 = mul i32 %2, %count
-  %4 = getelementptr inbounds i8* %ptr, i32 %3
-  store i8* %4, i8** %retptr, align 4, !tbaa !0
+entry:
+  %size = getelementptr inbounds %struct.type_desc* %ty, i32 0, i32 1
+  %0 = load i32* %size, align 4, !tbaa !3
+  %mul = mul i32 %0, %count
+  %arrayidx = getelementptr inbounds i8* %ptr, i32 %mul
+  store i8* %arrayidx, i8** %retptr, align 4, !tbaa !0
   ret void
 }
 
 define void @rust_intrinsic_cast(i8* nocapture %retptr, i8* nocapture %env, %struct.type_desc* nocapture %t1, %struct.type_desc* nocapture %t2, i8* nocapture %src) nounwind {
-  %1 = getelementptr inbounds %struct.type_desc* %t1, i32 0, i32 1
-  %2 = load i32* %1, align 4, !tbaa !3
-  tail call void @llvm.memmove.p0i8.p0i8.i32(i8* %retptr, i8* %src, i32 %2, i32 1, i1 false)
+entry:
+  %size = getelementptr inbounds %struct.type_desc* %t1, i32 0, i32 1
+  %0 = load i32* %size, align 4, !tbaa !3
+  tail call void @llvm.memmove.p0i8.p0i8.i32(i8* %retptr, i8* %src, i32 %0, i32 1, i1 false)
   ret void
 }
 
 declare void @llvm.memmove.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i32, i1) nounwind
 
 define void @rust_intrinsic_addr_of(i8** nocapture %retptr, i8* nocapture %env, %struct.type_desc* nocapture %ty, i8* %valptr) nounwind {
+entry:
   store i8* %valptr, i8** %retptr, align 4, !tbaa !0
   ret void
 }
 
 define void @rust_intrinsic_call_with_retptr(i8** %retptr, i8* nocapture %env, %struct.type_desc* nocapture %ty, %struct.rust_fn* nocapture %recvfn) {
-  %1 = getelementptr inbounds %struct.rust_fn* %recvfn, i32 0, i32 0
-  %2 = load i32** %1, align 4, !tbaa !0
-  %3 = bitcast i32* %2 to void (i8**, i8*, i8**)*
-  %4 = getelementptr inbounds %struct.rust_fn* %recvfn, i32 0, i32 1
-  %5 = load %struct.rust_box** %4, align 4, !tbaa !0
-  %6 = bitcast %struct.rust_box* %5 to i8*
-  tail call void %3(i8** null, i8* %6, i8** %retptr)
+entry:
+  %fn1 = getelementptr inbounds %struct.rust_fn* %recvfn, i32 0, i32 0
+  %0 = load i32** %fn1, align 4, !tbaa !0
+  %1 = bitcast i32* %0 to void (i8**, i8*, i8**)*
+  %env2 = getelementptr inbounds %struct.rust_fn* %recvfn, i32 0, i32 1
+  %2 = load %struct.rust_box** %env2, align 4, !tbaa !0
+  %3 = bitcast %struct.rust_box* %2 to i8*
+  tail call void %1(i8** null, i8* %3, i8** %retptr)
   ret void
 }
 
 define void @rust_intrinsic_get_type_desc(i8** nocapture %retptr, i8* nocapture %env, %struct.type_desc* %ty) nounwind {
+entry:
   %ty.c = bitcast %struct.type_desc* %ty to i8*
   store i8* %ty.c, i8** %retptr, align 4, !tbaa !0
   ret void
 }
 
-define void @rust_intrinsic_task_sleep(i8** nocapture %retptr, i8* nocapture %env, %struct.rust_task* %task, i32 %time_in_us, i8* %killed) {
-  tail call void @rust_task_sleep(%struct.rust_task* %task, i32 %time_in_us, i8* %killed)
+define void @rust_intrinsic_task_yield(i8** nocapture %retptr, i8* nocapture %env, %struct.rust_task* %task, i8* %killed) {
+entry:
+  tail call void @rust_task_yield(%struct.rust_task* %task, i8* %killed)
   ret void
 }
 
-declare void @rust_task_sleep(%struct.rust_task*, i32, i8*)
+declare void @rust_task_yield(%struct.rust_task*, i8*)
 
 !0 = metadata !{metadata !"any pointer", metadata !1}
 !1 = metadata !{metadata !"omnipotent char", metadata !2}
index a1eaf123980097a59d5bad4e5a85d128df74e5b5..5f0e1709f6afe68c1f12173e3d02ca61bdfcf4fd 100644 (file)
@@ -10,109 +10,115 @@ target triple = "@CFG_TARGET_TRIPLE@"
 %struct.rust_vec = type { i64, i64, [0 x i8] }
 %struct.rust_fn = type { i64*, %struct.rust_box* }
 %struct.rust_box = type opaque
-%struct.rust_task = type { %struct.rust_task_user, i64, %class.context, %struct.stk_seg*, i64, %struct.rust_scheduler*, %class.rust_crate_cache*, %class.rust_kernel*, i8*, %class.rust_task_list*, %struct.rust_cond*, i8*, %struct.rust_task*, i32, i64, %class.timer, i64*, i32, i32, %class.memory_region, i8, i8, i8, %class.lock_and_signal, %class.hash_map.4, %class.rust_obstack, %"class.std::map", i32, %"class.debug::task_debug_info" }
+%struct.rust_task = type { %struct.rust_task_user, i64, %class.context, %struct.stk_seg*, i64, %struct.rust_task_thread*, %class.rust_crate_cache*, %class.rust_kernel*, i8*, %class.rust_task_list*, %struct.rust_cond*, i8*, %struct.rust_task*, i32, i64, i64*, %class.memory_region, %class.boxed_region, i8, i8, i8, %class.lock_and_signal, %class.hash_map.4, %class.rust_obstack, i32, %"class.debug::task_debug_info", i64, [8 x i8] }
 %struct.rust_task_user = type { i64, i64, %struct.chan_handle, i64 }
 %struct.chan_handle = type { i64, i64 }
-%class.context = type { %struct.registers_t, %class.context* }
+%class.context = type { %struct.registers_t, %class.context*, [8 x i8] }
 %struct.registers_t = type { [22 x i64] }
-%struct.stk_seg = type { %struct.stk_seg*, i64, i32, [0 x i8] }
-%struct.rust_scheduler = type { %class.rust_thread, i64, i64, %class.rust_log, i32, %class.rust_srv*, i8*, %class.rust_task_list, %class.rust_task_list, %class.rust_task_list, %class.rust_task_list, %class.rust_crate_cache, %struct.randctx, %class.rust_kernel*, i32, i32, %class.lock_and_signal, i64, %union.pthread_attr_t, %struct.rust_env*, %class.context }
+%struct.stk_seg = type { %struct.stk_seg*, %struct.stk_seg*, i64, i32, [0 x i8] }
+%struct.rust_task_thread = type { %class.rust_thread, i64, %class.rust_log, i32, %class.rust_srv*, i8*, %class.rust_task_list, %class.rust_task_list, %class.rust_task_list, %class.rust_task_list, %class.rust_crate_cache, %struct.randctx, %class.rust_kernel*, i32, i32, %class.lock_and_signal, i64, %union.pthread_attr_t, %struct.rust_env*, [8 x i8], %class.context, i8, [15 x i8] }
 %class.rust_thread = type { i32 (...)**, i8, i64 }
-%class.rust_log = type { i32 (...)**, %class.rust_srv*, %struct.rust_scheduler*, i8 }
+%class.rust_log = type { i32 (...)**, %class.rust_srv*, %struct.rust_task_thread*, i8 }
 %class.rust_srv = type { i32 (...)**, %struct.rust_env*, %class.memory_region }
-%struct.rust_env = type { i64, i64, i8*, i8, i8, i8* }
+%struct.rust_env = type { i64, i64, i64, i8*, i8, i8, i8* }
 %class.memory_region = type { i32 (...)**, %class.rust_srv*, %class.memory_region*, i32, %class.array_list, i8, i8, %class.lock_and_signal }
 %class.array_list = type { i64, %"struct.memory_region::alloc_header"**, i64 }
 %"struct.memory_region::alloc_header" = type { i8 }
-%class.lock_and_signal = type { i32 (...)**, %union.pthread_cond_t, %union.pthread_mutex_t, i64, i8, i8 }
+%class.lock_and_signal = type { i32 (...)**, %union.pthread_cond_t, %union.pthread_mutex_t, i64 }
 %union.pthread_cond_t = type { %struct.anon }
 %struct.anon = type { i32, i32, i64, i64, i64, i8*, i32, i32 }
 %union.pthread_mutex_t = type { %"struct.<anonymous union>::__pthread_mutex_s" }
 %"struct.<anonymous union>::__pthread_mutex_s" = type { i32, i32, i32, i32, i32, i32, %struct.__pthread_internal_list }
 %struct.__pthread_internal_list = type { %struct.__pthread_internal_list*, %struct.__pthread_internal_list* }
-%class.rust_task_list = type { %class.indexed_list, %struct.rust_scheduler*, i8* }
+%class.rust_task_list = type { %class.indexed_list, %struct.rust_task_thread*, i8* }
 %class.indexed_list = type { i32 (...)**, %class.array_list.1 }
 %class.array_list.1 = type { i64, %struct.rust_task**, i64 }
-%class.rust_crate_cache = type { %struct.type_desc*, %struct.rust_scheduler*, i64 }
+%class.rust_crate_cache = type { %struct.type_desc*, %struct.rust_hashable_dict*, %struct.rust_task_thread*, i64 }
+%struct.rust_hashable_dict = type { %struct.UT_hash_handle, [0 x i8*] }
 %struct.randctx = type { i64, [256 x i64], [256 x i64], i64, i64, i64 }
-%class.rust_kernel = type { i32 (...)**, %class.memory_region, %class.rust_log, %class.rust_srv*, %class.lock_and_signal, %class.array_list.3, %struct.randctx, i64, %class.hash_map, i64, i32, i32, %struct.rust_env* }
-%class.array_list.3 = type { i64, %struct.rust_scheduler**, i64 }
+%class.rust_kernel = type { i32 (...)**, %class.memory_region, %class.rust_log, %class.rust_srv*, %class.lock_and_signal, %class.array_list.3, %struct.randctx, i64, %class.hash_map, i32, i64, i32, %struct.rust_env* }
+%class.array_list.3 = type { i64, %struct.rust_task_thread**, i64 }
 %class.hash_map = type { %"struct.hash_map<long, rust_task *>::map_entry"* }
 %"struct.hash_map<long, rust_task *>::map_entry" = type opaque
 %union.pthread_attr_t = type { i64, [48 x i8] }
 %struct.rust_cond = type { i8 }
-%class.timer = type { i32 (...)**, i64, i64 }
+%class.boxed_region = type { %class.memory_region*, %struct.rust_opaque_box* }
+%struct.rust_opaque_box = type { i64, %struct.type_desc*, %struct.rust_opaque_box*, %struct.rust_opaque_box* }
 %class.hash_map.4 = type { %"struct.hash_map<long, rust_port *>::map_entry"* }
 %"struct.hash_map<long, rust_port *>::map_entry" = type opaque
 %class.rust_obstack = type { %struct.rust_obstack_chunk*, %struct.rust_task* }
 %struct.rust_obstack_chunk = type { %struct.rust_obstack_chunk*, i64, i64, i64, [0 x i8] }
+%"class.debug::task_debug_info" = type { %"class.std::map" }
 %"class.std::map" = type { %"class.std::_Rb_tree" }
-%"class.std::_Rb_tree" = type { %"struct.std::_Rb_tree<void *, std::pair<void *const, const type_desc *>, std::_Select1st<std::pair<void *const, const type_desc *> >, std::less<void *>, std::allocator<std::pair<void *const, const type_desc *> > >::_Rb_tree_impl" }
-%"struct.std::_Rb_tree<void *, std::pair<void *const, const type_desc *>, std::_Select1st<std::pair<void *const, const type_desc *> >, std::less<void *>, std::allocator<std::pair<void *const, const type_desc *> > >::_Rb_tree_impl" = type { %"struct.std::less", %"struct.std::_Rb_tree_node_base", i64 }
+%"class.std::_Rb_tree" = type { %"struct.std::_Rb_tree<void *, std::pair<void *const, std::basic_string<char> >, std::_Select1st<std::pair<void *const, std::basic_string<char> > >, std::less<void *>, std::allocator<std::pair<void *const, std::basic_string<char> > > >::_Rb_tree_impl" }
+%"struct.std::_Rb_tree<void *, std::pair<void *const, std::basic_string<char> >, std::_Select1st<std::pair<void *const, std::basic_string<char> > >, std::less<void *>, std::allocator<std::pair<void *const, std::basic_string<char> > > >::_Rb_tree_impl" = type { %"struct.std::less", %"struct.std::_Rb_tree_node_base", i64 }
 %"struct.std::less" = type { i8 }
 %"struct.std::_Rb_tree_node_base" = type { i32, %"struct.std::_Rb_tree_node_base"*, %"struct.std::_Rb_tree_node_base"*, %"struct.std::_Rb_tree_node_base"* }
-%"class.debug::task_debug_info" = type { %"class.std::map.5" }
-%"class.std::map.5" = type { %"class.std::_Rb_tree.6" }
-%"class.std::_Rb_tree.6" = type { %"struct.std::_Rb_tree<void *, std::pair<void *const, std::basic_string<char> >, std::_Select1st<std::pair<void *const, std::basic_string<char> > >, std::less<void *>, std::allocator<std::pair<void *const, std::basic_string<char> > > >::_Rb_tree_impl" }
-%"struct.std::_Rb_tree<void *, std::pair<void *const, std::basic_string<char> >, std::_Select1st<std::pair<void *const, std::basic_string<char> > >, std::less<void *>, std::allocator<std::pair<void *const, std::basic_string<char> > > >::_Rb_tree_impl" = type { %"struct.std::less", %"struct.std::_Rb_tree_node_base", i64 }
 
 define void @rust_intrinsic_vec_len(i64* nocapture %retptr, i8* nocapture %env, %struct.type_desc* nocapture %ty, %struct.rust_vec** nocapture %vp) nounwind uwtable {
-  %1 = load %struct.rust_vec** %vp, align 8, !tbaa !0
-  %2 = getelementptr inbounds %struct.rust_vec* %1, i64 0, i32 0
-  %3 = load i64* %2, align 8, !tbaa !3
-  %4 = getelementptr inbounds %struct.type_desc* %ty, i64 0, i32 1
-  %5 = load i64* %4, align 8, !tbaa !3
-  %6 = udiv i64 %3, %5
-  store i64 %6, i64* %retptr, align 8, !tbaa !3
+entry:
+  %0 = load %struct.rust_vec** %vp, align 8, !tbaa !0
+  %fill = getelementptr inbounds %struct.rust_vec* %0, i64 0, i32 0
+  %1 = load i64* %fill, align 8, !tbaa !3
+  %size = getelementptr inbounds %struct.type_desc* %ty, i64 0, i32 1
+  %2 = load i64* %size, align 8, !tbaa !3
+  %div = udiv i64 %1, %2
+  store i64 %div, i64* %retptr, align 8, !tbaa !3
   ret void
 }
 
 define void @rust_intrinsic_ptr_offset(i8** nocapture %retptr, i8* nocapture %env, %struct.type_desc* nocapture %ty, i8* %ptr, i64 %count) nounwind uwtable {
-  %1 = getelementptr inbounds %struct.type_desc* %ty, i64 0, i32 1
-  %2 = load i64* %1, align 8, !tbaa !3
-  %3 = mul i64 %2, %count
-  %4 = getelementptr inbounds i8* %ptr, i64 %3
-  store i8* %4, i8** %retptr, align 8, !tbaa !0
+entry:
+  %size = getelementptr inbounds %struct.type_desc* %ty, i64 0, i32 1
+  %0 = load i64* %size, align 8, !tbaa !3
+  %mul = mul i64 %0, %count
+  %arrayidx = getelementptr inbounds i8* %ptr, i64 %mul
+  store i8* %arrayidx, i8** %retptr, align 8, !tbaa !0
   ret void
 }
 
 define void @rust_intrinsic_cast(i8* nocapture %retptr, i8* nocapture %env, %struct.type_desc* nocapture %t1, %struct.type_desc* nocapture %t2, i8* nocapture %src) nounwind uwtable {
-  %1 = getelementptr inbounds %struct.type_desc* %t1, i64 0, i32 1
-  %2 = load i64* %1, align 8, !tbaa !3
-  tail call void @llvm.memmove.p0i8.p0i8.i64(i8* %retptr, i8* %src, i64 %2, i32 1, i1 false)
+entry:
+  %size = getelementptr inbounds %struct.type_desc* %t1, i64 0, i32 1
+  %0 = load i64* %size, align 8, !tbaa !3
+  tail call void @llvm.memmove.p0i8.p0i8.i64(i8* %retptr, i8* %src, i64 %0, i32 1, i1 false)
   ret void
 }
 
 declare void @llvm.memmove.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i32, i1) nounwind
 
 define void @rust_intrinsic_addr_of(i8** nocapture %retptr, i8* nocapture %env, %struct.type_desc* nocapture %ty, i8* %valptr) nounwind uwtable {
+entry:
   store i8* %valptr, i8** %retptr, align 8, !tbaa !0
   ret void
 }
 
 define void @rust_intrinsic_call_with_retptr(i8** %retptr, i8* nocapture %env, %struct.type_desc* nocapture %ty, %struct.rust_fn* nocapture %recvfn) uwtable {
-  %1 = getelementptr inbounds %struct.rust_fn* %recvfn, i64 0, i32 0
-  %2 = load i64** %1, align 8, !tbaa !0
-  %3 = bitcast i64* %2 to void (i8**, i8*, i8**)*
-  %4 = getelementptr inbounds %struct.rust_fn* %recvfn, i64 0, i32 1
-  %5 = load %struct.rust_box** %4, align 8, !tbaa !0
-  %6 = bitcast %struct.rust_box* %5 to i8*
-  tail call void %3(i8** null, i8* %6, i8** %retptr)
+entry:
+  %fn1 = getelementptr inbounds %struct.rust_fn* %recvfn, i64 0, i32 0
+  %0 = load i64** %fn1, align 8, !tbaa !0
+  %1 = bitcast i64* %0 to void (i8**, i8*, i8**)*
+  %env2 = getelementptr inbounds %struct.rust_fn* %recvfn, i64 0, i32 1
+  %2 = load %struct.rust_box** %env2, align 8, !tbaa !0
+  %3 = bitcast %struct.rust_box* %2 to i8*
+  tail call void %1(i8** null, i8* %3, i8** %retptr)
   ret void
 }
 
 define void @rust_intrinsic_get_type_desc(i8** nocapture %retptr, i8* nocapture %env, %struct.type_desc* %ty) nounwind uwtable {
+entry:
   %ty.c = bitcast %struct.type_desc* %ty to i8*
   store i8* %ty.c, i8** %retptr, align 8, !tbaa !0
   ret void
 }
 
-define void @rust_intrinsic_task_sleep(i8** nocapture %retptr, i8* nocapture %env, %struct.rust_task* %task, i64 %time_in_us, i8* %killed) uwtable {
-  tail call void @rust_task_sleep(%struct.rust_task* %task, i64 %time_in_us, i8* %killed)
+define void @rust_intrinsic_task_yield(i8** nocapture %retptr, i8* nocapture %env, %struct.rust_task* %task, i8* %killed) uwtable {
+entry:
+  tail call void @rust_task_yield(%struct.rust_task* %task, i8* %killed)
   ret void
 }
 
-declare void @rust_task_sleep(%struct.rust_task*, i64, i8*)
+declare void @rust_task_yield(%struct.rust_task*, i8*)
 
 !0 = metadata !{metadata !"any pointer", metadata !1}
 !1 = metadata !{metadata !"omnipotent char", metadata !2}
index 1a3e94c10bd1d8e728d0aca814c2bb66fec02fdd..a3d7270e79d0014e22c1f4a366c83b8177c1ea99 100644 (file)
@@ -50,6 +50,9 @@ private:
     void dec_alloc();
     void maybe_poison(void *mem);
 
+    void release_alloc(void *mem);
+    void claim_alloc(void *mem);
+
 public:
     memory_region(rust_srv *srv, bool synchronized);
     memory_region(memory_region *parent);
@@ -58,10 +61,7 @@ public:
     void *realloc(void *mem, size_t size);
     void free(void *mem);
     virtual ~memory_region();
-
-    void release_alloc(void *mem);
-    void claim_alloc(void *mem);
-};
+ };
 
 inline void *operator new(size_t size, memory_region &region,
                           const char *tag) {
index 6542c7237a76ef930b17ceeb7fd94a76f25ce1b6..b5af3942a20c449beade7a3d106b99cf87ec1705 100644 (file)
@@ -1,5 +1,6 @@
 #include "rust_internal.h"
 #include "rust_util.h"
+#include "rust_scheduler.h"
 #include <cstdio>
 
 struct
@@ -75,6 +76,8 @@ command_line_args : public kernel_owned<command_line_args>
 
 int check_claims = 0;
 
+const size_t MAIN_STACK_SIZE = 1024*1024;
+
 extern "C" CDECL int
 rust_start(uintptr_t main_fn, int argc, char **argv, void* crate_map) {
 
@@ -85,25 +88,26 @@ rust_start(uintptr_t main_fn, int argc, char **argv, void* crate_map) {
 
     rust_srv *srv = new rust_srv(env);
     rust_kernel *kernel = new rust_kernel(srv, env->num_sched_threads);
-    rust_task_id root_id = kernel->create_task(NULL, "main");
+    rust_scheduler *sched = kernel->get_default_scheduler();
+    rust_task_id root_id = sched->create_task(NULL, "main", MAIN_STACK_SIZE);
     rust_task *root_task = kernel->get_task_by_id(root_id);
     I(kernel, root_task != NULL);
-    rust_scheduler *sched = root_task->sched;
+    rust_task_thread *thread = root_task->thread;
     command_line_args *args
         = new (kernel, "main command line args")
         command_line_args(root_task, argc, argv);
 
-    DLOG(sched, dom, "startup: %d args in 0x%" PRIxPTR,
+    DLOG(thread, dom, "startup: %d args in 0x%" PRIxPTR,
              args->argc, (uintptr_t)args->args);
     for (int i = 0; i < args->argc; i++) {
-        DLOG(sched, dom, "startup: arg[%d] = '%s'", i, args->argv[i]);
+        DLOG(thread, dom, "startup: arg[%d] = '%s'", i, args->argv[i]);
     }
 
     root_task->start((spawn_fn)main_fn, NULL, args->args);
     root_task->deref();
     root_task = NULL;
 
-    int ret = kernel->start_task_threads();
+    int ret = kernel->start_schedulers();
     delete args;
     delete kernel;
     delete srv;
index 4bf51da214bfcaa64b09e0122be2d89a961caf33..783ca43d8622549146cd47085d59f8f43f2c831a 100644 (file)
@@ -1,9 +1,11 @@
 /* Native builtins. */
 
 #include "rust_internal.h"
-#include "rust_scheduler.h"
+#include "rust_task_thread.h"
 #include "rust_task.h"
 #include "rust_util.h"
+#include "rust_scheduler.h"
+#include "sync/timer.h"
 
 #if !defined(__WIN32__)
 #include <sys/time.h>
@@ -11,7 +13,7 @@
 
 extern "C" CDECL rust_str*
 last_os_error() {
-    rust_task *task = rust_scheduler::get_task();
+    rust_task *task = rust_task_thread::get_task();
 
     LOG(task, task, "last_os_error()");
 
@@ -54,7 +56,7 @@ last_os_error() {
 
 extern "C" CDECL rust_str *
 rust_getcwd() {
-    rust_task *task = rust_scheduler::get_task();
+    rust_task *task = rust_task_thread::get_task();
     LOG(task, task, "rust_getcwd()");
 
     char cbuf[BUF_BYTES];
@@ -90,22 +92,24 @@ refcount(intptr_t *v) {
     return (*v) - 1;
 }
 
-extern "C" CDECL void
-do_gc() {
-    // TODO
-}
-
 extern "C" CDECL void
 unsupervise() {
-    rust_task *task = rust_scheduler::get_task();
+    rust_task *task = rust_task_thread::get_task();
     task->unsupervise();
 }
 
 extern "C" CDECL void
 vec_reserve_shared(type_desc* ty, rust_vec** vp,
                    size_t n_elts) {
-    rust_task *task = rust_scheduler::get_task();
-    reserve_vec(task, vp, n_elts * ty->size);
+    rust_task *task = rust_task_thread::get_task();
+    reserve_vec_exact(task, vp, n_elts * ty->size);
+}
+
+extern "C" CDECL void
+str_reserve_shared(rust_vec** sp,
+                   size_t n_elts) {
+    rust_task *task = rust_task_thread::get_task();
+    reserve_vec_exact(task, sp, n_elts + 1);
 }
 
 /**
@@ -114,7 +118,7 @@ vec_reserve_shared(type_desc* ty, rust_vec** vp,
  */
 extern "C" CDECL rust_vec*
 vec_from_buf_shared(type_desc *ty, void *ptr, size_t count) {
-    rust_task *task = rust_scheduler::get_task();
+    rust_task *task = rust_task_thread::get_task();
     size_t fill = ty->size * count;
     rust_vec* v = (rust_vec*)task->kernel->malloc(fill + sizeof(rust_vec),
                                                     "vec_from_buf");
@@ -125,7 +129,7 @@ vec_from_buf_shared(type_desc *ty, void *ptr, size_t count) {
 
 extern "C" CDECL void
 rust_str_push(rust_vec** sp, uint8_t byte) {
-    rust_task *task = rust_scheduler::get_task();
+    rust_task *task = rust_task_thread::get_task();
     size_t fill = (*sp)->fill;
     reserve_vec(task, sp, fill + 1);
     (*sp)->data[fill-1] = byte;
@@ -135,14 +139,14 @@ rust_str_push(rust_vec** sp, uint8_t byte) {
 
 extern "C" CDECL void *
 rand_new() {
-    rust_task *task = rust_scheduler::get_task();
-    rust_scheduler *sched = task->sched;
+    rust_task *task = rust_task_thread::get_task();
+    rust_task_thread *thread = task->thread;
     randctx *rctx = (randctx *) task->malloc(sizeof(randctx), "randctx");
     if (!rctx) {
         task->fail();
         return NULL;
     }
-    isaac_init(sched, rctx);
+    isaac_init(thread->kernel, rctx);
     return rctx;
 }
 
@@ -153,7 +157,7 @@ rand_next(randctx *rctx) {
 
 extern "C" CDECL void
 rand_free(randctx *rctx) {
-    rust_task *task = rust_scheduler::get_task();
+    rust_task *task = rust_task_thread::get_task();
     task->free(rctx);
 }
 
@@ -162,7 +166,7 @@ rand_free(randctx *rctx) {
 static void
 debug_tydesc_helper(type_desc *t)
 {
-    rust_task *task = rust_scheduler::get_task();
+    rust_task *task = rust_task_thread::get_task();
     LOG(task, stdlib, "  size %" PRIdPTR ", align %" PRIdPTR
         ", first_param 0x%" PRIxPTR,
         t->size, t->align, t->first_param);
@@ -170,14 +174,14 @@ debug_tydesc_helper(type_desc *t)
 
 extern "C" CDECL void
 debug_tydesc(type_desc *t) {
-    rust_task *task = rust_scheduler::get_task();
+    rust_task *task = rust_task_thread::get_task();
     LOG(task, stdlib, "debug_tydesc");
     debug_tydesc_helper(t);
 }
 
 extern "C" CDECL void
 debug_opaque(type_desc *t, uint8_t *front) {
-    rust_task *task = rust_scheduler::get_task();
+    rust_task *task = rust_task_thread::get_task();
     LOG(task, stdlib, "debug_opaque");
     debug_tydesc_helper(t);
     // FIXME may want to actually account for alignment.  `front` may not
@@ -196,7 +200,7 @@ struct rust_box {
 
 extern "C" CDECL void
 debug_box(type_desc *t, rust_box *box) {
-    rust_task *task = rust_scheduler::get_task();
+    rust_task *task = rust_task_thread::get_task();
     LOG(task, stdlib, "debug_box(0x%" PRIxPTR ")", box);
     debug_tydesc_helper(t);
     LOG(task, stdlib, "  refcount %" PRIdPTR,
@@ -213,7 +217,7 @@ struct rust_tag {
 
 extern "C" CDECL void
 debug_tag(type_desc *t, rust_tag *tag) {
-    rust_task *task = rust_scheduler::get_task();
+    rust_task *task = rust_task_thread::get_task();
 
     LOG(task, stdlib, "debug_tag");
     debug_tydesc_helper(t);
@@ -231,7 +235,7 @@ struct rust_obj {
 
 extern "C" CDECL void
 debug_obj(type_desc *t, rust_obj *obj, size_t nmethods, size_t nbytes) {
-    rust_task *task = rust_scheduler::get_task();
+    rust_task *task = rust_task_thread::get_task();
 
     LOG(task, stdlib, "debug_obj with %" PRIdPTR " methods", nmethods);
     debug_tydesc_helper(t);
@@ -253,7 +257,7 @@ struct rust_fn {
 
 extern "C" CDECL void
 debug_fn(type_desc *t, rust_fn *fn) {
-    rust_task *task = rust_scheduler::get_task();
+    rust_task *task = rust_task_thread::get_task();
     LOG(task, stdlib, "debug_fn");
     debug_tydesc_helper(t);
     LOG(task, stdlib, "  thunk at 0x%" PRIxPTR, fn->thunk);
@@ -267,7 +271,7 @@ extern "C" CDECL void *
 debug_ptrcast(type_desc *from_ty,
               type_desc *to_ty,
               void *ptr) {
-    rust_task *task = rust_scheduler::get_task();
+    rust_task *task = rust_task_thread::get_task();
     LOG(task, stdlib, "debug_ptrcast from");
     debug_tydesc_helper(from_ty);
     LOG(task, stdlib, "to");
@@ -277,13 +281,13 @@ debug_ptrcast(type_desc *from_ty,
 
 extern "C" CDECL void *
 debug_get_stk_seg() {
-    rust_task *task = rust_scheduler::get_task();
+    rust_task *task = rust_task_thread::get_task();
     return task->stk;
 }
 
 extern "C" CDECL rust_vec*
 rust_list_files(rust_str *path) {
-    rust_task *task = rust_scheduler::get_task();
+    rust_task *task = rust_task_thread::get_task();
     array_list<rust_str*> strings;
 #if defined(__WIN32__)
     WIN32_FIND_DATA FindFileData;
@@ -350,7 +354,7 @@ rust_ptr_eq(type_desc *t, rust_box *a, rust_box *b) {
 #if defined(__WIN32__)
 extern "C" CDECL void
 get_time(uint32_t *sec, uint32_t *usec) {
-    rust_task *task = rust_scheduler::get_task();
+    rust_task *task = rust_task_thread::get_task();
     SYSTEMTIME systemTime;
     FILETIME fileTime;
     GetSystemTime(&systemTime);
@@ -379,28 +383,16 @@ nano_time(uint64_t *ns) {
     *ns = t.time_ns();
 }
 
-extern "C" CDECL void
-pin_task() {
-    rust_task *task = rust_scheduler::get_task();
-    task->pin();
-}
-
-extern "C" CDECL void
-unpin_task() {
-    rust_task *task = rust_scheduler::get_task();
-    task->unpin();
-}
-
 extern "C" CDECL rust_task_id
 get_task_id() {
-    rust_task *task = rust_scheduler::get_task();
+    rust_task *task = rust_task_thread::get_task();
     return task->user.id;
 }
 
 extern "C" CDECL rust_task_id
 new_task() {
-    rust_task *task = rust_scheduler::get_task();
-    return task->kernel->create_task(task, NULL);
+    rust_task *task = rust_task_thread::get_task();
+    return task->sched->create_task(task, NULL);
 }
 
 extern "C" CDECL void
@@ -412,55 +404,32 @@ drop_task(rust_task *target) {
 
 extern "C" CDECL rust_task *
 get_task_pointer(rust_task_id id) {
-    rust_task *task = rust_scheduler::get_task();
+    rust_task *task = rust_task_thread::get_task();
     return task->kernel->get_task_by_id(id);
 }
 
 extern "C" rust_task *
 rust_get_task() {
-    return rust_scheduler::get_task();
+    return rust_task_thread::get_task();
 }
 
 extern "C" CDECL void
 start_task(rust_task_id id, fn_env_pair *f) {
-    rust_task *task = rust_scheduler::get_task();
+    rust_task *task = rust_task_thread::get_task();
     rust_task *target = task->kernel->get_task_by_id(id);
     target->start(f->f, f->env, NULL);
     target->deref();
 }
 
-extern "C" CDECL void
-migrate_alloc(void *alloc, rust_task_id tid) {
-    rust_task *task = rust_scheduler::get_task();
-    if(!alloc) return;
-    rust_task *target = task->kernel->get_task_by_id(tid);
-    if(target) {
-        const type_desc *tydesc = task->release_alloc(alloc);
-        target->claim_alloc(alloc, tydesc);
-        target->deref();
-    }
-    else {
-        // We couldn't find the target. Maybe we should just free?
-        task->fail();
-    }
-}
-
-// defined in rust_task.cpp
-extern size_t g_custom_min_stack_size;
-extern "C" CDECL void
-set_min_stack(uintptr_t stack_size) {
-    g_custom_min_stack_size = stack_size;
-}
-
 extern "C" CDECL int
 sched_threads() {
-    rust_task *task = rust_scheduler::get_task();
-    return task->kernel->num_threads;
+    rust_task *task = rust_task_thread::get_task();
+    return task->sched->number_of_threads();
 }
 
 extern "C" CDECL rust_port*
 new_port(size_t unit_sz) {
-    rust_task *task = rust_scheduler::get_task();
+    rust_task *task = rust_task_thread::get_task();
     LOG(task, comm, "new_port(task=0x%" PRIxPTR " (%s), unit_sz=%d)",
         (uintptr_t) task, task->name, unit_sz);
     // port starts with refcount == 1
@@ -469,7 +438,7 @@ new_port(size_t unit_sz) {
 
 extern "C" CDECL void
 rust_port_detach(rust_port *port) {
-    rust_task *task = rust_scheduler::get_task();
+    rust_task *task = rust_task_thread::get_task();
     LOG(task, comm, "rust_port_detach(0x%" PRIxPTR ")", (uintptr_t) port);
     port->detach();
     // FIXME: Busy waiting until we're the only ref
@@ -482,9 +451,9 @@ rust_port_detach(rust_port *port) {
 
 extern "C" CDECL void
 del_port(rust_port *port) {
-    rust_task *task = rust_scheduler::get_task();
+    rust_task *task = rust_task_thread::get_task();
     LOG(task, comm, "del_port(0x%" PRIxPTR ")", (uintptr_t) port);
-    A(task->sched, port->ref_count == 1, "Expected port ref_count == 1");
+    A(task->thread, port->ref_count == 1, "Expected port ref_count == 1");
     port->deref();
 }
 
@@ -503,7 +472,7 @@ chan_id_send(type_desc *t, rust_task_id target_task_id,
              rust_port_id target_port_id, void *sptr) {
     // FIXME: make sure this is thread-safe
     bool sent = false;
-    rust_task *task = rust_scheduler::get_task();
+    rust_task *task = rust_task_thread::get_task();
     rust_task *target_task = task->kernel->get_task_by_id(target_task_id);
     if(target_task) {
         rust_port *port = target_task->get_port_by_id(target_port_id);
@@ -521,8 +490,8 @@ chan_id_send(type_desc *t, rust_task_id target_task_id,
 // This is called by an intrinsic on the Rust stack and must run
 // entirely in the red zone. Do not call on the C stack.
 extern "C" CDECL void
-rust_task_sleep(rust_task *task, size_t time_in_us, bool *killed) {
-    task->yield(time_in_us, killed);
+rust_task_yield(rust_task *task, bool *killed) {
+    task->yield(killed);
 }
 
 extern "C" CDECL void
@@ -530,7 +499,7 @@ port_recv(uintptr_t *dptr, rust_port *port,
           uintptr_t *yield, uintptr_t *killed) {
     *yield = false;
     *killed = false;
-    rust_task *task = rust_scheduler::get_task();
+    rust_task *task = rust_task_thread::get_task();
     {
         scoped_lock with(port->lock);
 
@@ -563,7 +532,7 @@ port_recv(uintptr_t *dptr, rust_port *port,
 
 extern "C" CDECL void
 rust_set_exit_status(intptr_t code) {
-    rust_task *task = rust_scheduler::get_task();
+    rust_task *task = rust_task_thread::get_task();
     task->kernel->set_exit_status((int)code);
 }
 
@@ -578,7 +547,7 @@ extern void log_console_off(rust_env *env);
 
 extern "C" CDECL void
 rust_log_console_off() {
-    rust_task *task = rust_scheduler::get_task();
+    rust_task *task = rust_task_thread::get_task();
     log_console_off(task->kernel->env);
 }
 
index 78138434d73c4841be398a298de57379d9060471..03a4bed014ef63c03538e4991feb2c20877d12d5 100644 (file)
@@ -2,7 +2,6 @@
 // time until LLVM's GC infrastructure is more mature.
 
 #include "rust_debug.h"
-#include "rust_gc.h"
 #include "rust_internal.h"
 #include "rust_shape.h"
 #include "rust_task.h"
@@ -25,7 +24,7 @@ namespace cc {
 
 // Internal reference count computation
 
-typedef std::map<void *,uintptr_t> irc_map;
+typedef std::map<rust_opaque_box*,uintptr_t> irc_map;
 
 class irc : public shape::data<irc,shape::ptr> {
     friend class shape::data<irc,shape::ptr>;
@@ -118,13 +117,6 @@ class irc : public shape::data<irc,shape::ptr> {
         }
     }
 
-    void walk_obj2() {
-        dp += sizeof(void *); // skip vtable
-        uint8_t *box_ptr = shape::bump_dp<uint8_t *>(dp);
-        shape::ptr ref_count_dp(box_ptr);
-        maybe_record_irc(ref_count_dp);
-    }
-
     void walk_iface2() {
         walk_box2();
     }
@@ -145,30 +137,32 @@ class irc : public shape::data<irc,shape::ptr> {
 
     void walk_uniq_contents2(irc &sub) { sub.walk(); }
 
-    void walk_box_contents2(irc &sub, shape::ptr &ref_count_dp) {
-        maybe_record_irc(ref_count_dp);
+    void walk_box_contents2(irc &sub, shape::ptr &box_dp) {
+        maybe_record_irc(box_dp);
 
         // Do not traverse the contents of this box; it's in the allocation
         // somewhere, so we're guaranteed to come back to it (if we haven't
         // traversed it already).
     }
 
-    void maybe_record_irc(shape::ptr &ref_count_dp) {
-        if (!ref_count_dp)
+    void maybe_record_irc(shape::ptr &box_dp) {
+        if (!box_dp)
             return;
 
+        rust_opaque_box *box_ptr = (rust_opaque_box *) box_dp;
+
         // Bump the internal reference count of the box.
-        if (ircs.find((void *)ref_count_dp) == ircs.end()) {
+        if (ircs.find(box_ptr) == ircs.end()) {
           LOG(task, gc,
               "setting internal reference count for %p to 1",
-              (void *)ref_count_dp);
-          ircs[(void *)ref_count_dp] = 1;
+              box_ptr);
+          ircs[box_ptr] = 1;
         } else {
-          uintptr_t newcount = ircs[(void *)ref_count_dp] + 1;
+          uintptr_t newcount = ircs[box_ptr] + 1;
           LOG(task, gc,
               "bumping internal reference count for %p to %lu",
-              (void *)ref_count_dp, newcount);
-          ircs[(void *)ref_count_dp] = newcount;
+              box_ptr, newcount);
+          ircs[box_ptr] = newcount;
         }
     }
 
@@ -207,36 +201,25 @@ irc::walk_variant2(shape::tag_info &tinfo, uint32_t variant_id,
 
 void
 irc::compute_ircs(rust_task *task, irc_map &ircs) {
-    std::map<void *,const type_desc *>::iterator
-        begin(task->local_allocs.begin()), end(task->local_allocs.end());
-    while (begin != end) {
-        uint8_t *p = reinterpret_cast<uint8_t *>(begin->first);
-
-        const type_desc *tydesc = begin->second;
-
-        LOG(task, gc, "determining internal ref counts: %p, tydesc=%p", p,
-            tydesc);
-
+    boxed_region *boxed = &task->boxed;
+    for (rust_opaque_box *box = boxed->first_live_alloc();
+         box != NULL;
+         box = box->next) {
+        type_desc *tydesc = box->td;
+        uint8_t *body = (uint8_t*) box_body(box);
+
+        LOG(task, gc, 
+            "determining internal ref counts: "
+            "box=%p tydesc=%p body=%p",
+            box, tydesc, body);
+        
         shape::arena arena;
         shape::type_param *params =
-            shape::type_param::from_tydesc_and_data(tydesc, p, arena);
-
-#if 0
-        shape::print print(task, true, tydesc->shape, params,
-                           tydesc->shape_tables);
-        print.walk();
-
-        shape::log log(task, true, tydesc->shape, params,
-                       tydesc->shape_tables, p + sizeof(uintptr_t),
-                       std::cerr);
-        log.walk();
-#endif
+            shape::type_param::from_tydesc_and_data(tydesc, body, arena);
 
         irc irc(task, true, tydesc->shape, params, tydesc->shape_tables,
-                p + sizeof(uintptr_t), ircs);
+                body, ircs);
         irc.walk();
-
-        ++begin;
     }
 }
 
@@ -244,17 +227,17 @@ irc::compute_ircs(rust_task *task, irc_map &ircs) {
 // Root finding
 
 void
-find_roots(rust_task *task, irc_map &ircs, std::vector<void *> &roots) {
-    std::map<void *,const type_desc *>::iterator
-        begin(task->local_allocs.begin()), end(task->local_allocs.end());
-    while (begin != end) {
-        void *alloc = begin->first;
-        uintptr_t *ref_count_ptr = reinterpret_cast<uintptr_t *>(alloc);
-        uintptr_t ref_count = *ref_count_ptr;
+find_roots(rust_task *task, irc_map &ircs,
+           std::vector<rust_opaque_box *> &roots) {
+    boxed_region *boxed = &task->boxed;
+    for (rust_opaque_box *box = boxed->first_live_alloc();
+         box != NULL;
+         box = box->next) {
+        uintptr_t ref_count = box->ref_count;
 
         uintptr_t irc;
-        if (ircs.find(alloc) != ircs.end())
-            irc = ircs[alloc];
+        if (ircs.find(box) != ircs.end())
+            irc = ircs[box];
         else
             irc = 0;
 
@@ -262,16 +245,14 @@ find_roots(rust_task *task, irc_map &ircs, std::vector<void *> &roots) {
             // This allocation must be a root, because the internal reference
             // count is smaller than the total reference count.
             LOG(task, gc,"root found: %p, irc %lu, ref count %lu",
-                alloc, irc, ref_count);
-            roots.push_back(alloc);
+                box, irc, ref_count);
+            roots.push_back(box);
         } else {
             LOG(task, gc, "nonroot found: %p, irc %lu, ref count %lu",
-                alloc, irc, ref_count);
+                box, irc, ref_count);
             assert(irc == ref_count && "Internal reference count must be "
                    "less than or equal to the total reference count!");
         }
-
-        ++begin;
     }
 }
 
@@ -281,7 +262,7 @@ find_roots(rust_task *task, irc_map &ircs, std::vector<void *> &roots) {
 class mark : public shape::data<mark,shape::ptr> {
     friend class shape::data<mark,shape::ptr>;
 
-    std::set<void *> &marked;
+    std::set<rust_opaque_box *> &marked;
 
     mark(const mark &other, const shape::ptr &in_dp)
     : shape::data<mark,shape::ptr>(other.task, other.align, other.sp,
@@ -319,7 +300,7 @@ class mark : public shape::data<mark,shape::ptr> {
          const shape::type_param *in_params,
          const rust_shape_tables *in_tables,
          uint8_t *in_data,
-         std::set<void *> &in_marked)
+         std::set<rust_opaque_box*> &in_marked)
     : shape::data<mark,shape::ptr>(in_task, in_align, in_sp, in_params,
                                    in_tables, in_data),
       marked(in_marked) {}
@@ -357,7 +338,7 @@ class mark : public shape::data<mark,shape::ptr> {
           case shape::SHAPE_BOX_FN: {
               // Record an irc for the environment box, but don't descend
               // into it since it will be walked via the box's allocation
-              shape::data<mark,shape::ptr>::walk_fn_contents1(dp, false);
+              shape::data<mark,shape::ptr>::walk_fn_contents1();
               break;
           }
           case shape::SHAPE_BARE_FN:        // Does not close over data.
@@ -368,10 +349,6 @@ class mark : public shape::data<mark,shape::ptr> {
         }
     }
 
-    void walk_obj2() {
-        shape::data<mark,shape::ptr>::walk_obj_contents1(dp);
-    }
-
     void walk_res2(const shape::rust_fn *dtor, unsigned n_params,
                   const shape::type_param *params, const uint8_t *end_sp,
                   bool live) {
@@ -392,14 +369,16 @@ class mark : public shape::data<mark,shape::ptr> {
 
     void walk_uniq_contents2(mark &sub) { sub.walk(); }
 
-    void walk_box_contents2(mark &sub, shape::ptr &ref_count_dp) {
-        if (!ref_count_dp)
+    void walk_box_contents2(mark &sub, shape::ptr &box_dp) {
+        if (!box_dp)
             return;
 
-        if (marked.find((void *)ref_count_dp) != marked.end())
+        rust_opaque_box *box_ptr = (rust_opaque_box *) box_dp;
+
+        if (marked.find(box_ptr) != marked.end())
             return; // Skip to avoid chasing cycles.
 
-        marked.insert((void *)ref_count_dp);
+        marked.insert(box_ptr);
         sub.walk();
     }
 
@@ -418,8 +397,9 @@ class mark : public shape::data<mark,shape::ptr> {
     inline void walk_number2() { /* no-op */ }
 
 public:
-    static void do_mark(rust_task *task, const std::vector<void *> &roots,
-                        std::set<void *> &marked);
+    static void do_mark(rust_task *task,
+                        const std::vector<rust_opaque_box *> &roots,
+                        std::set<rust_opaque_box*> &marked);
 };
 
 void
@@ -438,35 +418,28 @@ mark::walk_variant2(shape::tag_info &tinfo, uint32_t variant_id,
 }
 
 void
-mark::do_mark(rust_task *task, const std::vector<void *> &roots,
-              std::set<void *> &marked) {
-    std::vector<void *>::const_iterator begin(roots.begin()),
-                                        end(roots.end());
+mark::do_mark(rust_task *task,
+              const std::vector<rust_opaque_box *> &roots,
+              std::set<rust_opaque_box *> &marked) {
+    std::vector<rust_opaque_box *>::const_iterator 
+      begin(roots.begin()),
+      end(roots.end());
     while (begin != end) {
-        void *alloc = *begin;
-        if (marked.find(alloc) == marked.end()) {
-            marked.insert(alloc);
+        rust_opaque_box *box = *begin;
+        if (marked.find(box) == marked.end()) {
+            marked.insert(box);
 
-            const type_desc *tydesc = task->local_allocs[alloc];
+            const type_desc *tydesc = box->td;
 
-            LOG(task, gc, "marking: %p, tydesc=%p", alloc, tydesc);
+            LOG(task, gc, "marking: %p, tydesc=%p", box, tydesc);
 
-            uint8_t *p = reinterpret_cast<uint8_t *>(alloc);
+            uint8_t *p = (uint8_t*) box_body(box);
             shape::arena arena;
             shape::type_param *params =
                 shape::type_param::from_tydesc_and_data(tydesc, p, arena);
 
-#if 0
-            // We skip over the reference count here.
-            shape::log log(task, true, tydesc->shape, params,
-                           tydesc->shape_tables, p + sizeof(uintptr_t),
-                           std::cerr);
-            log.walk();
-#endif
-
-            // We skip over the reference count here.
             mark mark(task, true, tydesc->shape, params, tydesc->shape_tables,
-                      p + sizeof(uintptr_t), marked);
+                      p, marked);
             mark.walk();
         }
 
@@ -552,13 +525,9 @@ class sweep : public shape::data<sweep,shape::ptr> {
               fn_env_pair pair = *(fn_env_pair*)dp;
 
               // free closed over data:
-              shape::data<sweep,shape::ptr>::walk_fn_contents1(dp, true);
+              shape::data<sweep,shape::ptr>::walk_fn_contents1();
 
               // now free the embedded type descr:
-              //
-              // see comment in walk_fn_contents1() concerning null_td
-              // to understand why this does not occur during the normal
-              // walk.
               upcall_s_free_shared_type_desc((type_desc*)pair.env->td);
 
               // now free the ptr:
@@ -610,7 +579,7 @@ class sweep : public shape::data<sweep,shape::ptr> {
 
     void walk_uniq_contents2(sweep &sub) { sub.walk(); }
 
-    void walk_box_contents2(sweep &sub, shape::ptr &ref_count_dp) {
+    void walk_box_contents2(sweep &sub, shape::ptr &box_dp) {
         return;
     }
 
@@ -637,50 +606,50 @@ class sweep : public shape::data<sweep,shape::ptr> {
     inline void walk_number2() { /* no-op */ }
 
 public:
-    static void do_sweep(rust_task *task, const std::set<void *> &marked);
+    static void do_sweep(rust_task *task,
+                         const std::set<rust_opaque_box*> &marked);
 };
 
 void
-sweep::do_sweep(rust_task *task, const std::set<void *> &marked) {
-    std::map<void *,const type_desc *>::iterator
-        begin(task->local_allocs.begin()), end(task->local_allocs.end());
-    while (begin != end) {
-        void *alloc = begin->first;
-
-        if (marked.find(alloc) == marked.end()) {
-            LOG(task, gc, "object is part of a cycle: %p", alloc);
-
-            const type_desc *tydesc = begin->second;
-            uint8_t *p = reinterpret_cast<uint8_t *>(alloc);
+sweep::do_sweep(rust_task *task,
+                const std::set<rust_opaque_box*> &marked) {
+    boxed_region *boxed = &task->boxed;
+    rust_opaque_box *box = boxed->first_live_alloc();
+    while (box != NULL) {
+        // save next ptr as we may be freeing box
+        rust_opaque_box *box_next = box->next;
+        if (marked.find(box) == marked.end()) {
+            LOG(task, gc, "object is part of a cycle: %p", box);
+
+            const type_desc *tydesc = box->td;
+            uint8_t *p = (uint8_t*) box_body(box);
             shape::arena arena;
             shape::type_param *params =
                 shape::type_param::from_tydesc_and_data(tydesc, p, arena);
 
             sweep sweep(task, true, tydesc->shape,
                         params, tydesc->shape_tables,
-                        p + sizeof(uintptr_t));
+                        p);
             sweep.walk();
 
-            // FIXME: Run the destructor, *if* it's a resource.
-            task->free(alloc);
+            boxed->free(box);
         }
-        ++begin;
+        box = box_next;
     }
 }
 
 
 void
 do_cc(rust_task *task) {
-    LOG(task, gc, "cc; n allocs = %lu",
-        (long unsigned int)task->local_allocs.size());
+    LOG(task, gc, "cc");
 
     irc_map ircs;
     irc::compute_ircs(task, ircs);
 
-    std::vector<void *> roots;
+    std::vector<rust_opaque_box*> roots;
     find_roots(task, ircs, roots);
 
-    std::set<void *> marked;
+    std::set<rust_opaque_box*> marked;
     mark::do_mark(task, roots, marked);
 
     sweep::do_sweep(task, marked);
index 17e5f34e5343cd04cfe0619191bd41f0139e610d..0294069051bddcd99150393a9d73e2af43634677 100644 (file)
@@ -9,20 +9,20 @@ rust_crate_cache::get_type_desc(size_t size,
                                 type_desc const **descs,
                                 uintptr_t n_obj_params)
 {
-    I(sched, n_descs > 1);
+    I(thread, n_descs > 1);
     type_desc *td = NULL;
     size_t keysz = n_descs * sizeof(type_desc*);
     HASH_FIND(hh, this->type_descs, descs, keysz, td);
     if (td) {
-        DLOG(sched, cache, "rust_crate_cache::get_type_desc hit");
+        DLOG(thread, cache, "rust_crate_cache::get_type_desc hit");
 
         // FIXME: This is a gross hack.
         td->n_obj_params = std::max(td->n_obj_params, n_obj_params);
 
         return td;
     }
-    DLOG(sched, cache, "rust_crate_cache::get_type_desc miss");
-    td = (type_desc*) sched->kernel->malloc(sizeof(type_desc) + keysz,
+    DLOG(thread, cache, "rust_crate_cache::get_type_desc miss");
+    td = (type_desc*) thread->kernel->malloc(sizeof(type_desc) + keysz,
                                             "crate cache typedesc");
     if (!td)
         return NULL;
@@ -34,7 +34,7 @@ rust_crate_cache::get_type_desc(size_t size,
     td->size = size;
     td->align = align;
     for (size_t i = 0; i < n_descs; ++i) {
-        DLOG(sched, cache,
+        DLOG(thread, cache,
                  "rust_crate_cache::descs[%" PRIdPTR "] = 0x%" PRIxPTR,
                  i, descs[i]);
         td->descs[i] = descs[i];
@@ -52,7 +52,7 @@ rust_crate_cache::get_dict(size_t n_fields, void** dict) {
     HASH_FIND(hh, this->dicts, dict, dictsz, found);
     if (found) return &(found->fields[0]);
     found = (rust_hashable_dict*)
-        sched->kernel->malloc(sizeof(UT_hash_handle) + dictsz,
+        thread->kernel->malloc(sizeof(UT_hash_handle) + dictsz,
                               "crate cache dict");
     if (!found) return NULL;
     void** retptr = &(found->fields[0]);
@@ -61,28 +61,28 @@ rust_crate_cache::get_dict(size_t n_fields, void** dict) {
     return retptr;
 }
 
-rust_crate_cache::rust_crate_cache(rust_scheduler *sched)
+rust_crate_cache::rust_crate_cache(rust_task_thread *thread)
     : type_descs(NULL),
       dicts(NULL),
-      sched(sched),
+      thread(thread),
       idx(0)
 {
 }
 
 void
 rust_crate_cache::flush() {
-    DLOG(sched, cache, "rust_crate_cache::flush()");
+    DLOG(thread, cache, "rust_crate_cache::flush()");
 
     while (type_descs) {
         type_desc *d = type_descs;
         HASH_DEL(type_descs, d);
-        DLOG(sched, mem, "rust_crate_cache::flush() tydesc %" PRIxPTR, d);
-        sched->kernel->free(d);
+        DLOG(thread, mem, "rust_crate_cache::flush() tydesc %" PRIxPTR, d);
+        thread->kernel->free(d);
     }
     while (dicts) {
         rust_hashable_dict *d = dicts;
         HASH_DEL(dicts, d);
-        sched->kernel->free(d);
+        thread->kernel->free(d);
     }
 }
 
diff --git a/src/rt/rust_gc.cpp b/src/rt/rust_gc.cpp
deleted file mode 100644 (file)
index 26e4885..0000000
+++ /dev/null
@@ -1,164 +0,0 @@
-// Rust garbage collection.
-
-#include <algorithm>
-#include <iostream>
-#include <utility>
-#include <vector>
-#include <stdint.h>
-
-#include "rust_abi.h"
-#include "rust_debug.h"
-#include "rust_gc.h"
-#include "rust_internal.h"
-#include "rust_shape.h"
-
-#ifdef __WIN32__
-#include <windows.h>
-#else
-#include <dlfcn.h>
-#endif
-
-using namespace stack_walk;
-
-namespace gc {
-
-weak_symbol<const uintptr_t> safe_point_data("rust_gc_safe_points");
-
-struct root_info {
-    intptr_t frame_offset;
-    uintptr_t dynamic;  // 0 = static, 1 = dynamic
-    const type_desc *tydesc;
-};
-
-struct root {
-    const type_desc *tydesc;
-    uint8_t *data;
-
-    root(const root_info &info, const frame &frame)
-    : tydesc(info.tydesc),
-      data((uint8_t *)frame.bp + info.frame_offset) {}
-};
-
-struct safe_point {
-    uintptr_t n_roots;
-    root_info roots[0];
-};
-
-struct safe_point_index_entry {
-    void (*ra)();                   // The return address.
-    const struct safe_point *safe_point;   // The safe point.
-
-    struct cmp {
-        bool operator()(const safe_point_index_entry &entry, void (*ra)())
-                const {
-            return entry.ra < ra;
-        }
-        bool operator()(void (*ra)(), const safe_point_index_entry &entry)
-                const {
-            return ra < entry.ra;
-        }
-    };
-};
-
-class safe_point_map {
-    uintptr_t n_safe_points;
-    const safe_point_index_entry *index;
-    const safe_point *safe_points;
-
-public:
-    safe_point_map() {
-        const uintptr_t *data = *safe_point_data;
-        n_safe_points = *data++;
-        index = (const safe_point_index_entry *)data;
-        data += n_safe_points * 2;
-        safe_points = (const safe_point *)data;
-    }
-
-    const safe_point *get_safe_point(void (*addr)());
-};
-
-class gc {
-private:
-    rust_task *task;
-
-    void mark(std::vector<root> &roots);
-    void sweep();
-
-public:
-    gc(rust_task *in_task) : task(in_task) {}
-    void run();
-};
-
-const safe_point *
-safe_point_map::get_safe_point(void (*addr)()) {
-    safe_point_index_entry::cmp cmp;
-    const safe_point_index_entry *entry =
-        std::lower_bound(index, index + n_safe_points, addr, cmp);
-    return (entry && entry->ra == addr) ? entry->safe_point : NULL;
-}
-
-void
-gc::mark(std::vector<root> &roots) {
-    std::vector<root>::iterator ri = roots.begin(), rend = roots.end();
-    while (ri < rend) {
-        DPRINT("root: %p\n", ri->data);
-
-        shape::arena arena;
-        shape::type_param *params =
-            shape::type_param::from_tydesc_and_data(ri->tydesc, ri->data,
-                                                    arena);
-        shape::log log(task, true, ri->tydesc->shape, params,
-                       ri->tydesc->shape_tables, ri->data, std::cerr);
-        log.walk();
-        DPRINT("\n");
-
-        ++ri;
-    }
-    // TODO
-}
-
-void
-gc::sweep() {
-    // TODO
-}
-
-void
-gc::run() {
-    safe_point_map map;
-
-    // Find roots.
-    std::vector<root> roots;
-    std::vector<frame> call_stack = backtrace();
-    for (unsigned i = 0; i < call_stack.size(); i++) {
-        frame f = call_stack[i];
-        const safe_point *sp = map.get_safe_point(f.ra);
-        if (!sp)
-            continue;
-
-        DPRINT("%u: ra %p, ebp %p\n", i, call_stack[i].ra, call_stack[i].bp);
-        for (unsigned j = 0; j < sp->n_roots; j++) {
-            root r(sp->roots[j], f);
-            roots.push_back(r);
-        }
-    }
-
-    // Mark and sweep.
-    mark(roots);
-    sweep();
-}
-
-void
-maybe_gc(rust_task *task) {
-    if (*safe_point_data == NULL)
-        return;
-
-    static debug::flag zeal("RUST_GC_ZEAL");
-
-    if (*zeal) {
-        gc gc(task);
-        gc.run();
-    }
-}
-
-}
-
diff --git a/src/rt/rust_gc.h b/src/rt/rust_gc.h
deleted file mode 100644 (file)
index 45349dc..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// Rust garbage collection.
-
-struct rust_task;
-
-namespace gc {
-
-void maybe_gc(rust_task *task);
-
-}
-
index aa62c22fc8fe08f636d216d952882e664a641835..8536681ecad095d1c16d0ac73242da87f76c3f0a 100644 (file)
@@ -47,11 +47,10 @@ extern "C" {
 #include "util/synchronized_indexed_list.h"
 #include "util/hash_map.h"
 #include "sync/sync.h"
-#include "sync/timer.h"
 #include "sync/lock_and_signal.h"
 #include "sync/lock_free_queue.h"
 
-struct rust_scheduler;
+struct rust_task_thread;
 struct rust_task;
 class rust_log;
 class rust_port;
@@ -218,28 +217,7 @@ public:
 #include "rust_srv.h"
 #include "rust_log.h"
 #include "rust_kernel.h"
-#include "rust_scheduler.h"
-
-struct rust_timer {
-    // FIXME: This will probably eventually need replacement
-    // with something more sophisticated and integrated with
-    // an IO event-handling library, when we have such a thing.
-    // For now it's just the most basic "thread that can interrupt
-    // its associated domain-thread" device, so that we have
-    // *some* form of task-preemption.
-    rust_scheduler *sched;
-    uintptr_t exit_flag;
-
-#if defined(__WIN32__)
-    HANDLE thread;
-#else
-    pthread_attr_t attr;
-    pthread_t thread;
-#endif
-
-    rust_timer(rust_scheduler *sched);
-    ~rust_timer();
-};
+#include "rust_task_thread.h"
 
 typedef void CDECL (glue_fn)(void *, void *,
                              const type_desc **, void *);
@@ -252,29 +230,36 @@ struct rust_shape_tables {
     uint8_t *resources;
 };
 
-struct rust_opaque_closure;
+typedef unsigned long ref_cnt_t;
+
+// Corresponds to the boxed data in the @ region.  The body follows the
+// header; you can obtain a ptr via box_body() below.
+struct rust_opaque_box {
+    ref_cnt_t ref_count;
+    type_desc *td;
+    rust_opaque_box *prev;
+    rust_opaque_box *next;
+};
 
 // The type of functions that we spawn, which fall into two categories:
 // - 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_closure*, void *);
+typedef void (*CDECL spawn_fn)(void*, rust_opaque_box*, void *);
 
 // corresponds to the layout of a fn(), fn@(), fn~() etc
 struct fn_env_pair {
     spawn_fn f;
-    rust_opaque_closure *env;
+    rust_opaque_box *env;
 };
 
-// corresponds the closures generated in trans_closure.rs
-struct rust_opaque_closure {
-    intptr_t ref_count;
-    const type_desc *td;
-    // The size/types of these will vary per closure, so they
-    // cannot be statically expressed.  See trans_closure.rs:
-    const type_desc *captured_tds[0];
-    // struct bound_data;
-};
+static inline void *box_body(rust_opaque_box *box) {
+    // Here we take advantage of the fact that the size of a box in 32
+    // (resp. 64) bit is 16 (resp. 32) bytes, and thus always 16-byte aligned.
+    // If this were to change, we would have to update the method
+    // rustc::middle::trans::base::opaque_box_body() as well.
+    return (void*)(box + 1);
+}
 
 struct type_desc {
     // First part of type_desc is known to compiler.
@@ -308,10 +293,6 @@ extern "C" type_desc *rust_clone_type_desc(type_desc*);
 #include "rust_port.h"
 #include "memory.h"
 
-#include "test/rust_test_harness.h"
-#include "test/rust_test_util.h"
-#include "test/rust_test_runtime.h"
-
 //
 // Local Variables:
 // mode: C++
index a7e4ee2e4506c095164e3767d169ac876cea97d8..f8e7e41971e627b0dad91a8c38d38cdd933b5b26 100644 (file)
@@ -1,5 +1,6 @@
 #include "rust_internal.h"
 #include "rust_util.h"
+#include "rust_scheduler.h"
 
 #define KLOG_(...)                              \
     KLOG(this, kern, __VA_ARGS__)
@@ -10,68 +11,13 @@ rust_kernel::rust_kernel(rust_srv *srv, size_t num_threads) :
     _region(srv, true),
     _log(srv, NULL),
     srv(srv),
-    max_id(0),
-    rval(0),
-    num_threads(num_threads),
     live_tasks(0),
+    max_task_id(0),
+    rval(0),
     env(srv->env)
 {
-    isaac_init(this, &rctx);
-    create_schedulers();
-}
-
-rust_scheduler *
-rust_kernel::create_scheduler(int id) {
-    _kernel_lock.lock();
-    rust_srv *srv = this->srv->clone();
-    rust_scheduler *sched =
-        new (this, "rust_scheduler") rust_scheduler(this, srv, id);
-    KLOG_("created scheduler: " PTR ", id: %d, index: %d",
-          sched, id, sched->list_index);
-    _kernel_lock.signal_all();
-    _kernel_lock.unlock();
-    return sched;
-}
-
-void
-rust_kernel::destroy_scheduler(rust_scheduler *sched) {
-    _kernel_lock.lock();
-    KLOG_("deleting scheduler: " PTR ", name: %s, index: %d",
-        sched, sched->name, sched->list_index);
-    rust_srv *srv = sched->srv;
-    delete sched;
-    delete srv;
-    _kernel_lock.signal_all();
-    _kernel_lock.unlock();
-}
-
-void rust_kernel::create_schedulers() {
-    KLOG_("Using %d scheduler threads.", num_threads);
-
-    for(size_t i = 0; i < num_threads; ++i) {
-        threads.push(create_scheduler(i));
-    }
-}
-
-void rust_kernel::destroy_schedulers() {
-    for(size_t i = 0; i < num_threads; ++i) {
-        destroy_scheduler(threads[i]);
-    }
-}
-
-void
-rust_kernel::log_all_scheduler_state() {
-    for(size_t i = 0; i < num_threads; ++i) {
-        threads[i]->log_state();
-    }
-}
-
-/**
- * Checks for simple deadlocks.
- */
-bool
-rust_kernel::is_deadlocked() {
-    return false;
+    sched = new (this, "rust_scheduler")
+        rust_scheduler(this, srv, num_threads);
 }
 
 void
@@ -96,7 +42,7 @@ rust_kernel::fatal(char const *fmt, ...) {
 }
 
 rust_kernel::~rust_kernel() {
-    destroy_schedulers();
+    delete sched;
 }
 
 void *
@@ -113,28 +59,17 @@ void rust_kernel::free(void *mem) {
     _region.free(mem);
 }
 
-void
-rust_kernel::signal_kernel_lock() {
-    _kernel_lock.lock();
-    _kernel_lock.signal_all();
-    _kernel_lock.unlock();
-}
-
-int rust_kernel::start_task_threads()
+int rust_kernel::start_schedulers()
 {
-    for(size_t i = 0; i < num_threads; ++i) {
-        rust_scheduler *thread = threads[i];
-        thread->start();
-    }
-
-    for(size_t i = 0; i < num_threads; ++i) {
-        rust_scheduler *thread = threads[i];
-        thread->join();
-    }
-
+    sched->start_task_threads();
     return rval;
 }
 
+rust_scheduler *
+rust_kernel::get_default_scheduler() {
+    return sched;
+}
+
 void
 rust_kernel::fail() {
     // FIXME: On windows we're getting "Application has requested the
@@ -144,25 +79,43 @@ rust_kernel::fail() {
 #if defined(__WIN32__)
     exit(rval);
 #endif
-    for(size_t i = 0; i < num_threads; ++i) {
-        rust_scheduler *thread = threads[i];
-        thread->kill_all_tasks();
+    sched->kill_all_tasks();
+}
+
+void
+rust_kernel::register_task(rust_task *task) {
+    uintptr_t new_live_tasks;
+    {
+        scoped_lock with(task_lock);
+        task->user.id = max_task_id++;
+        task_table.put(task->user.id, task);
+        new_live_tasks = ++live_tasks;
     }
+    K(srv, task->user.id != INTPTR_MAX, "Hit the maximum task id");
+    KLOG_("Registered task %" PRIdPTR, task->user.id);
+    KLOG_("Total outstanding tasks: %d", new_live_tasks);
 }
 
-rust_task_id
-rust_kernel::create_task(rust_task *spawner, const char *name) {
-    scoped_lock with(_kernel_lock);
-    rust_scheduler *thread = threads[isaac_rand(&rctx) % num_threads];
-    rust_task *t = thread->create_task(spawner, name);
-    t->user.id = max_id++;
-    task_table.put(t->user.id, t);
-    return t->user.id;
+void
+rust_kernel::release_task_id(rust_task_id id) {
+    KLOG_("Releasing task %" PRIdPTR, id);
+    uintptr_t new_live_tasks;
+    {
+        scoped_lock with(task_lock);
+        task_table.remove(id);
+        new_live_tasks = --live_tasks;
+    }
+    KLOG_("Total outstanding tasks: %d", new_live_tasks);
+    if (new_live_tasks == 0) {
+        // There are no more tasks and there never will be.
+        // Tell all the schedulers to exit.
+        sched->exit();
+    }
 }
 
 rust_task *
 rust_kernel::get_task_by_id(rust_task_id id) {
-    scoped_lock with(_kernel_lock);
+    scoped_lock with(task_lock);
     rust_task *task = NULL;
     // get leaves task unchanged if not found.
     task_table.get(id, &task);
@@ -180,18 +133,6 @@ rust_kernel::get_task_by_id(rust_task_id id) {
     return task;
 }
 
-void
-rust_kernel::release_task_id(rust_task_id id) {
-    scoped_lock with(_kernel_lock);
-    task_table.remove(id);
-}
-
-void rust_kernel::wakeup_schedulers() {
-    for(size_t i = 0; i < num_threads; ++i) {
-        threads[i]->lock.signal_all();
-    }
-}
-
 #ifdef __WIN32__
 void
 rust_kernel::win32_require(LPCTSTR fn, BOOL ok) {
@@ -213,7 +154,7 @@ rust_kernel::win32_require(LPCTSTR fn, BOOL ok) {
 
 void
 rust_kernel::set_exit_status(int code) {
-    scoped_lock with(_kernel_lock);
+    scoped_lock with(rval_lock);
     // If we've already failed then that's the code we're going to use
     if (rval != PROC_FAIL_CODE) {
         rval = code;
index f60987acae5597596d319e3056de718fc2418c52..047cd73bf0389692bb9ae6e641c616fb1eb78141 100644 (file)
@@ -5,6 +5,7 @@
 #include "memory_region.h"
 #include "rust_log.h"
 
+struct rust_task_thread;
 struct rust_scheduler;
 
 /**
@@ -19,40 +20,30 @@ class rust_kernel {
 public:
     rust_srv *srv;
 private:
-    lock_and_signal _kernel_lock;
-
-    array_list<rust_scheduler *> threads;
-
-    randctx rctx;
-
-    rust_scheduler *create_scheduler(int id);
-    void destroy_scheduler(rust_scheduler *sched);
-
-    void create_schedulers();
-    void destroy_schedulers();
-
-    rust_task_id max_id;
+    rust_scheduler *sched;
+
+    // Protects live_tasks, max_task_id and task_table
+    lock_and_signal task_lock;
+    // Tracks the number of tasks that are being managed by
+    // schedulers. When this hits 0 we will tell all schedulers
+    // to exit.
+    uintptr_t live_tasks;
+    // The next task id
+    rust_task_id max_task_id;
     hash_map<rust_task_id, rust_task *> task_table;
 
+    lock_and_signal rval_lock;
     int rval;
 
 public:
-    const size_t num_threads;
 
-    volatile int live_tasks;
     struct rust_env *env;
 
     rust_kernel(rust_srv *srv, size_t num_threads);
+    ~rust_kernel();
 
-    bool is_deadlocked();
-
-    void signal_kernel_lock();
-    void wakeup_schedulers();
-
-    void log_all_scheduler_state();
     void log(uint32_t level, char const *fmt, ...);
     void fatal(char const *fmt, ...);
-    virtual ~rust_kernel();
 
     void *malloc(size_t size, const char *tag);
     void *realloc(void *mem, size_t size);
@@ -60,15 +51,17 @@ public:
 
     void fail();
 
-    int start_task_threads();
+    int start_schedulers();
+    rust_scheduler* get_default_scheduler();
 
 #ifdef __WIN32__
     void win32_require(LPCTSTR fn, BOOL ok);
 #endif
 
-    rust_task_id create_task(rust_task *spawner, const char *name);
+    void register_task(rust_task *task);
     rust_task *get_task_by_id(rust_task_id id);
     void release_task_id(rust_task_id tid);
+
     void set_exit_status(int code);
 };
 
index 61b1fe9aaa0afc18ec100fa827c053b9bc7eeaf1..729ca2462e885ab095b85d40f884c74e9dae847d 100644 (file)
@@ -40,9 +40,9 @@ log_console_off(rust_env *env) {
     }
 }
 
-rust_log::rust_log(rust_srv *srv, rust_scheduler *sched) :
+rust_log::rust_log(rust_srv *srv, rust_task_thread *thread) :
     _srv(srv),
-    _sched(sched) {
+    _thread(thread) {
 }
 
 rust_log::~rust_log() {
@@ -118,12 +118,12 @@ rust_log::trace_ln(rust_task *task, uint32_t level, char *message) {
 #endif
 
     char prefix[BUF_BYTES] = "";
-    if (_sched && _sched->name) {
+    if (_thread && _thread->name) {
         append_string(prefix, "%04" PRIxPTR ":%.10s:",
-                      thread_id, _sched->name);
+                      thread_id, _thread->name);
     } else {
         append_string(prefix, "%04" PRIxPTR ":0x%08" PRIxPTR ":",
-                      thread_id, (uintptr_t) _sched);
+                      thread_id, (uintptr_t) _thread);
     }
     if (task) {
         if (task->name) {
index d086a5e1f3234627cca08b126f851d0016e1a3f1..8c5e87cf4927dd63b80beb7db4cf389755333fda 100644 (file)
@@ -8,18 +8,18 @@ const uint32_t log_info = 2;
 const uint32_t log_debug = 3;
 
 #define LOG(task, field, ...)                                   \
-    DLOG_LVL(log_debug, task, task->sched, field, __VA_ARGS__)
+    DLOG_LVL(log_debug, task, task->thread, field, __VA_ARGS__)
 #define LOG_ERR(task, field, ...)                               \
-    DLOG_LVL(log_err, task, task->sched, field, __VA_ARGS__)
-#define DLOG(sched, field, ...)                                   \
-    DLOG_LVL(log_debug, NULL, sched, field, __VA_ARGS__)
-#define DLOG_ERR(sched, field, ...)                               \
-    DLOG_LVL(log_err, NULL, sched, field, __VA_ARGS__)
-#define LOGPTR(sched, msg, ptrval)                                \
-    DLOG_LVL(log_debug, NULL, sched, mem, "%s 0x%" PRIxPTR, msg, ptrval)
-#define DLOG_LVL(lvl, task, sched, field, ...)                    \
+    DLOG_LVL(log_err, task, task->thread, field, __VA_ARGS__)
+#define DLOG(thread, field, ...)                                   \
+    DLOG_LVL(log_debug, NULL, thread, field, __VA_ARGS__)
+#define DLOG_ERR(thread, field, ...)                               \
+    DLOG_LVL(log_err, NULL, thread, field, __VA_ARGS__)
+#define LOGPTR(thread, msg, ptrval)                                \
+    DLOG_LVL(log_debug, NULL, thread, mem, "%s 0x%" PRIxPTR, msg, ptrval)
+#define DLOG_LVL(lvl, task, thread, field, ...)                    \
     do {                                                        \
-        rust_scheduler* _d_ = sched;                            \
+        rust_task_thread* _d_ = thread;                            \
         if (log_rt_##field >= lvl && _d_->log_lvl >= lvl) {     \
             _d_->log(task, lvl, __VA_ARGS__);                   \
         }                                                       \
@@ -34,13 +34,13 @@ const uint32_t log_debug = 3;
         }                                                     \
     } while (0)
 
-struct rust_scheduler;
+struct rust_task_thread;
 struct rust_task;
 
 class rust_log {
 
 public:
-    rust_log(rust_srv *srv, rust_scheduler *sched);
+    rust_log(rust_srv *srv, rust_task_thread *thread);
     virtual ~rust_log();
 
     void trace_ln(rust_task *task, uint32_t level, char *message);
@@ -49,7 +49,7 @@ public:
 
 private:
     rust_srv *_srv;
-    rust_scheduler *_sched;
+    rust_task_thread *_thread;
     bool _use_labels;
     void trace_ln(rust_task *task, char *message);
 };
index 30d38369abf85150f684c0672fa834dea1e6d753..a917c12e151a32ff400ca66dcf6cfbaeabbbaade 100644 (file)
@@ -21,7 +21,7 @@ rust_port::~rust_port() {
 }
 
 void rust_port::detach() {
-    I(task->sched, !task->lock.lock_held_by_current_thread());
+    I(task->thread, !task->lock.lock_held_by_current_thread());
     scoped_lock with(task->lock);
     {
         task->release_port(id);
@@ -29,7 +29,7 @@ void rust_port::detach() {
 }
 
 void rust_port::send(void *sptr) {
-    I(task->sched, !lock.lock_held_by_current_thread());
+    I(task->thread, !lock.lock_held_by_current_thread());
     scoped_lock with(lock);
 
     buffer.enqueue(sptr);
@@ -46,7 +46,7 @@ void rust_port::send(void *sptr) {
 }
 
 bool rust_port::receive(void *dptr) {
-    I(task->sched, lock.lock_held_by_current_thread());
+    I(task->thread, lock.lock_held_by_current_thread());
     if (buffer.is_empty() == false) {
         buffer.dequeue(dptr);
         LOG(task, comm, "<=== read data ===");
@@ -56,7 +56,7 @@ bool rust_port::receive(void *dptr) {
 }
 
 size_t rust_port::size() {
-    I(task->sched, !lock.lock_held_by_current_thread());
+    I(task->thread, !lock.lock_held_by_current_thread());
     scoped_lock with(lock);
     return buffer.size();
 }
index 0b4e35910acda10a40b9b0c8c74d9a85df5cc5fc..3e306cc418d4f48ba8b811ce6062213ab09d831f 100644 (file)
-
-#include <stdarg.h>
-#include <cassert>
-#include <pthread.h>
-#include "rust_internal.h"
+#include "rust_scheduler.h"
 #include "rust_util.h"
-#include "globals.h"
-
-#ifndef _WIN32
-pthread_key_t rust_scheduler::task_key;
-#else
-DWORD rust_scheduler::task_key;
-#endif
-
-bool rust_scheduler::tls_initialized = false;
 
 rust_scheduler::rust_scheduler(rust_kernel *kernel,
-                               rust_srv *srv,
-                               int id) :
-    ref_count(1),
-    interrupt_flag(0),
-    _log(srv, this),
-    log_lvl(log_debug),
-    srv(srv),
-    // TODO: calculate a per scheduler name.
-    name("main"),
-    newborn_tasks(this, "newborn"),
-    running_tasks(this, "running"),
-    blocked_tasks(this, "blocked"),
-    dead_tasks(this, "dead"),
-    cache(this),
+                              rust_srv *srv,
+                              size_t num_threads) :
     kernel(kernel),
-    id(id),
-    min_stack_size(kernel->env->min_stack_size),
-    env(kernel->env)
+    srv(srv),
+    env(srv->env),
+    num_threads(num_threads)
 {
-    LOGPTR(this, "new dom", (uintptr_t)this);
-    isaac_init(this, &rctx);
-#ifndef __WIN32__
-    pthread_attr_init(&attr);
-    pthread_attr_setstacksize(&attr, 1024 * 1024);
-    pthread_attr_setdetachstate(&attr, true);
-#endif
-
-    if (!tls_initialized)
-        init_tls();
+    isaac_init(kernel, &rctx);
+    create_task_threads();
 }
 
 rust_scheduler::~rust_scheduler() {
-    DLOG(this, dom, "~rust_scheduler %s @0x%" PRIxPTR, name, (uintptr_t)this);
-
-    newborn_tasks.delete_all();
-    running_tasks.delete_all();
-    blocked_tasks.delete_all();
-    dead_tasks.delete_all();
-#ifndef __WIN32__
-    pthread_attr_destroy(&attr);
-#endif
-}
-
-void
-rust_scheduler::activate(rust_task *task) {
-    task->ctx.next = &c_context;
-    DLOG(this, task, "descheduling...");
-    lock.unlock();
-    task->ctx.swap(c_context);
-    lock.lock();
-    DLOG(this, task, "task has returned");
+    destroy_task_threads();
 }
 
-void
-rust_scheduler::log(rust_task* task, uint32_t level, char const *fmt, ...) {
-    char buf[BUF_BYTES];
-    va_list args;
-    va_start(args, fmt);
-    vsnprintf(buf, sizeof(buf), fmt, args);
-    _log.trace_ln(task, level, buf);
-    va_end(args);
+rust_task_thread *
+rust_scheduler::create_task_thread(int id) {
+    rust_srv *srv = this->srv->clone();
+    rust_task_thread *thread =
+        new (kernel, "rust_task_thread") rust_task_thread(this, srv, id);
+    KLOG(kernel, kern, "created task thread: " PTR ", id: %d, index: %d",
+          thread, id, thread->list_index);
+    return thread;
 }
 
 void
-rust_scheduler::fail() {
-    log(NULL, log_err, "domain %s @0x%" PRIxPTR " root task failed",
-        name, this);
-    kernel->fail();
+rust_scheduler::destroy_task_thread(rust_task_thread *thread) {
+    KLOG(kernel, kern, "deleting task thread: " PTR ", name: %s, index: %d",
+        thread, thread->name, thread->list_index);
+    rust_srv *srv = thread->srv;
+    delete thread;
+    delete srv;
 }
 
 void
-rust_scheduler::kill_all_tasks() {
-    I(this, !lock.lock_held_by_current_thread());
-    scoped_lock with(lock);
+rust_scheduler::create_task_threads() {
+    KLOG(kernel, kern, "Using %d scheduler threads.", num_threads);
 
-    for (size_t i = 0; i < running_tasks.length(); i++) {
-        // We don't want the failure of these tasks to propagate back
-        // to the kernel again since we're already failing everything
-        running_tasks[i]->unsupervise();
-        running_tasks[i]->kill();
+    for(size_t i = 0; i < num_threads; ++i) {
+        threads.push(create_task_thread(i));
     }
-
-    for (size_t i = 0; i < blocked_tasks.length(); i++) {
-        blocked_tasks[i]->unsupervise();
-        blocked_tasks[i]->kill();
-    }
-}
-
-size_t
-rust_scheduler::number_of_live_tasks() {
-    return running_tasks.length() + blocked_tasks.length();
 }
 
-/**
- * Delete any dead tasks.
- */
 void
-rust_scheduler::reap_dead_tasks(int id) {
-    I(this, lock.lock_held_by_current_thread());
-    if (dead_tasks.length() == 0) {
-        return;
+rust_scheduler::destroy_task_threads() {
+    for(size_t i = 0; i < num_threads; ++i) {
+        destroy_task_thread(threads[i]);
     }
-
-    // First make a copy of the dead_task list with the lock held
-    size_t dead_tasks_len = dead_tasks.length();
-    rust_task **dead_tasks_copy = (rust_task**)
-        srv->malloc(sizeof(rust_task*) * dead_tasks_len);
-    for (size_t i = 0; i < dead_tasks_len; ++i) {
-        rust_task *task = dead_tasks[i];
-        dead_tasks_copy[i] = task;
-    }
-
-    // Now drop the lock and futz with the tasks. This avoids establishing
-    // a sched->lock then task->lock locking order, which would be devestating
-    // to performance.
-    lock.unlock();
-
-    for (size_t i = 0; i < dead_tasks_len; ++i) {
-        rust_task *task = dead_tasks_copy[i];
-        task->lock.lock();
-        // Make sure this task isn't still running somewhere else...
-        if (task->can_schedule(id)) {
-            DLOG(this, task,
-                "deleting unreferenced dead task %s @0x%" PRIxPTR,
-                task->name, task);
-            task->lock.unlock();
-        } else {
-            task->lock.unlock();
-            dead_tasks_copy[i] = NULL;
-        }
-    }
-
-    // Now grab the lock again and remove the tasks that were truly dead
-    lock.lock();
-
-    for (size_t i = 0; i < dead_tasks_len; ++i) {
-        rust_task *task = dead_tasks_copy[i];
-        if (task) {
-            dead_tasks.remove(task);
-        }
-    }
-
-    // Now unlock again because we have to actually free the dead tasks,
-    // and that may end up wanting to lock the task and sched locks
-    // again (via target->send)
-    lock.unlock();
-
-    for (size_t i = 0; i < dead_tasks_len; ++i) {
-        rust_task *task = dead_tasks_copy[i];
-        if (task) {
-            task->deref();
-            sync::decrement(kernel->live_tasks);
-            kernel->wakeup_schedulers();
-        }
-    }
-    srv->free(dead_tasks_copy);
-
-    lock.lock();
-}
-
-/**
- * Schedules a running task for execution. Only running tasks can be
- * activated.  Blocked tasks have to be unblocked before they can be
- * activated.
- *
- * Returns NULL if no tasks can be scheduled.
- */
-rust_task *
-rust_scheduler::schedule_task(int id) {
-    I(this, this);
-    // FIXME: in the face of failing tasks, this is not always right.
-    // I(this, n_live_tasks() > 0);
-    if (running_tasks.length() > 0) {
-        size_t k = isaac_rand(&rctx);
-        // Look around for a runnable task, starting at k.
-        for(size_t j = 0; j < running_tasks.length(); ++j) {
-            size_t  i = (j + k) % running_tasks.length();
-            if (running_tasks[i]->can_schedule(id)) {
-                return (rust_task *)running_tasks[i];
-            }
-        }
-    }
-    return NULL;
 }
 
 void
-rust_scheduler::log_state() {
-    if (log_rt_task < log_debug) return;
-
-    if (!running_tasks.is_empty()) {
-        log(NULL, log_debug, "running tasks:");
-        for (size_t i = 0; i < running_tasks.length(); i++) {
-            log(NULL, log_debug, "\t task: %s @0x%" PRIxPTR
-                " remaining: %" PRId64 " us",
-                running_tasks[i]->name,
-                running_tasks[i],
-                running_tasks[i]->yield_timer.remaining_us());
-        }
-    }
-
-    if (!blocked_tasks.is_empty()) {
-        log(NULL, log_debug, "blocked tasks:");
-        for (size_t i = 0; i < blocked_tasks.length(); i++) {
-            log(NULL, log_debug, "\t task: %s @0x%" PRIxPTR ", blocked on: 0x%"
-                PRIxPTR " '%s'",
-                blocked_tasks[i]->name, blocked_tasks[i],
-                blocked_tasks[i]->cond, blocked_tasks[i]->cond_name);
-        }
+rust_scheduler::start_task_threads()
+{
+    for(size_t i = 0; i < num_threads; ++i) {
+        rust_task_thread *thread = threads[i];
+        thread->start();
     }
 
-    if (!dead_tasks.is_empty()) {
-        log(NULL, log_debug, "dead tasks:");
-        for (size_t i = 0; i < dead_tasks.length(); i++) {
-            log(NULL, log_debug, "\t task: %s 0x%" PRIxPTR,
-                dead_tasks[i]->name, dead_tasks[i]);
-        }
+    for(size_t i = 0; i < num_threads; ++i) {
+        rust_task_thread *thread = threads[i];
+        thread->join();
     }
 }
-/**
- * Starts the main scheduler loop which performs task scheduling for this
- * domain.
- *
- * Returns once no more tasks can be scheduled and all task ref_counts
- * drop to zero.
- */
-void
-rust_scheduler::start_main_loop() {
-    lock.lock();
-
-    // Make sure someone is watching, to pull us out of infinite loops.
-    //
-    // FIXME: time-based interruption is not presently working; worked
-    // in rustboot and has been completely broken in rustc.
-    //
-    // rust_timer timer(this);
-
-    DLOG(this, dom, "started domain loop %d", id);
 
-    while (kernel->live_tasks > 0) {
-        A(this, kernel->is_deadlocked() == false, "deadlock");
-
-        DLOG(this, dom, "worker %d, number_of_live_tasks = %d, total = %d",
-             id, number_of_live_tasks(), kernel->live_tasks);
-
-        rust_task *scheduled_task = schedule_task(id);
-
-        if (scheduled_task == NULL) {
-            log_state();
-            DLOG(this, task,
-                 "all tasks are blocked, scheduler id %d yielding ...",
-                 id);
-            lock.timed_wait(10);
-            reap_dead_tasks(id);
-            DLOG(this, task,
-                 "scheduler %d resuming ...", id);
-            continue;
-        }
-
-        I(this, scheduled_task->running());
-
-        DLOG(this, task,
-             "activating task %s 0x%" PRIxPTR
-             ", sp=0x%" PRIxPTR
-             ", state: %s",
-             scheduled_task->name,
-             (uintptr_t)scheduled_task,
-             scheduled_task->user.rust_sp,
-             scheduled_task->state->name);
-
-        place_task_in_tls(scheduled_task);
-
-        interrupt_flag = 0;
-
-        DLOG(this, task,
-             "Running task %p on worker %d",
-             scheduled_task, id);
-        scheduled_task->running_on = id;
-        activate(scheduled_task);
-        scheduled_task->running_on = -1;
-
-        DLOG(this, task,
-             "returned from task %s @0x%" PRIxPTR
-             " in state '%s', sp=0x%x, worker id=%d" PRIxPTR,
-             scheduled_task->name,
-             (uintptr_t)scheduled_task,
-             scheduled_task->state->name,
-             scheduled_task->user.rust_sp,
-             id);
-
-        reap_dead_tasks(id);
-    }
-
-    DLOG(this, dom,
-         "terminated scheduler loop, reaping dead tasks ...");
-
-    while (dead_tasks.length() > 0) {
-        DLOG(this, dom,
-             "waiting for %d dead tasks to become dereferenced, "
-             "scheduler yielding ...",
-             dead_tasks.length());
-        log_state();
-        lock.unlock();
-        sync::yield();
-        lock.lock();
-        reap_dead_tasks(id);
+void
+rust_scheduler::kill_all_tasks() {
+    for(size_t i = 0; i < num_threads; ++i) {
+        rust_task_thread *thread = threads[i];
+        thread->kill_all_tasks();
     }
-
-    DLOG(this, dom, "finished main-loop %d", id);
-
-    lock.unlock();
-}
-
-rust_crate_cache *
-rust_scheduler::get_cache() {
-    return &cache;
 }
 
-rust_task *
-rust_scheduler::create_task(rust_task *spawner, const char *name) {
-    rust_task *task =
-        new (this->kernel, "rust_task")
-        rust_task (this, &newborn_tasks, spawner, name);
-    DLOG(this, task, "created task: " PTR ", spawner: %s, name: %s",
-                        task, spawner ? spawner->name : "null", name);
-    if(spawner) {
-        task->pin(spawner->pinned_on);
-    }
-
+rust_task_id
+rust_scheduler::create_task(rust_task *spawner, const char *name,
+                           size_t init_stack_sz) {
+    size_t thread_no;
     {
-        scoped_lock with(lock);
-        newborn_tasks.append(task);
+       scoped_lock with(lock);
+       thread_no = isaac_rand(&rctx) % num_threads;
     }
-
-    sync::increment(kernel->live_tasks);
-
-    return task;
-}
-
-void rust_scheduler::run() {
-    this->start_main_loop();
-}
-
-#ifndef _WIN32
-void
-rust_scheduler::init_tls() {
-    int result = pthread_key_create(&task_key, NULL);
-    assert(!result && "Couldn't create the TLS key!");
-    tls_initialized = true;
+    rust_task_thread *thread = threads[thread_no];
+    return thread->create_task(spawner, name, init_stack_sz);
 }
 
-void
-rust_scheduler::place_task_in_tls(rust_task *task) {
-    int result = pthread_setspecific(task_key, task);
-    assert(!result && "Couldn't place the task in TLS!");
-    task->record_stack_limit();
-}
-
-rust_task *
-rust_scheduler::get_task() {
-    if (!tls_initialized)
-        return NULL;
-    rust_task *task = reinterpret_cast<rust_task *>
-        (pthread_getspecific(task_key));
-    assert(task && "Couldn't get the task from TLS!");
-    return task;
-}
-#else
-void
-rust_scheduler::init_tls() {
-    task_key = TlsAlloc();
-    assert(task_key != TLS_OUT_OF_INDEXES && "Couldn't create the TLS key!");
-    tls_initialized = true;
+rust_task_id
+rust_scheduler::create_task(rust_task *spawner, const char *name) {
+    return create_task(spawner, name, env->min_stack_size);
 }
 
 void
-rust_scheduler::place_task_in_tls(rust_task *task) {
-    BOOL result = TlsSetValue(task_key, task);
-    assert(result && "Couldn't place the task in TLS!");
-    task->record_stack_limit();
+rust_scheduler::exit() {
+    for(size_t i = 0; i < num_threads; ++i) {
+        threads[i]->exit();
+    }
 }
 
-rust_task *
-rust_scheduler::get_task() {
-    if (!tls_initialized)
-        return NULL;
-    rust_task *task = reinterpret_cast<rust_task *>(TlsGetValue(task_key));
-    assert(task && "Couldn't get the task from TLS!");
-    return task;
+size_t
+rust_scheduler::number_of_threads() {
+    return num_threads;
 }
-#endif
-
-//
-// Local Variables:
-// mode: C++
-// fill-column: 70;
-// indent-tabs-mode: nil
-// c-basic-offset: 4
-// buffer-file-coding-system: utf-8-unix
-// End:
-//
index 4980264601162b7933387f18156ab950cfc51f41..03eb3186ed34201e118f2a280d1579ef406472fd 100644 (file)
 #ifndef RUST_SCHEDULER_H
 #define RUST_SCHEDULER_H
 
-#include "context.h"
+#include "rust_internal.h"
 
-#ifndef _WIN32
-#include <pthread.h>
-#else
-#include <windows.h>
-#endif
-
-struct rust_scheduler;
-
-struct rust_hashable_dict {
-    UT_hash_handle hh;
-    void* fields[0];
-};
-
-class rust_crate_cache {
+class rust_scheduler : public kernel_owned<rust_scheduler> {
+    // FIXME: Make these private
 public:
-    type_desc *get_type_desc(size_t size,
-                             size_t align,
-                             size_t n_descs,
-                             type_desc const **descs,
-                             uintptr_t n_obj_params);
-    void** get_dict(size_t n_fields, void** dict);
-
-private:
-
-    type_desc *type_descs;
-    rust_hashable_dict *dicts;
-
-public:
-
-    rust_scheduler *sched;
-    size_t idx;
-
-    rust_crate_cache(rust_scheduler *sched);
-    ~rust_crate_cache();
-    void flush();
-};
-
-struct rust_scheduler : public kernel_owned<rust_scheduler>,
-                        rust_thread
-{
-    RUST_REFCOUNTED(rust_scheduler)
-
-    // Fields known to the compiler:
-    uintptr_t interrupt_flag;
-
-    // Fields known only by the runtime:
-    rust_log _log;
-
-    // NB: this is used to filter *runtime-originating* debug
-    // logging, on a per-scheduler basis. It's not likely what
-    // you want to expose to the user in terms of per-task
-    // or per-module logging control. By default all schedulers
-    // are set to debug-level logging here, and filtered by
-    // runtime category using the pseudo-modules ::rt::foo.
-    uint32_t log_lvl;
-
-    rust_srv *srv;
-    const char *const name;
-
-    rust_task_list newborn_tasks;
-    rust_task_list running_tasks;
-    rust_task_list blocked_tasks;
-    rust_task_list dead_tasks;
-
-    rust_crate_cache cache;
-
-    randctx rctx;
-
     rust_kernel *kernel;
-    int32_t list_index;
-
-    const int id;
-
+    rust_srv *srv;
+    rust_env *env;
+private:
     lock_and_signal lock;
-    size_t min_stack_size;
-
-#ifndef __WIN32__
-    pthread_attr_t attr;
-    static pthread_key_t task_key;
-#else
-    static DWORD task_key;
-#endif
+    array_list<rust_task_thread *> threads;
+    randctx rctx;
+    const size_t num_threads;
+    int rval;
 
-    static bool tls_initialized;
+    void create_task_threads();
+    void destroy_task_threads();
 
-    rust_env *env;
-    context c_context;
+    rust_task_thread *create_task_thread(int id);
+    void destroy_task_thread(rust_task_thread *thread);
 
-    // Only a pointer to 'name' is kept, so it must live as long as this
-    // domain.
-    rust_scheduler(rust_kernel *kernel, rust_srv *srv, int id);
+public:
+    rust_scheduler(rust_kernel *kernel, rust_srv *srv, size_t num_threads);
     ~rust_scheduler();
-    void activate(rust_task *task);
-    void log(rust_task *task, uint32_t level, char const *fmt, ...);
-    rust_log & get_log();
-    void fail();
-
-    rust_crate_cache *get_cache();
-    size_t number_of_live_tasks();
-
-    void reap_dead_tasks(int id);
-    rust_task *schedule_task(int id);
-
-    void start_main_loop();
-
-    void log_state();
 
+    void start_task_threads();
     void kill_all_tasks();
-
-    rust_task *create_task(rust_task *spawner, const char *name);
-
-    virtual void run();
-
-#ifdef __WIN32__
-    inline void win32_require(LPCTSTR fn, BOOL ok) {
-        kernel->win32_require(fn, ok);
-    }
-#endif
-
-    void init_tls();
-    void place_task_in_tls(rust_task *task);
-
-    static rust_task *get_task();
+    rust_task_id create_task(rust_task *spawner,
+                            const char *name,
+                            size_t init_stack_sz);
+    rust_task_id create_task(rust_task *spawner, const char *name);
+    void exit();
+    size_t number_of_threads();
 };
 
-inline rust_log &
-rust_scheduler::get_log() {
-    return _log;
-}
-
-//
-// Local Variables:
-// mode: C++
-// fill-column: 78;
-// indent-tabs-mode: nil
-// c-basic-offset: 4
-// buffer-file-coding-system: utf-8-unix
-// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
-// End:
-//
-
 #endif /* RUST_SCHEDULER_H */
index 37d8a42e95a191383b81bd6d34bb86dd68556769..20f8bef89aad915672165ee8b19f1134884cf267 100644 (file)
@@ -264,7 +264,7 @@ private:
         result = sub.result;
     }
 
-    inline void walk_box_contents2(cmp &sub, ptr_pair &ref_count_dp) {
+    inline void walk_box_contents2(cmp &sub, ptr_pair &box_dp) {
         sub.align = true;
         sub.walk();
         result = sub.result;
@@ -532,7 +532,7 @@ extern "C" void
 shape_cmp_type(int8_t *result, const type_desc *tydesc,
               const type_desc **subtydescs, uint8_t *data_0,
               uint8_t *data_1, uint8_t cmp_type) {
-    rust_task *task = rust_scheduler::get_task();
+    rust_task *task = rust_task_thread::get_task();
     shape::arena arena;
 
     // FIXME: This may well be broken when comparing two closures or objects
@@ -553,7 +553,7 @@ shape_cmp_type(int8_t *result, const type_desc *tydesc,
 
 extern "C" rust_str *
 shape_log_str(const type_desc *tydesc, uint8_t *data) {
-    rust_task *task = rust_scheduler::get_task();
+    rust_task *task = rust_task_thread::get_task();
 
     shape::arena arena;
     shape::type_param *params =
@@ -571,7 +571,7 @@ shape_log_str(const type_desc *tydesc, uint8_t *data) {
 
 extern "C" void
 shape_log_type(const type_desc *tydesc, uint8_t *data, uint32_t level) {
-    rust_task *task = rust_scheduler::get_task();
+    rust_task *task = rust_task_thread::get_task();
 
     shape::arena arena;
     shape::type_param *params =
@@ -583,6 +583,6 @@ shape_log_type(const type_desc *tydesc, uint8_t *data, uint32_t level) {
 
     log.walk();
 
-    task->sched->log(task, level, "%s", ss.str().c_str());
+    task->thread->log(task, level, "%s", ss.str().c_str());
 }
 
index 848e304df3025452d446e17761498f5015f0f37b..92f660db741a7117dd33c8c3ec4a266f6ba96b3a 100644 (file)
@@ -28,7 +28,6 @@ namespace shape {
 
 typedef unsigned long tag_variant_t;
 typedef unsigned long tag_align_t;
-typedef unsigned long ref_cnt_t;
 
 // Constants
 
@@ -376,7 +375,6 @@ ctxt<T>::walk() {
     case SHAPE_TAG:      walk_tag0();             break;
     case SHAPE_BOX:      walk_box0();             break;
     case SHAPE_STRUCT:   walk_struct0();          break;
-    case SHAPE_OBJ:      WALK_SIMPLE(walk_obj1);      break;
     case SHAPE_RES:      walk_res0();             break;
     case SHAPE_VAR:      walk_var0();             break;
     case SHAPE_UNIQ:     walk_uniq0();            break;
@@ -591,7 +589,6 @@ public:
           default: abort();
         }
     }
-    void walk_obj1() { DPRINT("obj"); }
     void walk_iface1() { DPRINT("iface"); }
 
     void walk_tydesc1(char kind) {
@@ -645,7 +642,6 @@ public:
     void walk_uniq1()       { sa.set(sizeof(void *),   sizeof(void *)); }
     void walk_box1()        { sa.set(sizeof(void *),   sizeof(void *)); }
     void walk_fn1(char)     { sa.set(sizeof(void *)*2, sizeof(void *)); }
-    void walk_obj1()        { sa.set(sizeof(void *)*2, sizeof(void *)); }
     void walk_iface1()      { sa.set(sizeof(void *),   sizeof(void *)); }
     void walk_tydesc1(char) { sa.set(sizeof(void *),   sizeof(void *)); }
     void walk_closure1();
@@ -854,9 +850,8 @@ protected:
 
     void walk_box_contents1();
     void walk_uniq_contents1();
-    void walk_fn_contents1(ptr &dp, bool null_td);
-    void walk_obj_contents1(ptr &dp);
-    void walk_iface_contents1(ptr &dp);
+    void walk_fn_contents1();
+    void walk_iface_contents1();
     void walk_variant1(tag_info &tinfo, tag_variant_t variant);
 
     static std::pair<uint8_t *,uint8_t *> get_vec_data_range(ptr dp);
@@ -894,13 +889,6 @@ public:
         dp = next_dp;
     }
 
-    void walk_obj1() {
-        ALIGN_TO(alignof<void *>());
-        U next_dp = dp + sizeof(void *) * 2;
-        static_cast<T *>(this)->walk_obj2();
-        dp = next_dp;
-    }
-
     void walk_iface1() {
         ALIGN_TO(alignof<void *>());
         U next_dp = dp + sizeof(void *);
@@ -946,9 +934,17 @@ template<typename T,typename U>
 void
 data<T,U>::walk_box_contents1() {
     typename U::template data<uint8_t *>::t box_ptr = bump_dp<uint8_t *>(dp);
-    U ref_count_dp(box_ptr);
-    T sub(*static_cast<T *>(this), ref_count_dp + sizeof(ref_cnt_t));
-    static_cast<T *>(this)->walk_box_contents2(sub, ref_count_dp);
+    U box_dp(box_ptr);
+
+    // No need to worry about alignment so long as the box header is
+    // a multiple of 16 bytes.  We can just find the body by adding
+    // the size of header to box_dp.
+    assert ((sizeof(rust_opaque_box) % 16) == 0 ||
+            !"Must align to find the box body");
+
+    U body_dp = box_dp + sizeof(rust_opaque_box);
+    T sub(*static_cast<T *>(this), body_dp);
+    static_cast<T *>(this)->walk_box_contents2(sub, box_dp);
 }
 
 template<typename T,typename U>
@@ -1010,80 +1006,26 @@ data<T,U>::walk_tag1(tag_info &tinfo) {
 
 template<typename T,typename U>
 void
-data<T,U>::walk_fn_contents1(ptr &dp, bool null_td) {
+data<T,U>::walk_fn_contents1() {
     fn_env_pair pair = bump_dp<fn_env_pair>(dp);
     if (!pair.env)
         return;
 
     arena arena;
     const type_desc *closure_td = pair.env->td;
-    type_param *params =
-      type_param::from_tydesc(closure_td, arena);
-    ptr closure_dp((uintptr_t)pair.env);
+    type_param *params = type_param::from_tydesc(closure_td, arena);
+    ptr closure_dp((uintptr_t)box_body(pair.env));
     T sub(*static_cast<T *>(this), closure_td->shape, params,
           closure_td->shape_tables, closure_dp);
     sub.align = true;
 
-    if (null_td) {
-        // if null_td flag is true, null out the type descr from
-        // the data structure while we walk.  This is used in cycle
-        // collector when we are sweeping up data.  The idea is that
-        // we are using the information in the embedded type desc to
-        // walk the contents, so we do not want to free it during that
-        // walk.  This is not *strictly* necessary today because
-        // type_param::from_tydesc() actually pulls out the "shape"
-        // string and other information and copies it into a new
-        // location that is unaffected by the free.  But it seems
-        // safer, particularly as this pulling out of information will
-        // not cope with nested, derived type descriptors.
-        pair.env->td = NULL;
-    }
-
-    sub.walk();
-
-    if (null_td) {
-        pair.env->td = closure_td;
-    }
-}
-
-template<typename T,typename U>
-void
-data<T,U>::walk_obj_contents1(ptr &dp) {
-    dp += sizeof(void *);   // Skip over the vtable.
-
-    uint8_t *box_ptr = bump_dp<uint8_t *>(dp);
-    type_desc *subtydesc =
-        *reinterpret_cast<type_desc **>(box_ptr + sizeof(void *));
-    ptr obj_closure_dp(box_ptr + sizeof(void *));
-    if (!box_ptr)   // Null check.
-        return;
-
-    arena arena;
-    type_param *params = type_param::from_obj_shape(subtydesc->shape,
-                                                    obj_closure_dp, arena);
-    T sub(*static_cast<T *>(this), subtydesc->shape, params,
-          subtydesc->shape_tables, obj_closure_dp);
-    sub.align = true;
     sub.walk();
 }
 
 template<typename T,typename U>
 void
-data<T,U>::walk_iface_contents1(ptr &dp) {
-    uint8_t *box_ptr = bump_dp<uint8_t *>(dp);
-    if (!box_ptr) return;
-    U ref_count_dp(box_ptr);
-    uint8_t *body_ptr = box_ptr + sizeof(void*);
-    type_desc *valtydesc =
-        *reinterpret_cast<type_desc **>(body_ptr);
-    ptr value_dp(body_ptr + sizeof(void*) * 2);
-    // FIXME The 5 is a hard-coded way to skip over a struct shape
-    // header and the first two (number-typed) fields. This is too
-    // fragile, but I didn't see a good way to properly encode it.
-    T sub(*static_cast<T *>(this), valtydesc->shape + 5, NULL, NULL,
-          value_dp);
-    sub.align = true;
-    static_cast<T *>(this)->walk_box_contents2(sub, ref_count_dp);
+data<T,U>::walk_iface_contents1() {
+    walk_box_contents1();
 }
 
 // Polymorphic logging, for convenience
@@ -1161,19 +1103,13 @@ private:
     void walk_fn2(char kind) {
         out << prefix << "fn";
         prefix = "";
-        data<log,ptr>::walk_fn_contents1(dp, false);
-    }
-
-    void walk_obj2() {
-        out << prefix << "obj";
-        prefix = "";
-        data<log,ptr>::walk_obj_contents1(dp);
+        data<log,ptr>::walk_fn_contents1();
     }
 
     void walk_iface2() {
         out << prefix << "iface(";
         prefix = "";
-        data<log,ptr>::walk_iface_contents1(dp);
+        data<log,ptr>::walk_iface_contents1();
         out << prefix << ")";
     }
 
index 758174a4ebb119c479d2029cf5bb4540767b38bc..9192af511d95383add00facabf3264ea4a10bc1f 100644 (file)
@@ -25,11 +25,7 @@ rust_srv::realloc(void *p, size_t bytes) {
 
 void
 rust_srv::log(char const *msg) {
-    printf("rust: %s\n", msg);
-    // FIXME: flushing each time is expensive, but at the moment
-    // necessary to get output through before a rust_task::fail
-    // call. This should be changed.
-    fflush(stdout);
+    fprintf(stderr, "rust: %s\n", msg);
 }
 
 void
index 4d136a59ae68fa461c7cdeb01bd825ab7e78157f..136b00e1f56eff3ac9878749cbc357ddb1622318 100644 (file)
@@ -14,6 +14,7 @@
 #include <algorithm>
 
 #include "globals.h"
+#include "rust_upcall.h"
 
 // The amount of extra space at the end of each stack segment, available
 // to the rt, compiler and dynamic linker for running small functions
@@ -65,20 +66,8 @@ const uint8_t stack_canary[] = {0xAB, 0xCD, 0xAB, 0xCD,
                                 0xAB, 0xCD, 0xAB, 0xCD,
                                 0xAB, 0xCD, 0xAB, 0xCD};
 
-// Stack size
-size_t g_custom_min_stack_size = 0;
-
 static size_t
-get_min_stk_size(size_t default_size) {
-    if (g_custom_min_stack_size != 0) {
-        return g_custom_min_stack_size;
-    } else {
-        return default_size;
-    }
-}
-
-static size_t
-get_next_stk_size(rust_scheduler *sched, rust_task *task,
+get_next_stk_size(rust_task_thread *thread, rust_task *task,
                   size_t min, size_t current, size_t requested) {
     LOG(task, mem, "calculating new stack size for 0x%" PRIxPTR, task);
     LOG(task, mem,
@@ -95,7 +84,7 @@ get_next_stk_size(rust_scheduler *sched, rust_task *task,
     sz = std::max(sz, next);
 
     LOG(task, mem, "next stack size: %" PRIdPTR, sz);
-    I(sched, requested <= sz);
+    I(thread, requested <= sz);
     return sz;
 }
 
@@ -143,13 +132,13 @@ user_stack_size(stk_seg *stk) {
 
 static void
 free_stk(rust_task *task, stk_seg *stk) {
-    LOGPTR(task->sched, "freeing stk segment", (uintptr_t)stk);
+    LOGPTR(task->thread, "freeing stk segment", (uintptr_t)stk);
     task->total_stack_sz -= user_stack_size(stk);
     task->free(stk);
 }
 
 static stk_seg*
-new_stk(rust_scheduler *sched, rust_task *task, size_t requested_sz)
+new_stk(rust_task_thread *thread, rust_task *task, size_t requested_sz)
 {
     LOG(task, mem, "creating new stack for task %" PRIxPTR, task);
     if (task->stk) {
@@ -157,7 +146,7 @@ new_stk(rust_scheduler *sched, rust_task *task, size_t requested_sz)
     }
 
     // The minimum stack size, in bytes, of a Rust stack, excluding red zone
-    size_t min_sz = get_min_stk_size(sched->min_stack_size);
+    size_t min_sz = thread->min_stack_size;
 
     // Try to reuse an existing stack segment
     if (task->stk != NULL && task->stk->prev != NULL) {
@@ -165,7 +154,7 @@ new_stk(rust_scheduler *sched, rust_task *task, size_t requested_sz)
         if (min_sz <= prev_sz && requested_sz <= prev_sz) {
             LOG(task, mem, "reusing existing stack");
             task->stk = task->stk->prev;
-            A(sched, task->stk->prev == NULL, "Bogus stack ptr");
+            A(thread, task->stk->prev == NULL, "Bogus stack ptr");
             config_valgrind_stack(task->stk);
             return task->stk;
         } else {
@@ -181,23 +170,23 @@ new_stk(rust_scheduler *sched, rust_task *task, size_t requested_sz)
         current_sz = user_stack_size(task->stk);
     }
     // The calculated size of the new stack, excluding red zone
-    size_t rust_stk_sz = get_next_stk_size(sched, task, min_sz,
+    size_t rust_stk_sz = get_next_stk_size(thread, task, min_sz,
                                            current_sz, requested_sz);
 
-    if (task->total_stack_sz + rust_stk_sz > sched->env->max_stack_size) {
+    if (task->total_stack_sz + rust_stk_sz > thread->env->max_stack_size) {
         LOG_ERR(task, task, "task %" PRIxPTR " ran out of stack", task);
         task->fail();
     }
 
     size_t sz = sizeof(stk_seg) + rust_stk_sz + RED_ZONE_SIZE;
     stk_seg *stk = (stk_seg *)task->malloc(sz, "stack");
-    LOGPTR(task->sched, "new stk", (uintptr_t)stk);
+    LOGPTR(task->thread, "new stk", (uintptr_t)stk);
     memset(stk, 0, sizeof(stk_seg));
     add_stack_canary(stk);
     stk->prev = NULL;
     stk->next = task->stk;
     stk->end = (uintptr_t) &stk->data[rust_stk_sz + RED_ZONE_SIZE];
-    LOGPTR(task->sched, "stk end", stk->end);
+    LOGPTR(task->thread, "stk end", stk->end);
 
     task->stk = stk;
     config_valgrind_stack(task->stk);
@@ -233,19 +222,21 @@ del_stk(rust_task *task, stk_seg *stk)
     unconfig_valgrind_stack(stk);
     if (delete_stack) {
         free_stk(task, stk);
-        A(task->sched, task->total_stack_sz == 0, "Stack size should be 0");
+        A(task->thread, task->total_stack_sz == 0, "Stack size should be 0");
     }
 }
 
 // Tasks
-rust_task::rust_task(rust_scheduler *sched, rust_task_list *state,
-                     rust_task *spawner, const char *name) :
+rust_task::rust_task(rust_task_thread *thread, rust_task_list *state,
+                     rust_task *spawner, const char *name,
+                     size_t init_stack_sz) :
     ref_count(1),
     stk(NULL),
     runtime_sp(0),
-    sched(sched),
+    sched(thread->sched),
+    thread(thread),
     cache(NULL),
-    kernel(sched->kernel),
+    kernel(thread->kernel),
     name(name),
     state(state),
     cond(NULL),
@@ -254,9 +245,8 @@ rust_task::rust_task(rust_scheduler *sched, rust_task_list *state,
     list_index(-1),
     next_port_id(0),
     rendezvous_ptr(0),
-    running_on(-1),
-    pinned_on(-1),
-    local_region(&sched->srv->local_region),
+    local_region(&thread->srv->local_region),
+    boxed(&local_region),
     unwinding(false),
     killed(false),
     propagate_failure(true),
@@ -264,14 +254,14 @@ rust_task::rust_task(rust_scheduler *sched, rust_task_list *state,
     cc_counter(0),
     total_stack_sz(0)
 {
-    LOGPTR(sched, "new task", (uintptr_t)this);
-    DLOG(sched, task, "sizeof(task) = %d (0x%x)", sizeof *this, sizeof *this);
+    LOGPTR(thread, "new task", (uintptr_t)this);
+    DLOG(thread, task, "sizeof(task) = %d (0x%x)", sizeof *this, sizeof *this);
 
     assert((void*)this == (void*)&user);
 
     user.notify_enabled = 0;
 
-    stk = new_stk(sched, this, 0);
+    stk = new_stk(thread, this, init_stack_sz);
     user.rust_sp = stk->end;
     if (supervisor) {
         supervisor->ref();
@@ -280,24 +270,24 @@ rust_task::rust_task(rust_scheduler *sched, rust_task_list *state,
 
 rust_task::~rust_task()
 {
-    I(sched, !sched->lock.lock_held_by_current_thread());
-    I(sched, port_table.is_empty());
-    DLOG(sched, task, "~rust_task %s @0x%" PRIxPTR ", refcnt=%d",
+    I(thread, !thread->lock.lock_held_by_current_thread());
+    I(thread, port_table.is_empty());
+    DLOG(thread, task, "~rust_task %s @0x%" PRIxPTR ", refcnt=%d",
          name, (uintptr_t)this, ref_count);
 
+    // FIXME: We should do this when the task exits, not in the destructor
     if (supervisor) {
         supervisor->deref();
     }
 
-    kernel->release_task_id(user.id);
-
     /* FIXME: tighten this up, there are some more
        assertions that hold at task-lifecycle events. */
-    I(sched, ref_count == 0); // ||
+    I(thread, ref_count == 0); // ||
     //   (ref_count == 1 && this == sched->root_task));
 
     // Delete all the stacks. There may be more than one if the task failed
     // and no landing pads stopped to clean up.
+    // FIXME: We should do this when the task exits, not in the destructor
     while (stk != NULL) {
         del_stk(this, stk);
     }
@@ -306,7 +296,7 @@ rust_task::~rust_task()
 struct spawn_args {
     rust_task *task;
     spawn_fn f;
-    rust_opaque_closure *envptr;
+    rust_opaque_box *envptr;
     void *argptr;
 };
 
@@ -336,13 +326,11 @@ cleanup_task(cleanup_args *args) {
 #ifndef __WIN32__
         task->conclude_failure();
 #else
-        A(task->sched, false, "Shouldn't happen");
+        A(task->thread, false, "Shouldn't happen");
 #endif
     }
 }
 
-extern "C" void upcall_shared_free(void* ptr);
-
 // This runs on the Rust stack
 extern "C" CDECL
 void task_start_wrapper(spawn_args *a)
@@ -355,37 +343,38 @@ void task_start_wrapper(spawn_args *a)
         // must have void return type, we can safely pass 0.
         a->f(0, a->envptr, a->argptr);
     } catch (rust_task *ex) {
-        A(task->sched, ex == task,
+        A(task->thread, ex == task,
           "Expected this task to be thrown for unwinding");
         threw_exception = true;
     }
 
-    rust_opaque_closure* env = a->envptr;
+    rust_opaque_box* env = a->envptr;
     if(env) {
-        // free the environment.
+        // free the environment (which should be a unique closure).
         const type_desc *td = env->td;
         LOG(task, task, "Freeing env %p with td %p", env, td);
-        td->drop_glue(NULL, NULL, td->first_param, env);
+        td->drop_glue(NULL, NULL, td->first_param, box_body(env));
+        upcall_free_shared_type_desc(env->td);
         upcall_shared_free(env);
     }
 
     // The cleanup work needs lots of stack
     cleanup_args ca = {a, threw_exception};
-    task->sched->c_context.call_shim_on_c_stack(&ca, (void*)cleanup_task);
+    task->thread->c_context.call_shim_on_c_stack(&ca, (void*)cleanup_task);
 
     task->ctx.next->swap(task->ctx);
 }
 
 void
 rust_task::start(spawn_fn spawnee_fn,
-                 rust_opaque_closure *envptr,
+                 rust_opaque_box *envptr,
                  void *argptr)
 {
     LOG(this, task, "starting task from fn 0x%" PRIxPTR
         " with env 0x%" PRIxPTR " and arg 0x%" PRIxPTR,
         spawnee_fn, envptr, argptr);
 
-    I(sched, stk->data != NULL);
+    I(thread, stk->data != NULL);
 
     char *sp = (char *)user.rust_sp;
 
@@ -405,20 +394,16 @@ rust_task::start(spawn_fn spawnee_fn,
 
 void rust_task::start()
 {
-    yield_timer.reset_us(0);
-    transition(&sched->newborn_tasks, &sched->running_tasks);
-    sched->lock.signal();
+    transition(&thread->newborn_tasks, &thread->running_tasks);
 }
 
 // Only run this on the rust stack
 void
-rust_task::yield(size_t time_in_us, bool *killed) {
+rust_task::yield(bool *killed) {
     if (this->killed) {
         *killed = true;
     }
 
-    yield_timer.reset_us(time_in_us);
-
     // Return to the scheduler.
     ctx.next->swap(ctx);
 
@@ -444,8 +429,6 @@ rust_task::kill() {
     // Unblock the task so it can unwind.
     unblock();
 
-    sched->lock.signal();
-
     LOG(this, task, "preparing to unwind task: 0x%" PRIxPTR, this);
     // run_on_resume(rust_unwind_glue);
 }
@@ -458,7 +441,7 @@ bool rust_task_is_unwinding(rust_task *rt) {
 void
 rust_task::fail() {
     // See note in ::kill() regarding who should call this.
-    DLOG(sched, task, "task %s @0x%" PRIxPTR " failing", name, this);
+    DLOG(thread, task, "task %s @0x%" PRIxPTR " failing", name, this);
     backtrace();
     unwinding = true;
 #ifndef __WIN32__
@@ -467,7 +450,7 @@ rust_task::fail() {
     die();
     conclude_failure();
     // FIXME: Need unwinding on windows. This will end up aborting
-    sched->fail();
+    thread->fail();
 #endif
 }
 
@@ -479,7 +462,7 @@ rust_task::conclude_failure() {
 void
 rust_task::fail_parent() {
     if (supervisor) {
-        DLOG(sched, task,
+        DLOG(thread, task,
              "task %s @0x%" PRIxPTR
              " propagating failure to supervisor %s @0x%" PRIxPTR,
              name, this, supervisor->name, supervisor);
@@ -487,17 +470,17 @@ rust_task::fail_parent() {
     }
     // FIXME: implement unwinding again.
     if (NULL == supervisor && propagate_failure)
-        sched->fail();
+        thread->fail();
 }
 
 void
 rust_task::unsupervise()
 {
-    DLOG(sched, task,
+    if (supervisor) {
+        DLOG(thread, task,
              "task %s @0x%" PRIxPTR
              " disconnecting from supervisor %s @0x%" PRIxPTR,
              name, this, supervisor->name, supervisor);
-    if (supervisor) {
         supervisor->deref();
     }
     supervisor = NULL;
@@ -513,13 +496,13 @@ rust_task::get_frame_glue_fns(uintptr_t fp) {
 bool
 rust_task::running()
 {
-    return state == &sched->running_tasks;
+    return state == &thread->running_tasks;
 }
 
 bool
 rust_task::blocked()
 {
-    return state == &sched->blocked_tasks;
+    return state == &thread->blocked_tasks;
 }
 
 bool
@@ -531,7 +514,7 @@ rust_task::blocked_on(rust_cond *on)
 bool
 rust_task::dead()
 {
-    return state == &sched->dead_tasks;
+    return state == &thread->dead_tasks;
 }
 
 void *
@@ -541,13 +524,13 @@ rust_task::malloc(size_t sz, const char *tag, type_desc *td)
 }
 
 void *
-rust_task::realloc(void *data, size_t sz, bool is_gc)
+rust_task::realloc(void *data, size_t sz)
 {
     return local_region.realloc(data, sz);
 }
 
 void
-rust_task::free(void *p, bool is_gc)
+rust_task::free(void *p)
 {
     local_region.free(p);
 }
@@ -555,58 +538,55 @@ rust_task::free(void *p, bool is_gc)
 void
 rust_task::transition(rust_task_list *src, rust_task_list *dst) {
     bool unlock = false;
-    if(!sched->lock.lock_held_by_current_thread()) {
+    if(!thread->lock.lock_held_by_current_thread()) {
         unlock = true;
-        sched->lock.lock();
+        thread->lock.lock();
     }
-    DLOG(sched, task,
+    DLOG(thread, task,
          "task %s " PTR " state change '%s' -> '%s' while in '%s'",
          name, (uintptr_t)this, src->name, dst->name, state->name);
-    I(sched, state == src);
+    I(thread, state == src);
     src->remove(this);
     dst->append(this);
     state = dst;
+    thread->lock.signal();
     if(unlock)
-        sched->lock.unlock();
+        thread->lock.unlock();
 }
 
 void
 rust_task::block(rust_cond *on, const char* name) {
-    I(sched, !lock.lock_held_by_current_thread());
+    I(thread, !lock.lock_held_by_current_thread());
     scoped_lock with(lock);
     LOG(this, task, "Blocking on 0x%" PRIxPTR ", cond: 0x%" PRIxPTR,
                          (uintptr_t) on, (uintptr_t) cond);
-    A(sched, cond == NULL, "Cannot block an already blocked task.");
-    A(sched, on != NULL, "Cannot block on a NULL object.");
+    A(thread, cond == NULL, "Cannot block an already blocked task.");
+    A(thread, on != NULL, "Cannot block on a NULL object.");
 
-    transition(&sched->running_tasks, &sched->blocked_tasks);
+    transition(&thread->running_tasks, &thread->blocked_tasks);
     cond = on;
     cond_name = name;
 }
 
 void
 rust_task::wakeup(rust_cond *from) {
-    I(sched, !lock.lock_held_by_current_thread());
+    I(thread, !lock.lock_held_by_current_thread());
     scoped_lock with(lock);
-    A(sched, cond != NULL, "Cannot wake up unblocked task.");
+    A(thread, cond != NULL, "Cannot wake up unblocked task.");
     LOG(this, task, "Blocked on 0x%" PRIxPTR " woken up on 0x%" PRIxPTR,
                         (uintptr_t) cond, (uintptr_t) from);
-    A(sched, cond == from, "Cannot wake up blocked task on wrong condition.");
+    A(thread, cond == from, "Cannot wake up blocked task on wrong condition.");
 
-    transition(&sched->blocked_tasks, &sched->running_tasks);
-    I(sched, cond == from);
     cond = NULL;
     cond_name = "none";
-
-    sched->lock.signal();
+    transition(&thread->blocked_tasks, &thread->running_tasks);
 }
 
 void
 rust_task::die() {
-    I(sched, !lock.lock_held_by_current_thread());
+    I(thread, !lock.lock_held_by_current_thread());
     scoped_lock with(lock);
-    transition(&sched->running_tasks, &sched->dead_tasks);
-    sched->lock.signal();
+    transition(&thread->running_tasks, &thread->dead_tasks);
 }
 
 void
@@ -622,8 +602,8 @@ rust_crate_cache *
 rust_task::get_crate_cache()
 {
     if (!cache) {
-        DLOG(sched, task, "fetching cache for current crate");
-        cache = sched->get_cache();
+        DLOG(thread, task, "fetching cache for current crate");
+        cache = thread->get_cache();
     }
     return cache;
 }
@@ -638,48 +618,28 @@ rust_task::backtrace() {
 #endif
 }
 
-bool rust_task::can_schedule(int id)
-{
-    return yield_timer.has_timed_out() &&
-        running_on == -1 &&
-        (pinned_on == -1 || pinned_on == id);
-}
-
 void *
 rust_task::calloc(size_t size, const char *tag) {
     return local_region.calloc(size, tag);
 }
 
-void rust_task::pin() {
-    I(this->sched, running_on != -1);
-    pinned_on = running_on;
-}
-
-void rust_task::pin(int id) {
-    I(this->sched, running_on == -1);
-    pinned_on = id;
-}
-
-void rust_task::unpin() {
-    pinned_on = -1;
-}
-
 rust_port_id rust_task::register_port(rust_port *port) {
-    I(sched, !lock.lock_held_by_current_thread());
+    I(thread, !lock.lock_held_by_current_thread());
     scoped_lock with(lock);
 
     rust_port_id id = next_port_id++;
+    A(thread, id != INTPTR_MAX, "Hit the maximum port id");
     port_table.put(id, port);
     return id;
 }
 
 void rust_task::release_port(rust_port_id id) {
-    I(sched, lock.lock_held_by_current_thread());
+    I(thread, lock.lock_held_by_current_thread());
     port_table.remove(id);
 }
 
 rust_port *rust_task::get_port_by_id(rust_port_id id) {
-    I(sched, !lock.lock_held_by_current_thread());
+    I(thread, !lock.lock_held_by_current_thread());
     scoped_lock with(lock);
     rust_port *port = NULL;
     port_table.get(id, &port);
@@ -689,38 +649,6 @@ rust_port *rust_task::get_port_by_id(rust_port_id id) {
     return port;
 }
 
-
-// Temporary routine to allow boxes on one task's shared heap to be reparented
-// to another.
-const type_desc *
-rust_task::release_alloc(void *alloc) {
-    I(sched, !lock.lock_held_by_current_thread());
-    lock.lock();
-
-    assert(local_allocs.find(alloc) != local_allocs.end());
-    const type_desc *tydesc = local_allocs[alloc];
-    local_allocs.erase(alloc);
-
-    local_region.release_alloc(alloc);
-
-    lock.unlock();
-    return tydesc;
-}
-
-// Temporary routine to allow boxes from one task's shared heap to be
-// reparented to this one.
-void
-rust_task::claim_alloc(void *alloc, const type_desc *tydesc) {
-    I(sched, !lock.lock_held_by_current_thread());
-    lock.lock();
-
-    assert(local_allocs.find(alloc) == local_allocs.end());
-    local_allocs[alloc] = tydesc;
-    local_region.claim_alloc(alloc);
-
-    lock.unlock();
-}
-
 void
 rust_task::notify(bool success) {
     // FIXME (1078) Do this in rust code
@@ -749,8 +677,8 @@ record_sp(void *limit);
 void *
 rust_task::new_stack(size_t stk_sz, void *args_addr, size_t args_sz) {
 
-    stk_seg *stk_seg = new_stk(sched, this, stk_sz + args_sz);
-    A(sched, stk_seg->end - (uintptr_t)stk_seg->data >= stk_sz + args_sz,
+    stk_seg *stk_seg = new_stk(thread, this, stk_sz + args_sz);
+    A(thread, stk_seg->end - (uintptr_t)stk_seg->data >= stk_sz + args_sz,
       "Did not receive enough stack");
     uint8_t *new_sp = (uint8_t*)stk_seg->end;
     // Push the function arguments to the new stack
@@ -774,7 +702,7 @@ rust_task::record_stack_limit() {
     // subtracting the frame size. As a result we need our stack limit to
     // account for those 256 bytes.
     const unsigned LIMIT_OFFSET = 256;
-    A(sched,
+    A(thread,
       (uintptr_t)stk->end - RED_ZONE_SIZE
       - (uintptr_t)stk->data >= LIMIT_OFFSET,
       "Stack size must be greater than LIMIT_OFFSET");
@@ -805,7 +733,7 @@ rust_task::reset_stack_limit() {
     uintptr_t sp = get_sp();
     while (!sp_in_stk_seg(sp, stk)) {
         del_stk(this, stk);
-        A(sched, stk != NULL, "Failed to find the current stack");
+        A(thread, stk != NULL, "Failed to find the current stack");
     }
     record_stack_limit();
 }
index 6ae663d2066b0db18c94d8b1b748e3e4b314331e..7e407b382000d75ae32d4c9c9db22464fb65b2fb 100644 (file)
@@ -14,6 +14,7 @@
 #include "rust_internal.h"
 #include "rust_kernel.h"
 #include "rust_obstack.h"
+#include "boxed_region.h"
 
 // Corresponds to the rust chan (currently _chan) type.
 struct chan_handle {
@@ -71,11 +72,11 @@ rust_task : public kernel_owned<rust_task>, rust_cond
 
     RUST_ATOMIC_REFCOUNT();
 
-    // Fields known to the compiler.
     context ctx;
     stk_seg *stk;
     uintptr_t runtime_sp;      // Runtime sp while task running.
     rust_scheduler *sched;
+    rust_task_thread *thread;
     rust_crate_cache *cache;
 
     // Fields known only to the runtime.
@@ -89,9 +90,6 @@ rust_task : public kernel_owned<rust_task>, rust_cond
 
     rust_port_id next_port_id;
 
-    // Keeps track of the last time this task yielded.
-    timer yield_timer;
-
     // Rendezvous pointer for receiving data when blocked on a port. If we're
     // trying to read data and no data is available on any incoming channel,
     // we block on the port, and yield control to the scheduler. Since, we
@@ -100,12 +98,8 @@ rust_task : public kernel_owned<rust_task>, rust_cond
     // that location before waking us up.
     uintptr_t* rendezvous_ptr;
 
-    // This flag indicates that a worker is either currently running the task
-    // or is about to run this task.
-    int running_on;
-    int pinned_on;
-
     memory_region local_region;
+    boxed_region boxed;
 
     // Indicates that fail() has been called and we are cleaning up.
     // We use this to suppress the "killed" flag during calls to yield.
@@ -121,7 +115,6 @@ rust_task : public kernel_owned<rust_task>, rust_cond
 
     rust_obstack dynastack;
 
-    std::map<void *,const type_desc *> local_allocs;
     uint32_t cc_counter;
 
     debug::task_debug_info debug;
@@ -130,15 +123,16 @@ rust_task : public kernel_owned<rust_task>, rust_cond
     size_t total_stack_sz;
 
     // Only a pointer to 'name' is kept, so it must live as long as this task.
-    rust_task(rust_scheduler *sched,
+    rust_task(rust_task_thread *thread,
               rust_task_list *state,
               rust_task *spawner,
-              const char *name);
+              const char *name,
+              size_t init_stack_sz);
 
     ~rust_task();
 
     void start(spawn_fn spawnee_fn,
-               rust_opaque_closure *env,
+               rust_opaque_box *env,
                void *args);
     void start();
     bool running();
@@ -147,8 +141,8 @@ rust_task : public kernel_owned<rust_task>, rust_cond
     bool dead();
 
     void *malloc(size_t sz, const char *tag, type_desc *td=0);
-    void *realloc(void *data, size_t sz, bool gc_mem=false);
-    void free(void *p, bool gc_mem=false);
+    void *realloc(void *data, size_t sz);
+    void free(void *p);
 
     void transition(rust_task_list *src, rust_task_list *dst);
 
@@ -160,8 +154,8 @@ rust_task : public kernel_owned<rust_task>, rust_cond
     // Print a backtrace, if the "bt" logging option is on.
     void backtrace();
 
-    // Yields for a specified duration of time.
-    void yield(size_t time_in_ms, bool *killed);
+    // Yields control to the scheduler. Called from the Rust stack
+    void yield(bool *killed);
 
     // Fail this task (assuming caller-on-stack is different task).
     void kill();
@@ -177,14 +171,8 @@ rust_task : public kernel_owned<rust_task>, rust_cond
     frame_glue_fns *get_frame_glue_fns(uintptr_t fp);
     rust_crate_cache * get_crate_cache();
 
-    bool can_schedule(int worker);
-
     void *calloc(size_t size, const char *tag);
 
-    void pin();
-    void pin(int id);
-    void unpin();
-
     rust_port_id register_port(rust_port *port);
     void release_port(rust_port_id id);
     rust_port *get_port_by_id(rust_port_id id);
@@ -193,11 +181,6 @@ rust_task : public kernel_owned<rust_task>, rust_cond
     // not at all safe.
     intptr_t get_ref_count() const { return ref_count; }
 
-    // FIXME: These functions only exist to get the tasking system off the
-    // ground. We should never be migrating shared boxes between tasks.
-    const type_desc *release_alloc(void *alloc);
-    void claim_alloc(void *alloc, const type_desc *tydesc);
-
     void notify(bool success);
 
     void *new_stack(size_t stk_sz, void *args_addr, size_t args_sz);
index 96d3d7bd34a2371e772f692f55dc9e018f3b0dc5..e7cc479f98f2d1523c38f179d34a9a663221e023 100644 (file)
@@ -1,15 +1,15 @@
 #include "rust_internal.h"
 
-rust_task_list::rust_task_list (rust_scheduler *sched, const char* name) :
-    sched(sched), name(name) {
+rust_task_list::rust_task_list (rust_task_thread *thread, const char* name) :
+    thread(thread), name(name) {
 }
 
 void
 rust_task_list::delete_all() {
-    DLOG(sched, task, "deleting all %s tasks", name);
+    DLOG(thread, task, "deleting all %s tasks", name);
     while (is_empty() == false) {
         rust_task *task = pop_value();
-        DLOG(sched, task, "deleting task " PTR, task);
+        DLOG(thread, task, "deleting task " PTR, task);
         delete task;
     }
 }
index 0991b32eed85ff76f34b40fc9271c72cf405e148..864cd3cdd57c0f0e8503203fc34f1a723e6d1c6f 100644 (file)
@@ -8,9 +8,9 @@
 class rust_task_list : public indexed_list<rust_task>,
                        public kernel_owned<rust_task_list> {
 public:
-    rust_scheduler *sched;
+    rust_task_thread *thread;
     const char* name;
-    rust_task_list (rust_scheduler *sched, const char* name);
+    rust_task_list (rust_task_thread *thread, const char* name);
     void delete_all();
 };
 
diff --git a/src/rt/rust_task_thread.cpp b/src/rt/rust_task_thread.cpp
new file mode 100644 (file)
index 0000000..a3bf729
--- /dev/null
@@ -0,0 +1,366 @@
+
+#include <stdarg.h>
+#include <cassert>
+#include <pthread.h>
+#include "rust_internal.h"
+#include "rust_util.h"
+#include "globals.h"
+#include "rust_scheduler.h"
+
+#ifndef _WIN32
+pthread_key_t rust_task_thread::task_key;
+#else
+DWORD rust_task_thread::task_key;
+#endif
+
+bool rust_task_thread::tls_initialized = false;
+
+rust_task_thread::rust_task_thread(rust_scheduler *sched,
+                                   rust_srv *srv,
+                                   int id) :
+    ref_count(1),
+    _log(srv, this),
+    log_lvl(log_debug),
+    srv(srv),
+    // TODO: calculate a per scheduler name.
+    name("main"),
+    newborn_tasks(this, "newborn"),
+    running_tasks(this, "running"),
+    blocked_tasks(this, "blocked"),
+    dead_tasks(this, "dead"),
+    cache(this),
+    kernel(sched->kernel),
+    sched(sched),
+    id(id),
+    min_stack_size(kernel->env->min_stack_size),
+    env(kernel->env),
+    should_exit(false)
+{
+    LOGPTR(this, "new dom", (uintptr_t)this);
+    isaac_init(kernel, &rctx);
+#ifndef __WIN32__
+    pthread_attr_init(&attr);
+    pthread_attr_setstacksize(&attr, 1024 * 1024);
+    pthread_attr_setdetachstate(&attr, true);
+#endif
+
+    if (!tls_initialized)
+        init_tls();
+}
+
+rust_task_thread::~rust_task_thread() {
+    DLOG(this, dom, "~rust_task_thread %s @0x%" PRIxPTR, name, (uintptr_t)this);
+
+    newborn_tasks.delete_all();
+    running_tasks.delete_all();
+    blocked_tasks.delete_all();
+    dead_tasks.delete_all();
+#ifndef __WIN32__
+    pthread_attr_destroy(&attr);
+#endif
+}
+
+void
+rust_task_thread::activate(rust_task *task) {
+    task->ctx.next = &c_context;
+    DLOG(this, task, "descheduling...");
+    lock.unlock();
+    task->ctx.swap(c_context);
+    lock.lock();
+    DLOG(this, task, "task has returned");
+}
+
+void
+rust_task_thread::log(rust_task* task, uint32_t level, char const *fmt, ...) {
+    char buf[BUF_BYTES];
+    va_list args;
+    va_start(args, fmt);
+    vsnprintf(buf, sizeof(buf), fmt, args);
+    _log.trace_ln(task, level, buf);
+    va_end(args);
+}
+
+void
+rust_task_thread::fail() {
+    log(NULL, log_err, "domain %s @0x%" PRIxPTR " root task failed",
+        name, this);
+    kernel->fail();
+}
+
+void
+rust_task_thread::kill_all_tasks() {
+    I(this, !lock.lock_held_by_current_thread());
+    scoped_lock with(lock);
+
+    for (size_t i = 0; i < running_tasks.length(); i++) {
+        // We don't want the failure of these tasks to propagate back
+        // to the kernel again since we're already failing everything
+        running_tasks[i]->unsupervise();
+        running_tasks[i]->kill();
+    }
+
+    for (size_t i = 0; i < blocked_tasks.length(); i++) {
+        blocked_tasks[i]->unsupervise();
+        blocked_tasks[i]->kill();
+    }
+}
+
+size_t
+rust_task_thread::number_of_live_tasks() {
+    return running_tasks.length() + blocked_tasks.length();
+}
+
+/**
+ * Delete any dead tasks.
+ */
+void
+rust_task_thread::reap_dead_tasks() {
+    I(this, lock.lock_held_by_current_thread());
+    if (dead_tasks.length() == 0) {
+        return;
+    }
+
+    // First make a copy of the dead_task list with the lock held
+    size_t dead_tasks_len = dead_tasks.length();
+    rust_task **dead_tasks_copy = (rust_task**)
+        srv->malloc(sizeof(rust_task*) * dead_tasks_len);
+    for (size_t i = 0; i < dead_tasks_len; ++i) {
+        dead_tasks_copy[i] = dead_tasks.pop_value();
+    }
+
+    // Now unlock again because we have to actually free the dead tasks,
+    // and that may end up wanting to lock the kernel lock. We have
+    // a kernel lock -> scheduler lock locking order that we need
+    // to maintain.
+    lock.unlock();
+
+    for (size_t i = 0; i < dead_tasks_len; ++i) {
+        rust_task *task = dead_tasks_copy[i];
+        if (task) {
+            kernel->release_task_id(task->user.id);
+            task->deref();
+        }
+    }
+    srv->free(dead_tasks_copy);
+
+    lock.lock();
+}
+
+/**
+ * Schedules a running task for execution. Only running tasks can be
+ * activated.  Blocked tasks have to be unblocked before they can be
+ * activated.
+ *
+ * Returns NULL if no tasks can be scheduled.
+ */
+rust_task *
+rust_task_thread::schedule_task() {
+    I(this, this);
+    // FIXME: in the face of failing tasks, this is not always right.
+    // I(this, n_live_tasks() > 0);
+    if (running_tasks.length() > 0) {
+        size_t k = isaac_rand(&rctx);
+        // Look around for a runnable task, starting at k.
+        for(size_t j = 0; j < running_tasks.length(); ++j) {
+            size_t  i = (j + k) % running_tasks.length();
+            return (rust_task *)running_tasks[i];
+        }
+    }
+    return NULL;
+}
+
+void
+rust_task_thread::log_state() {
+    if (log_rt_task < log_debug) return;
+
+    if (!running_tasks.is_empty()) {
+        log(NULL, log_debug, "running tasks:");
+        for (size_t i = 0; i < running_tasks.length(); i++) {
+            log(NULL, log_debug, "\t task: %s @0x%" PRIxPTR,
+                running_tasks[i]->name,
+                running_tasks[i]);
+        }
+    }
+
+    if (!blocked_tasks.is_empty()) {
+        log(NULL, log_debug, "blocked tasks:");
+        for (size_t i = 0; i < blocked_tasks.length(); i++) {
+            log(NULL, log_debug, "\t task: %s @0x%" PRIxPTR ", blocked on: 0x%"
+                PRIxPTR " '%s'",
+                blocked_tasks[i]->name, blocked_tasks[i],
+                blocked_tasks[i]->cond, blocked_tasks[i]->cond_name);
+        }
+    }
+
+    if (!dead_tasks.is_empty()) {
+        log(NULL, log_debug, "dead tasks:");
+        for (size_t i = 0; i < dead_tasks.length(); i++) {
+            log(NULL, log_debug, "\t task: %s 0x%" PRIxPTR,
+                dead_tasks[i]->name, dead_tasks[i]);
+        }
+    }
+}
+/**
+ * Starts the main scheduler loop which performs task scheduling for this
+ * domain.
+ *
+ * Returns once no more tasks can be scheduled and all task ref_counts
+ * drop to zero.
+ */
+void
+rust_task_thread::start_main_loop() {
+    lock.lock();
+
+    DLOG(this, dom, "started domain loop %d", id);
+
+    while (!should_exit) {
+        DLOG(this, dom, "worker %d, number_of_live_tasks = %d",
+             id, number_of_live_tasks());
+
+        rust_task *scheduled_task = schedule_task();
+
+        if (scheduled_task == NULL) {
+            log_state();
+            DLOG(this, task,
+                 "all tasks are blocked, scheduler id %d yielding ...",
+                 id);
+            lock.wait();
+            reap_dead_tasks();
+            DLOG(this, task,
+                 "scheduler %d resuming ...", id);
+            continue;
+        }
+
+        I(this, scheduled_task->running());
+
+        DLOG(this, task,
+             "activating task %s 0x%" PRIxPTR
+             ", sp=0x%" PRIxPTR
+             ", state: %s",
+             scheduled_task->name,
+             (uintptr_t)scheduled_task,
+             scheduled_task->user.rust_sp,
+             scheduled_task->state->name);
+
+        place_task_in_tls(scheduled_task);
+
+        DLOG(this, task,
+             "Running task %p on worker %d",
+             scheduled_task, id);
+        activate(scheduled_task);
+
+        DLOG(this, task,
+             "returned from task %s @0x%" PRIxPTR
+             " in state '%s', sp=0x%x, worker id=%d" PRIxPTR,
+             scheduled_task->name,
+             (uintptr_t)scheduled_task,
+             scheduled_task->state->name,
+             scheduled_task->user.rust_sp,
+             id);
+
+        reap_dead_tasks();
+    }
+
+    A(this, newborn_tasks.is_empty(), "Should have no newborn tasks");
+    A(this, running_tasks.is_empty(), "Should have no running tasks");
+    A(this, blocked_tasks.is_empty(), "Should have no blocked tasks");
+    A(this, dead_tasks.is_empty(), "Should have no dead tasks");
+
+    DLOG(this, dom, "finished main-loop %d", id);
+
+    lock.unlock();
+}
+
+rust_crate_cache *
+rust_task_thread::get_cache() {
+    return &cache;
+}
+
+rust_task_id
+rust_task_thread::create_task(rust_task *spawner, const char *name,
+                            size_t init_stack_sz) {
+    rust_task *task =
+        new (this->kernel, "rust_task")
+        rust_task (this, &newborn_tasks, spawner, name, init_stack_sz);
+    DLOG(this, task, "created task: " PTR ", spawner: %s, name: %s",
+                        task, spawner ? spawner->name : "null", name);
+
+    {
+        scoped_lock with(lock);
+        newborn_tasks.append(task);
+    }
+
+    kernel->register_task(task);
+    return task->user.id;
+}
+
+void rust_task_thread::run() {
+    this->start_main_loop();
+}
+
+#ifndef _WIN32
+void
+rust_task_thread::init_tls() {
+    int result = pthread_key_create(&task_key, NULL);
+    assert(!result && "Couldn't create the TLS key!");
+    tls_initialized = true;
+}
+
+void
+rust_task_thread::place_task_in_tls(rust_task *task) {
+    int result = pthread_setspecific(task_key, task);
+    assert(!result && "Couldn't place the task in TLS!");
+    task->record_stack_limit();
+}
+
+rust_task *
+rust_task_thread::get_task() {
+    if (!tls_initialized)
+        return NULL;
+    rust_task *task = reinterpret_cast<rust_task *>
+        (pthread_getspecific(task_key));
+    assert(task && "Couldn't get the task from TLS!");
+    return task;
+}
+#else
+void
+rust_task_thread::init_tls() {
+    task_key = TlsAlloc();
+    assert(task_key != TLS_OUT_OF_INDEXES && "Couldn't create the TLS key!");
+    tls_initialized = true;
+}
+
+void
+rust_task_thread::place_task_in_tls(rust_task *task) {
+    BOOL result = TlsSetValue(task_key, task);
+    assert(result && "Couldn't place the task in TLS!");
+    task->record_stack_limit();
+}
+
+rust_task *
+rust_task_thread::get_task() {
+    if (!tls_initialized)
+        return NULL;
+    rust_task *task = reinterpret_cast<rust_task *>(TlsGetValue(task_key));
+    assert(task && "Couldn't get the task from TLS!");
+    return task;
+}
+#endif
+
+void
+rust_task_thread::exit() {
+    A(this, !lock.lock_held_by_current_thread(), "Shouldn't have lock");
+    scoped_lock with(lock);
+    should_exit = true;
+    lock.signal();
+}
+
+//
+// Local Variables:
+// mode: C++
+// fill-column: 70;
+// indent-tabs-mode: nil
+// c-basic-offset: 4
+// buffer-file-coding-system: utf-8-unix
+// End:
+//
diff --git a/src/rt/rust_task_thread.h b/src/rt/rust_task_thread.h
new file mode 100644 (file)
index 0000000..e8fb70f
--- /dev/null
@@ -0,0 +1,145 @@
+#ifndef RUST_TASK_THREAD_H
+#define RUST_TASK_THREAD_H
+
+#include "context.h"
+
+#ifndef _WIN32
+#include <pthread.h>
+#else
+#include <windows.h>
+#endif
+
+struct rust_task_thread;
+
+struct rust_hashable_dict {
+    UT_hash_handle hh;
+    void* fields[0];
+};
+
+class rust_crate_cache {
+public:
+    type_desc *get_type_desc(size_t size,
+                             size_t align,
+                             size_t n_descs,
+                             type_desc const **descs,
+                             uintptr_t n_obj_params);
+    void** get_dict(size_t n_fields, void** dict);
+
+private:
+
+    type_desc *type_descs;
+    rust_hashable_dict *dicts;
+
+public:
+
+    rust_task_thread *thread;
+    size_t idx;
+
+    rust_crate_cache(rust_task_thread *thread);
+    ~rust_crate_cache();
+    void flush();
+};
+
+struct rust_task_thread : public kernel_owned<rust_task_thread>,
+                        rust_thread
+{
+    RUST_REFCOUNTED(rust_task_thread)
+
+    // Fields known only by the runtime:
+    rust_log _log;
+
+    // NB: this is used to filter *runtime-originating* debug
+    // logging, on a per-scheduler basis. It's not likely what
+    // you want to expose to the user in terms of per-task
+    // or per-module logging control. By default all schedulers
+    // are set to debug-level logging here, and filtered by
+    // runtime category using the pseudo-modules ::rt::foo.
+    uint32_t log_lvl;
+
+    rust_srv *srv;
+    const char *const name;
+
+    rust_task_list newborn_tasks;
+    rust_task_list running_tasks;
+    rust_task_list blocked_tasks;
+    rust_task_list dead_tasks;
+
+    rust_crate_cache cache;
+
+    randctx rctx;
+
+    rust_kernel *kernel;
+    rust_scheduler *sched;
+    int32_t list_index;
+
+    const int id;
+
+    lock_and_signal lock;
+    size_t min_stack_size;
+
+#ifndef __WIN32__
+    pthread_attr_t attr;
+    static pthread_key_t task_key;
+#else
+    static DWORD task_key;
+#endif
+
+    static bool tls_initialized;
+
+    rust_env *env;
+    context c_context;
+
+    bool should_exit;
+
+    // Only a pointer to 'name' is kept, so it must live as long as this
+    // domain.
+    rust_task_thread(rust_scheduler *sched, rust_srv *srv, int id);
+    ~rust_task_thread();
+    void activate(rust_task *task);
+    void log(rust_task *task, uint32_t level, char const *fmt, ...);
+    rust_log & get_log();
+    void fail();
+
+    rust_crate_cache *get_cache();
+    size_t number_of_live_tasks();
+
+    void reap_dead_tasks();
+    rust_task *schedule_task();
+
+    void start_main_loop();
+
+    void log_state();
+
+    void kill_all_tasks();
+
+    rust_task_id create_task(rust_task *spawner, const char *name,
+                             size_t init_stack_sz);
+
+    virtual void run();
+
+    void init_tls();
+    void place_task_in_tls(rust_task *task);
+
+    static rust_task *get_task();
+
+    // Tells the scheduler to exit it's scheduling loop and thread
+    void exit();
+};
+
+inline rust_log &
+rust_task_thread::get_log() {
+    return _log;
+}
+
+//
+// Local Variables:
+// mode: C++
+// fill-column: 78;
+// indent-tabs-mode: nil
+// c-basic-offset: 4
+// buffer-file-coding-system: utf-8-unix
+// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
+// End:
+//
+
+#endif /* RUST_TASK_THREAD_H */
diff --git a/src/rt/rust_timer.cpp b/src/rt/rust_timer.cpp
deleted file mode 100644 (file)
index ffa9876..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-#include "rust_internal.h"
-#include "vg/valgrind.h"
-
-// The mechanism in this file is very crude; every domain (thread) spawns its
-// own secondary timer thread, and that timer thread *never idles*. It
-// sleep-loops interrupting the domain.
-//
-// This will need replacement, particularly in order to achieve an actual
-// state of idling when we're waiting on the outside world.  Though that might
-// be as simple as making a secondary waitable start/stop-timer signalling
-// system between the domain and its timer thread. We'll see.
-//
-// On the other hand, we don't presently have the ability to idle domains *at
-// all*, and without the timer thread we're unable to otherwise preempt rust
-// tasks. So ... one step at a time.
-//
-// The implementation here is "lockless" in the sense that it only involves
-// one-directional signaling of one-shot events, so the event initiator just
-// writes a nonzero word to a prederermined location and waits for the
-// receiver to see it show up in their memory.
-
-#if defined(__WIN32__)
-static DWORD WINAPI
-#elif defined(__GNUC__)
-static void *
-#else
-#error "Platform not supported"
-#endif
-timer_loop(void *ptr) {
-    // We were handed the rust_timer that owns us.
-    rust_timer *timer = (rust_timer *)ptr;
-    rust_scheduler *sched = timer->sched;
-    DLOG(sched, timer, "in timer 0x%" PRIxPTR, (uintptr_t)timer);
-    size_t ms = TIME_SLICE_IN_MS;
-
-    while (!timer->exit_flag) {
-#if defined(__WIN32__)
-        Sleep(ms);
-#else
-        usleep(ms * 1000);
-#endif
-        DLOG(sched, timer, "timer 0x%" PRIxPTR
-        " interrupting schedain 0x%" PRIxPTR, (uintptr_t) timer,
-                 (uintptr_t) sched);
-        sched->interrupt_flag = 1;
-    }
-#if defined(__WIN32__)
-    ExitThread(0);
-#else
-    pthread_exit(NULL);
-#endif
-    return 0;
-}
-
-rust_timer::rust_timer(rust_scheduler *sched) :
-    sched(sched), exit_flag(0) {
-    DLOG(sched, timer, "creating timer for domain 0x%" PRIxPTR, sched);
-#if defined(__WIN32__)
-    thread = CreateThread(NULL, 0, timer_loop, this, 0, NULL);
-    sched->kernel->win32_require("CreateThread", thread != NULL);
-    if (RUNNING_ON_VALGRIND)
-        Sleep(10);
-#else
-    pthread_attr_init(&attr);
-    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
-    pthread_create(&thread, &attr, timer_loop, (void *)this);
-#endif
-}
-
-rust_timer::~rust_timer() {
-    exit_flag = 1;
-#if defined(__WIN32__)
-    sched->kernel->win32_require("WaitForSingleObject",
-                               WaitForSingleObject(thread, INFINITE) ==
-                               WAIT_OBJECT_0);
-#else
-    pthread_join(thread, NULL);
-#endif
-}
-
-//
-// Local Variables:
-// mode: C++
-// fill-column: 78;
-// indent-tabs-mode: nil
-// c-basic-offset: 4
-// buffer-file-coding-system: utf-8-unix
-// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
-// End:
-//
index 65299a7d24453181b1df005047100232dcd21126..6c666fb8189bbc20cbcc3522cb72a303c9f8b29c 100644 (file)
@@ -7,15 +7,28 @@
  */
 
 #include "rust_cc.h"
-#include "rust_gc.h"
 #include "rust_internal.h"
-#include "rust_scheduler.h"
+#include "rust_task_thread.h"
 #include "rust_unwind.h"
 #include "rust_upcall.h"
 #include "rust_util.h"
 #include <stdint.h>
 
 
+#ifdef __GNUC__
+#define LOG_UPCALL_ENTRY(task)                            \
+    LOG(task, upcall,                                     \
+        "> UPCALL %s - task: %s 0x%" PRIxPTR              \
+        " retpc: x%" PRIxPTR,                             \
+        __FUNCTION__,                                     \
+        (task)->name, (task),                             \
+        __builtin_return_address(0));
+#else
+#define LOG_UPCALL_ENTRY(task)                            \
+    LOG(task, upcall, "> UPCALL task: %s @x%" PRIxPTR,    \
+        (task)->name, (task));
+#endif
+
 // This is called to ensure we've set up our rust stacks
 // correctly. Strategically placed at entry to upcalls because they begin on
 // the rust stack and happen frequently enough to catch most stack changes,
@@ -33,9 +46,9 @@ static void check_stack_alignment() { }
 inline void
 call_upcall_on_c_stack(void *args, void *fn_ptr) {
     check_stack_alignment();
-    rust_task *task = rust_scheduler::get_task();
-    rust_scheduler *sched = task->sched;
-    sched->c_context.call_shim_on_c_stack(args, fn_ptr);
+    rust_task *task = rust_task_thread::get_task();
+    rust_task_thread *thread = task->thread;
+    thread->c_context.call_shim_on_c_stack(args, fn_ptr);
 }
 
 extern "C" void record_sp(void *limit);
@@ -49,21 +62,21 @@ extern "C" void record_sp(void *limit);
  */
 extern "C" CDECL void
 upcall_call_shim_on_c_stack(void *args, void *fn_ptr) {
-    rust_task *task = rust_scheduler::get_task();
+    rust_task *task = rust_task_thread::get_task();
 
     // FIXME (1226) - The shim functions generated by rustc contain the
     // morestack prologue, so we need to let them know they have enough
     // stack.
     record_sp(0);
 
-    rust_scheduler *sched = task->sched;
+    rust_task_thread *thread = task->thread;
     try {
-        sched->c_context.call_shim_on_c_stack(args, fn_ptr);
+        thread->c_context.call_shim_on_c_stack(args, fn_ptr);
     } catch (...) {
-        A(sched, false, "Native code threw an exception");
+        A(thread, false, "Native code threw an exception");
     }
 
-    task = rust_scheduler::get_task();
+    task = rust_task_thread::get_task();
     task->record_stack_limit();
 }
 
@@ -77,7 +90,7 @@ struct s_fail_args {
 
 extern "C" CDECL void
 upcall_s_fail(s_fail_args *args) {
-    rust_task *task = rust_scheduler::get_task();
+    rust_task *task = rust_task_thread::get_task();
     LOG_UPCALL_ENTRY(task);
     LOG_ERR(task, upcall, "upcall fail '%s', %s:%" PRIdPTR, 
             args->expr, args->file, args->line);
@@ -98,40 +111,34 @@ upcall_fail(char const *expr,
 
 struct s_malloc_args {
     uintptr_t retval;
-    size_t nbytes;
     type_desc *td;
 };
 
 extern "C" CDECL void
 upcall_s_malloc(s_malloc_args *args) {
-    rust_task *task = rust_scheduler::get_task();
+    rust_task *task = rust_task_thread::get_task();
     LOG_UPCALL_ENTRY(task);
 
-    LOG(task, mem,
-        "upcall malloc(%" PRIdPTR ", 0x%" PRIxPTR ")",
-        args->nbytes, args->td);
+    LOG(task, mem, "upcall malloc(0x%" PRIxPTR ")", args->td);
 
-    gc::maybe_gc(task);
     cc::maybe_cc(task);
 
-    // TODO: Maybe use dladdr here to find a more useful name for the
-    // type_desc.
-
-    void *p = task->malloc(args->nbytes, "tdesc", args->td);
-    memset(p, '\0', args->nbytes);
+    // FIXME--does this have to be calloc?
+    rust_opaque_box *box = task->boxed.calloc(args->td);
+    void *body = box_body(box);
 
-    task->local_allocs[p] = args->td;
-    debug::maybe_track_origin(task, p);
+    debug::maybe_track_origin(task, box);
 
     LOG(task, mem,
-        "upcall malloc(%" PRIdPTR ", 0x%" PRIxPTR ") = 0x%" PRIxPTR,
-        args->nbytes, args->td, (uintptr_t)p);
-    args->retval = (uintptr_t) p;
+        "upcall malloc(0x%" PRIxPTR ") = box 0x%" PRIxPTR
+        " with body 0x%" PRIxPTR,
+        args->td, (uintptr_t)box, (uintptr_t)body);
+    args->retval = (uintptr_t) box;
 }
 
 extern "C" CDECL uintptr_t
-upcall_malloc(size_t nbytes, type_desc *td) {
-    s_malloc_args args = {0, nbytes, td};
+upcall_malloc(type_desc *td) {
+    s_malloc_args args = {0, td};
     UPCALL_SWITCH_STACK(&args, upcall_s_malloc);
     return args.retval;
 }
@@ -142,31 +149,45 @@ upcall_malloc(size_t nbytes, type_desc *td) {
 
 struct s_free_args {
     void *ptr;
-    uintptr_t is_gc;
 };
 
 extern "C" CDECL void
 upcall_s_free(s_free_args *args) {
-    rust_task *task = rust_scheduler::get_task();
+    rust_task *task = rust_task_thread::get_task();
     LOG_UPCALL_ENTRY(task);
 
-    rust_scheduler *sched = task->sched;
-    DLOG(sched, mem,
+    rust_task_thread *thread = task->thread;
+    DLOG(thread, mem,
              "upcall free(0x%" PRIxPTR ", is_gc=%" PRIdPTR ")",
-             (uintptr_t)args->ptr, args->is_gc);
+             (uintptr_t)args->ptr);
 
-    task->local_allocs.erase(args->ptr);
     debug::maybe_untrack_origin(task, args->ptr);
 
-    task->free(args->ptr, (bool) args->is_gc);
+    rust_opaque_box *box = (rust_opaque_box*) args->ptr;
+    task->boxed.free(box);
 }
 
 extern "C" CDECL void
-upcall_free(void* ptr, uintptr_t is_gc) {
-    s_free_args args = {ptr, is_gc};
+upcall_free(void* ptr) {
+    s_free_args args = {ptr};
     UPCALL_SWITCH_STACK(&args, upcall_s_free);
 }
 
+/**********************************************************************
+ * Sanity checks on boxes, insert when debugging possible
+ * use-after-free bugs.  See maybe_validate_box() in trans.rs.
+ */
+
+extern "C" CDECL void
+upcall_validate_box(rust_opaque_box* ptr) {
+    if (ptr) {
+        assert(ptr->ref_count > 0);
+        assert(ptr->td != NULL);
+        assert(ptr->td->align <= 8);
+        assert(ptr->td->size <= 4096); // might not really be true...
+    }
+}
+
 /**********************************************************************
  * Allocate an object in the exchange heap.
  */
@@ -179,7 +200,7 @@ struct s_shared_malloc_args {
 
 extern "C" CDECL void
 upcall_s_shared_malloc(s_shared_malloc_args *args) {
-    rust_task *task = rust_scheduler::get_task();
+    rust_task *task = rust_task_thread::get_task();
     LOG_UPCALL_ENTRY(task);
 
     LOG(task, mem,
@@ -211,11 +232,11 @@ struct s_shared_free_args {
 
 extern "C" CDECL void
 upcall_s_shared_free(s_shared_free_args *args) {
-    rust_task *task = rust_scheduler::get_task();
+    rust_task *task = rust_task_thread::get_task();
     LOG_UPCALL_ENTRY(task);
 
-    rust_scheduler *sched = task->sched;
-    DLOG(sched, mem,
+    rust_task_thread *thread = task->thread;
+    DLOG(thread, mem,
              "upcall shared_free(0x%" PRIxPTR")",
              (uintptr_t)args->ptr);
     task->kernel->free(args->ptr);
@@ -241,7 +262,7 @@ struct s_create_shared_type_desc_args {
 
 void upcall_s_create_shared_type_desc(s_create_shared_type_desc_args *args)
 {
-    rust_task *task = rust_scheduler::get_task();
+    rust_task *task = rust_task_thread::get_task();
     LOG_UPCALL_ENTRY(task);
 
     // Copy the main part of the type descriptor:
@@ -280,7 +301,7 @@ upcall_create_shared_type_desc(type_desc *td) {
 
 void upcall_s_free_shared_type_desc(type_desc *td)
 { // n.b.: invoked from rust_cc.cpp as well as generated code
-    rust_task *task = rust_scheduler::get_task();
+    rust_task *task = rust_task_thread::get_task();
     LOG_UPCALL_ENTRY(task);
 
     if (td) {
@@ -316,7 +337,7 @@ struct s_get_type_desc_args {
 
 extern "C" CDECL void
 upcall_s_get_type_desc(s_get_type_desc_args *args) {
-    rust_task *task = rust_scheduler::get_task();
+    rust_task *task = rust_task_thread::get_task();
     LOG_UPCALL_ENTRY(task);
 
     LOG(task, cache, "upcall get_type_desc with size=%" PRIdPTR
@@ -354,7 +375,7 @@ struct s_intern_dict_args {
 
 extern "C" CDECL void
 upcall_s_intern_dict(s_intern_dict_args *args) {
-    rust_task *task = rust_scheduler::get_task();
+    rust_task *task = rust_task_thread::get_task();
     LOG_UPCALL_ENTRY(task);
     rust_crate_cache *cache = task->get_crate_cache();
     args->res = cache->get_dict(args->n_fields, args->dict);
@@ -376,7 +397,7 @@ struct s_vec_grow_args {
 
 extern "C" CDECL void
 upcall_s_vec_grow(s_vec_grow_args *args) {
-    rust_task *task = rust_scheduler::get_task();
+    rust_task *task = rust_task_thread::get_task();
     LOG_UPCALL_ENTRY(task);
     reserve_vec(task, args->vp, args->new_sz);
     (*args->vp)->fill = args->new_sz;
@@ -417,7 +438,7 @@ struct s_vec_push_args {
 
 extern "C" CDECL void
 upcall_s_vec_push(s_vec_push_args *args) {
-    rust_task *task = rust_scheduler::get_task();
+    rust_task *task = rust_task_thread::get_task();
     LOG_UPCALL_ENTRY(task);
     size_t new_sz = (*args->vp)->fill + args->elt_ty->size;
     reserve_vec(task, args->vp, new_sz);
@@ -435,7 +456,7 @@ upcall_vec_push(rust_vec** vp, type_desc* elt_ty, void* elt) {
     upcall_s_vec_push(&args);
 
     // Do the stack check to make sure this op, on the Rust stack, is behaving
-    rust_task *task = rust_scheduler::get_task();
+    rust_task *task = rust_task_thread::get_task();
     task->check_stack_canary();
 }
 
@@ -450,7 +471,7 @@ struct s_dynastack_mark_args {
 
 extern "C" CDECL void
 upcall_s_dynastack_mark(s_dynastack_mark_args *args) {
-    args->retval = rust_scheduler::get_task()->dynastack.mark();
+    args->retval = rust_task_thread::get_task()->dynastack.mark();
 }
 
 extern "C" CDECL void *
@@ -475,7 +496,7 @@ extern "C" CDECL void
 upcall_s_dynastack_alloc(s_dynastack_alloc_args *args) {
     size_t sz = args->sz;
     args->retval = sz ?
-        rust_scheduler::get_task()->dynastack.alloc(sz, NULL) : NULL;
+        rust_task_thread::get_task()->dynastack.alloc(sz, NULL) : NULL;
 }
 
 extern "C" CDECL void *
@@ -501,7 +522,7 @@ upcall_s_dynastack_alloc_2(s_dynastack_alloc_2_args *args) {
     size_t sz = args->sz;
     type_desc *ty = args->ty;
     args->retval = sz ?
-        rust_scheduler::get_task()->dynastack.alloc(sz, ty) : NULL;
+        rust_task_thread::get_task()->dynastack.alloc(sz, ty) : NULL;
 }
 
 extern "C" CDECL void *
@@ -517,7 +538,7 @@ struct s_dynastack_free_args {
 
 extern "C" CDECL void
 upcall_s_dynastack_free(s_dynastack_free_args *args) {
-    return rust_scheduler::get_task()->dynastack.free(args->ptr);
+    return rust_task_thread::get_task()->dynastack.free(args->ptr);
 }
 
 /** Frees space in the dynamic stack. */
@@ -566,7 +587,7 @@ upcall_rust_personality(int version,
     s_rust_personality_args args = {(_Unwind_Reason_Code)0,
                                     version, actions, exception_class,
                                     ue_header, context};
-    rust_task *task = rust_scheduler::get_task();
+    rust_task *task = rust_task_thread::get_task();
 
     // The personality function is run on the stack of the
     // last function that threw or landed, which is going
@@ -638,7 +659,7 @@ struct s_new_stack_args {
 
 extern "C" CDECL void
 upcall_s_new_stack(struct s_new_stack_args *args) {
-    rust_task *task = rust_scheduler::get_task();
+    rust_task *task = rust_task_thread::get_task();
     args->result = task->new_stack(args->stk_sz,
                                    args->args_addr,
                                    args->args_sz);
@@ -653,7 +674,7 @@ upcall_new_stack(size_t stk_sz, void *args_addr, size_t args_sz) {
 
 extern "C" CDECL void
 upcall_s_del_stack() {
-    rust_task *task = rust_scheduler::get_task();
+    rust_task *task = rust_task_thread::get_task();
     task->del_stack();
 }
 
@@ -668,7 +689,7 @@ upcall_del_stack() {
 // needs to acquire the value of the stack pointer
 extern "C" CDECL void
 upcall_reset_stack_limit() {
-    rust_task *task = rust_scheduler::get_task();
+    rust_task *task = rust_task_thread::get_task();
     task->reset_stack_limit();
 }
 
index e5ee5bb694823aef7acd461ac153f829b1bf57b1..46676497d6330f4e3ca35e7d3640a0504c0a93f4 100644 (file)
@@ -1,17 +1,7 @@
 #pragma once
 
-#ifdef __GNUC__
-#define LOG_UPCALL_ENTRY(task)                            \
-    LOG(task, upcall,                                     \
-        "> UPCALL %s - task: %s 0x%" PRIxPTR              \
-        " retpc: x%" PRIxPTR,                             \
-        __FUNCTION__,                                     \
-        (task)->name, (task),                             \
-        __builtin_return_address(0));
-#else
-#define LOG_UPCALL_ENTRY(task)                            \
-    LOG(task, upcall, "> UPCALL task: %s @x%" PRIxPTR,    \
-        (task)->name, (task));
-#endif
+// Upcalls used from C code on occasion:
 
+extern "C" CDECL void upcall_shared_free(void* ptr);
+extern "C" CDECL void upcall_free_shared_type_desc(type_desc *td);
 
index 9b3b4c6f45dd11dfcc818e72c86ca007d810844b..07569db3ffa6da2293bb8186a3930ab5e7af8f7d 100644 (file)
@@ -13,24 +13,24 @@ ptr_vec<T>::ptr_vec(rust_task *task) :
     fill(0),
     data(new (task, "ptr_vec<T>") T*[alloc])
 {
-    I(task->sched, data);
-    DLOG(task->sched, mem, "new ptr_vec(data=0x%" PRIxPTR ") -> 0x%" PRIxPTR,
+    I(task->thread, data);
+    DLOG(task->thread, mem, "new ptr_vec(data=0x%" PRIxPTR ") -> 0x%" PRIxPTR,
          (uintptr_t)data, (uintptr_t)this);
 }
 
 template <typename T>
 ptr_vec<T>::~ptr_vec()
 {
-    I(task->sched, data);
-    DLOG(task->sched, mem, "~ptr_vec 0x%" PRIxPTR ", data=0x%" PRIxPTR,
+    I(task->thread, data);
+    DLOG(task->thread, mem, "~ptr_vec 0x%" PRIxPTR ", data=0x%" PRIxPTR,
          (uintptr_t)this, (uintptr_t)data);
-    I(task->sched, fill == 0);
+    I(task->thread, fill == 0);
     task->free(data);
 }
 
 template <typename T> T *&
 ptr_vec<T>::operator[](size_t offset) {
-    I(task->sched, data[offset]->idx == offset);
+    I(task->thread, data[offset]->idx == offset);
     return data[offset];
 }
 
@@ -38,14 +38,14 @@ template <typename T>
 void
 ptr_vec<T>::push(T *p)
 {
-    I(task->sched, data);
-    I(task->sched, fill <= alloc);
+    I(task->thread, data);
+    I(task->thread, fill <= alloc);
     if (fill == alloc) {
         alloc *= 2;
         data = (T **)task->realloc(data, alloc * sizeof(T*));
-        I(task->sched, data);
+        I(task->thread, data);
     }
-    I(task->sched, fill < alloc);
+    I(task->thread, fill < alloc);
     p->idx = fill;
     data[fill++] = p;
 }
@@ -68,13 +68,13 @@ template <typename T>
 void
 ptr_vec<T>::trim(size_t sz)
 {
-    I(task->sched, data);
+    I(task->thread, data);
     if (sz <= (alloc / 4) &&
         (alloc / 2) >= INIT_SIZE) {
         alloc /= 2;
-        I(task->sched, alloc >= fill);
+        I(task->thread, alloc >= fill);
         data = (T **)task->realloc(data, alloc * sizeof(T*));
-        I(task->sched, data);
+        I(task->thread, data);
     }
 }
 
@@ -83,9 +83,9 @@ void
 ptr_vec<T>::swap_delete(T *item)
 {
     /* Swap the endpoint into i and decr fill. */
-    I(task->sched, data);
-    I(task->sched, fill > 0);
-    I(task->sched, item->idx < fill);
+    I(task->thread, data);
+    I(task->thread, fill > 0);
+    I(task->thread, item->idx < fill);
     fill--;
     if (fill > 0) {
         T *subst = data[fill];
@@ -124,13 +124,12 @@ align_to(T size, size_t alignment) {
 
 // Initialization helper for ISAAC RNG
 
-template <typename sched_or_kernel>
-static inline void
-isaac_init(sched_or_kernel *sched, randctx *rctx)
+inline void
+isaac_init(rust_kernel *kernel, randctx *rctx)
 {
         memset(rctx, 0, sizeof(randctx));
 
-        char *rust_seed = sched->env->rust_seed;
+        char *rust_seed = kernel->env->rust_seed;
         if (rust_seed != NULL) {
             ub4 seed = (ub4) atoi(rust_seed);
             for (size_t i = 0; i < RANDSIZ; i ++) {
@@ -140,24 +139,24 @@ isaac_init(sched_or_kernel *sched, randctx *rctx)
         } else {
 #ifdef __WIN32__
             HCRYPTPROV hProv;
-            sched->win32_require
+            kernel->win32_require
                 (_T("CryptAcquireContext"),
                  CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL,
                                      CRYPT_VERIFYCONTEXT|CRYPT_SILENT));
-            sched->win32_require
+            kernel->win32_require
                 (_T("CryptGenRandom"),
                  CryptGenRandom(hProv, sizeof(rctx->randrsl),
                                 (BYTE*)(&rctx->randrsl)));
-            sched->win32_require
+            kernel->win32_require
                 (_T("CryptReleaseContext"),
                  CryptReleaseContext(hProv, 0));
 #else
             int fd = open("/dev/urandom", O_RDONLY);
-            I(sched, fd > 0);
-            I(sched,
+            I(kernel, fd > 0);
+            I(kernel,
               read(fd, (void*) &rctx->randrsl, sizeof(rctx->randrsl))
               == sizeof(rctx->randrsl));
-            I(sched, close(fd) == 0);
+            I(kernel, close(fd) == 0);
 #endif
         }
 
@@ -179,15 +178,17 @@ inline size_t vec_size(size_t elems) {
     return sizeof(rust_vec) + sizeof(T) * elems;
 }
 
-inline void reserve_vec(rust_task* task, rust_vec** vpp, size_t size) {
+inline void reserve_vec_exact(rust_task* task, rust_vec** vpp, size_t size) {
     if (size > (*vpp)->alloc) {
-        size_t new_alloc = next_power_of_two(size);
-        *vpp = (rust_vec*)task->kernel->realloc(*vpp, new_alloc +
-                                                sizeof(rust_vec));
-        (*vpp)->alloc = new_alloc;
+        *vpp = (rust_vec*)task->kernel->realloc(*vpp, size + sizeof(rust_vec));
+        (*vpp)->alloc = size;
     }
 }
 
+inline void reserve_vec(rust_task* task, rust_vec** vpp, size_t size) {
+    reserve_vec_exact(task, vpp, next_power_of_two(size));
+}
+
 typedef rust_vec rust_str;
 
 inline rust_str *
index 7f4b425e5ec8e1aadd4bd72b0ecbb477ab18fadb..7bd0b4fe55bd99c1d6aad741e7ed8641cb412762 100644 (file)
@@ -87,7 +87,7 @@ private:
 public:
 
     rust_uvtmp_thread() {
-       task = rust_scheduler::get_task();
+       task = rust_task_thread::get_task();
        stop_flag = false;
        loop = uv_loop_new();
        uv_idle_init(loop, &idle);
index 052f4a42779cd4405cec886ae21c03322d2ec73a..48736ef029b2376662d74ede5299c43ba9bb18a6 100644 (file)
@@ -9,7 +9,6 @@ debug_ptrcast
 debug_tag
 debug_tydesc
 debug_get_stk_seg
-do_gc
 drop_task
 get_port_id
 get_task_id
@@ -17,13 +16,10 @@ get_task_pointer
 get_time
 last_os_error
 leak
-migrate_alloc
 nano_time
 new_port
 new_task
-pin_task
 port_recv
-unpin_task
 rand_free
 rand_new
 rand_next
@@ -46,15 +42,15 @@ rust_run_program
 rust_set_exit_status
 rust_start
 rust_getcwd
+rust_task_yield
 rust_task_is_unwinding
-rust_task_sleep
 rust_get_task
-set_min_stack
 sched_threads
 shape_log_str
 squareroot
 start_task
 vec_reserve_shared
+str_reserve_shared
 vec_from_buf_shared
 unsupervise
 upcall_cmp_type
@@ -64,6 +60,7 @@ upcall_dynastack_free
 upcall_dynastack_mark
 upcall_fail
 upcall_free
+upcall_validate_box
 upcall_create_shared_type_desc
 upcall_free_shared_type_desc
 upcall_get_type_desc
@@ -99,4 +96,3 @@ rust_uvtmp_read_start
 rust_uvtmp_timer
 rust_uvtmp_delete_buf
 rust_uvtmp_get_req_id
-
index 3a1c702aac75a30ff6283337267356b99671fbe2..f9d40681a60a40fcffccd22ca3670e9c174740d2 100644 (file)
@@ -1,3 +1,4 @@
+#include <assert.h>
 #include "../globals.h"
 
 /*
 
 #include "lock_and_signal.h"
 
+// FIXME: This is not a portable way of specifying an invalid pthread_t
+#define INVALID_THREAD 0
+
+
 #if defined(__WIN32__)
 lock_and_signal::lock_and_signal()
-    : alive(true)
+    : _holding_thread(INVALID_THREAD)
 {
-    // FIXME: In order to match the behavior of pthread_cond_broadcast on
-    // Windows, we create manual reset events. This however breaks the
-    // behavior of pthread_cond_signal, fixing this is quite involved:
-    // refer to: http://www.cs.wustl.edu/~schmidt/win32-cv-1.html
-
-    _event = CreateEvent(NULL, TRUE, FALSE, NULL);
+    _event = CreateEvent(NULL, FALSE, FALSE, NULL);
     InitializeCriticalSection(&_cs);
 }
 
 #else
 lock_and_signal::lock_and_signal()
-    : _locked(false), alive(true)
+    : _holding_thread(INVALID_THREAD)
 {
     CHECKED(pthread_cond_init(&_cond, NULL));
     CHECKED(pthread_mutex_init(&_mutex, NULL));
@@ -38,7 +38,6 @@ lock_and_signal::~lock_and_signal() {
     CHECKED(pthread_cond_destroy(&_cond));
     CHECKED(pthread_mutex_destroy(&_mutex));
 #endif
-    alive = false;
 }
 
 void lock_and_signal::lock() {
@@ -49,11 +48,10 @@ void lock_and_signal::lock() {
     CHECKED(pthread_mutex_lock(&_mutex));
     _holding_thread = pthread_self();
 #endif
-    _locked = true;
 }
 
 void lock_and_signal::unlock() {
-    _locked = false;
+    _holding_thread = INVALID_THREAD;
 #if defined(__WIN32__)
     LeaveCriticalSection(&_cs);
 #else
@@ -65,50 +63,17 @@ void lock_and_signal::unlock() {
  * Wait indefinitely until condition is signaled.
  */
 void lock_and_signal::wait() {
-    timed_wait(0);
-}
-
-bool lock_and_signal::timed_wait(size_t timeout_in_ms) {
-    _locked = false;
-    bool rv = true;
+    assert(lock_held_by_current_thread());
+    _holding_thread = INVALID_THREAD;
 #if defined(__WIN32__)
     LeaveCriticalSection(&_cs);
-    DWORD timeout = timeout_in_ms == 0 ? INFINITE : timeout_in_ms;
-    rv = WaitForSingleObject(_event, timeout) != WAIT_TIMEOUT;
+    WaitForSingleObject(_event, INFINITE);
     EnterCriticalSection(&_cs);
     _holding_thread = GetCurrentThreadId();
 #else
-    if (timeout_in_ms == 0) {
-        CHECKED(pthread_cond_wait(&_cond, &_mutex));
-    } else {
-        timeval time_val;
-        gettimeofday(&time_val, NULL);
-        timespec time_spec;
-        time_spec.tv_sec = time_val.tv_sec + 0;
-        time_spec.tv_nsec = time_val.tv_usec * 1000 + timeout_in_ms * 1000000;
-        if(time_spec.tv_nsec >= 1000000000) {
-            time_spec.tv_sec++;
-            time_spec.tv_nsec -= 1000000000;
-        }
-        int cond_wait_status
-            = pthread_cond_timedwait(&_cond, &_mutex, &time_spec);
-        switch(cond_wait_status) {
-        case 0:
-            // successfully grabbed the lock.
-            break;
-        case ETIMEDOUT:
-            // Oops, we timed out.
-            rv = false;
-            break;
-        default:
-            // Error
-            CHECKED(cond_wait_status);
-        }
-    }
+    CHECKED(pthread_cond_wait(&_cond, &_mutex));
     _holding_thread = pthread_self();
 #endif
-    _locked = true;
-    return rv;
 }
 
 /**
@@ -122,23 +87,12 @@ void lock_and_signal::signal() {
 #endif
 }
 
-/**
- * Signal condition, and resume all waiting threads.
- */
-void lock_and_signal::signal_all() {
-#if defined(__WIN32__)
-    SetEvent(_event);
-#else
-    CHECKED(pthread_cond_broadcast(&_cond));
-#endif
-}
-
 bool lock_and_signal::lock_held_by_current_thread()
 {
 #if defined(__WIN32__)
-    return _locked && _holding_thread == GetCurrentThreadId();
+    return _holding_thread == GetCurrentThreadId();
 #else
-    return _locked && _holding_thread == pthread_self();
+    return pthread_equal(_holding_thread, pthread_self());
 #endif
 }
 
index 6e656017115d27cb1e0b1760246a235a8d41ba99..4fc629b9fac5131596d935c1a06892de89d06ff6 100644 (file)
@@ -13,9 +13,6 @@ class lock_and_signal {
 
     pthread_t _holding_thread;
 #endif
-    bool _locked;
-
-    bool alive;
 
 public:
     lock_and_signal();
@@ -24,9 +21,7 @@ public:
     void lock();
     void unlock();
     void wait();
-    bool timed_wait(size_t timeout_in_ns);
     void signal();
-    void signal_all();
 
     bool lock_held_by_current_thread();
 };
diff --git a/src/rt/test/rust_test_harness.cpp b/src/rt/test/rust_test_harness.cpp
deleted file mode 100644 (file)
index ec89da1..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-#include "../rust_internal.h"
-
-bool
-rust_test::run() {
-    return false;
-}
-
-const char *
-rust_test::name() {
-    return "untitled";
-}
-
-rust_test_suite::rust_test_suite() {
-    tests.append(new rust_domain_test());
-    tests.append(new rust_task_test(this));
-    tests.append(new rust_array_list_test());
-    tests.append(new rust_synchronized_indexed_list_test());
-}
-
-rust_test_suite::~rust_test_suite() {
-
-}
-
-bool
-rust_test_suite::run() {
-    bool pass = true;
-    for (size_t i = 0; i < tests.size(); i++) {
-        rust_test *test = tests[i];
-        printf("test: %s running ... \n", test->name());
-        timer timer;
-        bool result = tests[i]->run();
-        printf("test: %s %s %.2f ms\n", test->name(),
-               result ? "PASS" : "FAIL", timer.elapsed_ms());
-        if (result == false) {
-            pass = false;
-        }
-    }
-    return pass;
-}
-
diff --git a/src/rt/test/rust_test_harness.h b/src/rt/test/rust_test_harness.h
deleted file mode 100644 (file)
index 401015e..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef RUST_TEST_HARNESS_H
-#define RUST_TEST_HARNESS_H
-
-#define CHECK(x) if ((x) == false)                               \
-    { printf("condition: %s failed at file: %s, line: %d\n", #x, \
-             __FILE__, __LINE__ ); return false; }
-
-class rust_test {
-public:
-    virtual bool run();
-    virtual const char *name();
-};
-
-class rust_test_suite : public rust_test {
-public:
-    array_list<rust_test*> tests;
-    rust_test_suite();
-    virtual ~rust_test_suite();
-    bool run();
-};
-
-#endif /* RUST_TEST_HARNESS_H */
diff --git a/src/rt/test/rust_test_runtime.cpp b/src/rt/test/rust_test_runtime.cpp
deleted file mode 100644 (file)
index 815d55a..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-#include "rust_test_runtime.h"
-
-rust_test_runtime::rust_test_runtime() {
-}
-
-rust_test_runtime::~rust_test_runtime() {
-}
-
-#define DOMAINS 32
-#define TASKS 32
-
-void
-rust_domain_test::worker::run() {
-    for (int i = 0; i < TASKS; i++) {
-        kernel->create_task(NULL, "child");
-    }
-    //sync::sleep(rand(&handle->rctx) % 1000);
-}
-
-bool
-rust_domain_test::run() {
-    rust_env env;
-    rust_srv srv(&env);
-    rust_kernel kernel(&srv, 1);
-
-    array_list<worker *> workers;
-    for (int i = 0; i < DOMAINS; i++) {
-        worker *worker = new rust_domain_test::worker (&kernel);
-        workers.append(worker);
-        worker->start();
-    }
-
-    // We don't join the worker threads here in order to simulate ad-hoc
-    // termination of domains. If we join_all_domains before all domains
-    // are actually spawned, this could crash, thus the reason for the
-    // sleep below.
-
-    sync::sleep(100);
-    return true;
-}
-
-void task_entry(void *, rust_opaque_closure *, void *) {
-    printf("task entry\n");
-}
-
-void
-rust_task_test::worker::run() {
-    rust_task_id root_id = kernel->create_task(NULL, "main");
-    rust_task *root_task = kernel->get_task_by_id(root_id);
-    root_task->start(&task_entry, NULL, NULL);
-    root_task->sched->start_main_loop();
-}
-
-bool
-rust_task_test::run() {
-    rust_env env;
-    rust_srv srv(&env);
-    rust_kernel kernel(&srv, 1);
-
-    array_list<worker *> workers;
-    for (int i = 0; i < DOMAINS; i++) {
-        worker *worker = new rust_task_test::worker (&kernel, this);
-        workers.append(worker);
-        worker->start();
-    }
-
-    //sync::sleep(rand(&kernel.sched->rctx) % 1000);
-    return true;
-}
diff --git a/src/rt/test/rust_test_runtime.h b/src/rt/test/rust_test_runtime.h
deleted file mode 100644 (file)
index eb8ebe2..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-#include "../rust_internal.h"
-
-#ifndef RUST_TEST_RUNTIME_H
-#define RUST_TEST_RUNTIME_H
-
-class rust_test_runtime {
-public:
-    rust_test_runtime();
-    virtual ~rust_test_runtime();
-};
-
-
-class rust_domain_test : public rust_test {
-public:
-    class worker : public rust_thread {
-        public:
-        rust_kernel *kernel;
-        worker(rust_kernel *kernel) : kernel(kernel) {
-        }
-        void run();
-    };
-    bool run();
-    const char *name() {
-        return "rust_domain_test";
-    }
-};
-
-class rust_task_test : public rust_test {
-public:
-    rust_test_suite *suite;
-    rust_task_test(rust_test_suite *suite) : suite(suite) {
-    }
-    class worker : public rust_thread {
-        public:
-        rust_kernel *kernel;
-        rust_task_test *parent;
-        worker(rust_kernel *kernel, rust_task_test *parent) :
-            kernel(kernel), parent(parent) {
-        }
-        void run();
-    };
-    bool run();
-    const char *name() {
-        return "rust_task_test";
-    }
-};
-
-#endif /* RUST_TEST_RUNTIME_H */
diff --git a/src/rt/test/rust_test_util.cpp b/src/rt/test/rust_test_util.cpp
deleted file mode 100644 (file)
index 9c6c5d7..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-#include "../rust_internal.h"
-
-#define COUNT 1000
-#define LARGE_COUNT 10000
-#define THREADS 10
-
-bool
-rust_array_list_test::run() {
-    array_list<int> list;
-
-    for (int i = 0; i < COUNT; i++) {
-        list.append(i);
-    }
-
-    for (int i = 0; i < COUNT; i++) {
-        CHECK (list[i] == i);
-    }
-
-    for (int i = 0; i < COUNT; i++) {
-        CHECK (list.index_of(i) == i);
-    }
-
-    for (int i = 0; i < COUNT; i++) {
-        CHECK (list.replace(i, -i));
-        CHECK (list.replace(-i, i));
-        CHECK (list.index_of(i) == i);
-    }
-
-    for (int i = COUNT - 1; i >= 0; i--) {
-        CHECK (list.pop(NULL));
-    }
-
-    return true;
-}
-
-bool
-rust_synchronized_indexed_list_test::run() {
-    array_list<worker*> workers;
-
-    for (int i = 0; i < THREADS; i++) {
-        worker *worker =
-            new rust_synchronized_indexed_list_test::worker(this);
-        workers.append(worker);
-    }
-
-    for (uint32_t i = 0; i < workers.size(); i++) {
-        workers[i]->start();
-    }
-
-    while(workers.is_empty() == false) {
-        worker *worker;
-        workers.pop(&worker);
-        worker->join();
-        delete worker;
-    }
-
-    size_t expected_items = LARGE_COUNT * THREADS;
-
-    CHECK(list.length() == expected_items);
-
-    long long sum = 0;
-    for (size_t i = 0; i < list.length(); i++) {
-        sum += list[i]->value;
-    }
-
-    long long expected_sum = LARGE_COUNT;
-    expected_sum = expected_sum * (expected_sum - 1) / 2 * THREADS;
-    CHECK (sum == expected_sum);
-    return true;
-}
-
-void
-rust_synchronized_indexed_list_test::worker::run() {
-    for (int i = 0; i < LARGE_COUNT; i++) {
-        parent->list.append(new indexed_list_element<int>(i));
-    }
-    return;
-}
diff --git a/src/rt/test/rust_test_util.h b/src/rt/test/rust_test_util.h
deleted file mode 100644 (file)
index 59eff04..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-#ifndef RUST_TEST_UTIL_H
-#define RUST_TEST_UTIL_H
-
-class rust_test_util : public rust_test {
-public:
-
-};
-
-class rust_array_list_test : public rust_test {
-public:
-    bool run();
-    const char *name() {
-        return "rust_array_list_test";
-    }
-};
-
-
-class rust_synchronized_indexed_list_test : public rust_test {
-public:
-    rust_env env;
-    rust_srv srv;
-    synchronized_indexed_list<indexed_list_element<int> > list;
-
-    rust_synchronized_indexed_list_test() :
-        srv(&env)
-    {
-    }
-
-    class worker : public rust_thread {
-    public:
-        rust_synchronized_indexed_list_test *parent;
-        worker(rust_synchronized_indexed_list_test *parent) : parent(parent) {
-        }
-        void run();
-    };
-    bool run();
-    const char *name() {
-        return "rust_synchronized_indexed_list_test";
-    }
-};
-
-#endif /* RUST_TEST_UTIL_H */
index bd998b0eec08b9efd437d40e06027a023d9d7672..439bfd81dc73c4098454aca7fb9cd9bed7b80898 100644 (file)
@@ -62,6 +62,8 @@ fn build_ctxt(sess: session::session, ast: @ast::crate) -> ctxt {
     }
 }
 
+// FIXME: this whole structure should not be duplicated here. makes it
+// painful to add or remove options.
 fn build_session() -> session::session {
     let sopts: @session::options = @{
         crate_type: session::lib_crate,
@@ -83,8 +85,8 @@ fn build_session() -> session::session {
         test: false,
         parse_only: false,
         no_trans: false,
-        do_gc: false,
         no_asm_comments: false,
+        monomorphize: false,
         warn_unused_imports: false
     };
     driver::build_session(sopts, ".", diagnostic::emit)
@@ -100,14 +102,12 @@ fn should_prune_unconfigured_items() {
 }
 
 #[test]
-#[ignore]
 fn srv_should_build_ast_map() {
-    // FIXME
-    /*let source = "fn a() { }";
+    let source = "fn a() { }";
     let srv = mk_srv_from_str(source);
     exec(srv) {|ctxt|
         assert ctxt.ast_map.size() != 0u
-    };*/
+    };
 }
 
 #[test]
index 97c0f31ea5c93dad3e059d03bdd1efdc735da85a..c66e0bdc8332349d4c71d4a232731030f9cbcb38 100644 (file)
 import core::tuple;
 
 export crate_attrs, mod_attrs, fn_attrs, arg_attrs,
-       const_attrs, enum_attrs, variant_attrs, res_attrs;
+       const_attrs, enum_attrs, variant_attrs, res_attrs,
+       iface_attrs, method_attrs, impl_attrs, type_attrs;
 export parse_crate, parse_mod, parse_fn, parse_const,
-       parse_enum, parse_variant, parse_res;
+       parse_enum, parse_variant, parse_res,
+       parse_iface, parse_method, parse_impl, parse_type;
 
 type crate_attrs = {
     name: option<str>
     args: [arg_attrs]
 };
 
+type iface_attrs = {
+    brief: option<str>,
+    desc: option<str>
+};
+
+type impl_attrs = {
+    brief: option<str>,
+    desc: option<str>
+};
+
+type method_attrs = fn_attrs;
+
+type type_attrs = {
+    brief: option<str>,
+    desc: option<str>
+};
+
 #[cfg(test)]
 mod test {
 
@@ -75,7 +94,7 @@ fn parse_attributes(source: str) -> [ast::attribute] {
             mutable byte_pos: 0u
         };
         let parser = parser::new_parser_from_source_str(
-            parse_sess, [], "-", @source);
+            parse_sess, [], "-", none, @source);
 
         parser::parse_outer_attributes(parser)
     }
@@ -481,4 +500,20 @@ fn shoulde_parse_resource_arg() {
     let attrs = parse_res(attrs);
     assert attrs.args[0].name == "a";
     assert attrs.args[0].desc == "b";
+}
+
+fn parse_iface(attrs: [ast::attribute]) -> iface_attrs {
+    parse_basic(attrs)
+}
+
+fn parse_method(attrs: [ast::attribute]) -> method_attrs {
+    parse_fn(attrs)
+}
+
+fn parse_impl(attrs: [ast::attribute]) -> impl_attrs {
+    parse_basic(attrs)
+}
+
+fn parse_type(attrs: [ast::attribute]) -> type_attrs {
+    parse_basic(attrs)
 }
\ No newline at end of file
index 9ee4f8ec78c22a38043ba96d314d761f1a41078f..e95a256fe047623f08acd961c703acf2b60543fb 100644 (file)
@@ -25,7 +25,10 @@ fn run(
         fold_fn: fold_fn,
         fold_const: fold_const,
         fold_enum: fold_enum,
-        fold_res: fold_res
+        fold_res: fold_res,
+        fold_iface: fold_iface,
+        fold_impl: fold_impl,
+        fold_type: fold_type
         with *fold::default_seq_fold(srv)
     });
     fold.fold_crate(fold, doc)
@@ -44,21 +47,17 @@ fn fold_crate(
         attr_parser::parse_crate(attrs)
     };
 
-    ~{
-        topmod: ~{
+    {
+        topmod: {
             name: option::from_maybe(doc.topmod.name, attrs.name)
-            with *doc.topmod
+            with doc.topmod
         }
     }
 }
 
 #[test]
 fn should_replace_top_module_name_with_crate_name() {
-    let source = "#[link(name = \"bond\")];";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let fold = fold::default_seq_fold(srv);
-    let doc = fold_crate(fold, doc);
+    let doc = test::mk_doc("#[link(name = \"bond\")];");
     assert doc.topmod.name == "bond";
 }
 
@@ -68,7 +67,10 @@ fn parse_item_attrs<T>(
     parse_attrs: fn~([ast::attribute]) -> T) -> T {
     astsrv::exec(srv) {|ctxt|
         let attrs = alt ctxt.ast_map.get(id) {
-          ast_map::node_item(item) { item.attrs }
+          ast_map::node_item(item, _) { item.attrs }
+          _ {
+            fail "parse_item_attrs: not an item";
+          }
         };
         parse_attrs(attrs)
     }
@@ -91,32 +93,24 @@ fn merge_mod_attrs(
         doc: doc::moddoc,
         attrs: attr_parser::mod_attrs
     ) -> doc::moddoc {
-        ~{
+        {
             brief: attrs.brief,
             desc: attrs.desc
-            with *doc
+            with doc
         }
     }
 }
 
 #[test]
 fn fold_mod_should_extract_mod_attributes() {
-    let source = "#[doc = \"test\"] mod a { }";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let fold = fold::default_seq_fold(srv);
-    let doc = fold_mod(fold, doc.topmod.mods[0]);
-    assert doc.desc == some("test");
+    let doc = test::mk_doc("#[doc = \"test\"] mod a { }");
+    assert doc.topmod.mods()[0].desc == some("test");
 }
 
 #[test]
 fn fold_mod_should_extract_top_mod_attributes() {
-    let source = "#[doc = \"test\"];";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let fold = fold::default_seq_fold(srv);
-    let doc = fold_mod(fold, doc.topmod);
-    assert doc.desc == some("test");
+    let doc = test::mk_doc("#[doc = \"test\"];");
+    assert doc.topmod.desc == some("test");
 }
 
 fn fold_fn(
@@ -133,65 +127,58 @@ fn merge_fn_attrs(
         doc: doc::fndoc,
         attrs: attr_parser::fn_attrs
     ) -> doc::fndoc {
-        ret ~{
+        ret {
             brief: attrs.brief,
             desc: attrs.desc,
             args: merge_arg_attrs(doc.args, attrs.args),
             return: merge_ret_attrs(doc.return, attrs.return),
             failure: attrs.failure
-            with *doc
+            with doc
         };
     }
+}
 
-    fn merge_arg_attrs(
-        docs: [doc::argdoc],
-        attrs: [attr_parser::arg_attrs]
-    ) -> [doc::argdoc] {
-        vec::map(docs) {|doc|
-            alt vec::find(attrs) {|attr|
-                attr.name == doc.name
-            } {
-                some(attr) {
-                    ~{
-                        desc: some(attr.desc)
-                        with *doc
-                    }
+fn merge_arg_attrs(
+    docs: [doc::argdoc],
+    attrs: [attr_parser::arg_attrs]
+) -> [doc::argdoc] {
+    vec::map(docs) {|doc|
+        alt vec::find(attrs) {|attr|
+            attr.name == doc.name
+        } {
+            some(attr) {
+                {
+                    desc: some(attr.desc)
+                    with doc
                 }
-                none { doc }
             }
+            none { doc }
         }
-        // FIXME: Warning when documenting a non-existent arg
     }
+    // FIXME: Warning when documenting a non-existent arg
+}
 
-    fn merge_ret_attrs(
-        doc: doc::retdoc,
-        attrs: option<str>
-    ) -> doc::retdoc {
-        {
-            desc: attrs
-            with doc
-        }
+
+fn merge_ret_attrs(
+    doc: doc::retdoc,
+    attrs: option<str>
+) -> doc::retdoc {
+    {
+        desc: attrs
+        with doc
     }
 }
 
 #[test]
 fn fold_fn_should_extract_fn_attributes() {
-    let source = "#[doc = \"test\"] fn a() -> int { }";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let fold = fold::default_seq_fold(srv);
-    let doc = fold_fn(fold, doc.topmod.fns[0]);
-    assert doc.desc == some("test");
+    let doc = test::mk_doc("#[doc = \"test\"] fn a() -> int { }");
+    assert doc.topmod.fns()[0].desc == some("test");
 }
 
 #[test]
 fn fold_fn_should_extract_arg_attributes() {
-    let source = "#[doc(args(a = \"b\"))] fn c(a: bool) { }";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let fold = fold::default_seq_fold(srv);
-    let doc = fold_fn(fold, doc.topmod.fns[0]);
-    assert doc.args[0].desc == some("b");
+    let doc = test::mk_doc("#[doc(args(a = \"b\"))] fn c(a: bool) { }");
+    assert doc.topmod.fns()[0].args[0].desc == some("b");
 }
 
 #[test]
@@ -201,7 +188,7 @@ fn fold_fn_should_extract_return_attributes() {
     let doc = extract::from_srv(srv, "");
     let doc = tystr_pass::mk_pass()(srv, doc);
     let fold = fold::default_seq_fold(srv);
-    let doc = fold_fn(fold, doc.topmod.fns[0]);
+    let doc = fold_fn(fold, doc.topmod.fns()[0]);
     assert doc.return.desc == some("what");
 }
 
@@ -212,18 +199,14 @@ fn fold_fn_should_preserve_sig() {
     let doc = extract::from_srv(srv, "");
     let doc = tystr_pass::mk_pass()(srv, doc);
     let fold = fold::default_seq_fold(srv);
-    let doc = fold_fn(fold, doc.topmod.fns[0]);
+    let doc = fold_fn(fold, doc.topmod.fns()[0]);
     assert doc.sig == some("fn a() -> int");
 }
 
 #[test]
 fn fold_fn_should_extract_failure_conditions() {
-    let source = "#[doc(failure = \"what\")] fn a() { }";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let fold = fold::default_seq_fold(srv);
-    let doc = fold_fn(fold, doc.topmod.fns[0]);
-    assert doc.failure == some("what");
+    let doc = test::mk_doc("#[doc(failure = \"what\")] fn a() { }");
+    assert doc.topmod.fns()[0].failure == some("what");
 }
 
 fn fold_const(
@@ -231,25 +214,21 @@ fn fold_const(
     doc: doc::constdoc
 ) -> doc::constdoc {
     let srv = fold.ctxt;
-    let attrs = parse_item_attrs(srv, doc.id, attr_parser::parse_mod);
+    let attrs = parse_item_attrs(srv, doc.id, attr_parser::parse_const);
 
-    ~{
+    {
         brief: attrs.brief,
         desc: attrs.desc
-        with *doc
+        with doc
     }
 }
 
 #[test]
 fn fold_const_should_extract_docs() {
-    let source = "#[doc(brief = \"foo\", desc = \"bar\")]\
-                  const a: bool = true;";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let fold = fold::default_seq_fold(srv);
-    let doc = fold_const(fold, doc.topmod.consts[0]);
-    assert doc.brief == some("foo");
-    assert doc.desc == some("bar");
+    let doc = test::mk_doc("#[doc(brief = \"foo\", desc = \"bar\")]\
+                            const a: bool = true;");
+    assert doc.topmod.consts()[0].brief == some("foo");
+    assert doc.topmod.consts()[0].desc == some("bar");
 }
 
 fn fold_enum(
@@ -259,7 +238,7 @@ fn fold_enum(
     let srv = fold.ctxt;
     let attrs = parse_item_attrs(srv, doc.id, attr_parser::parse_enum);
 
-    ~{
+    {
         brief: attrs.brief,
         desc: attrs.desc,
         variants: vec::map(doc.variants) {|variant|
@@ -267,7 +246,7 @@ fn fold_enum(
                 alt ctxt.ast_map.get(doc.id) {
                   ast_map::node_item(@{
                     node: ast::item_enum(ast_variants, _), _
-                  }) {
+                  }, _) {
                     let ast_variant = option::get(
                         vec::find(ast_variants) {|v|
                             v.node.name == variant.name
@@ -275,38 +254,31 @@ fn fold_enum(
 
                     attr_parser::parse_variant(ast_variant.node.attrs)
                   }
+                  _ { fail "fold_enum: undocumented invariant"; }
                 }
             };
 
-            ~{
+            {
                 desc: attrs.desc
-                with *variant
+                with variant
             }
         }
-        with *doc
+        with doc
     }
 }
 
 #[test]
 fn fold_enum_should_extract_docs() {
-    let source = "#[doc(brief = \"a\", desc = \"b\")]\
-                  enum a { v }";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let fold = fold::default_seq_fold(srv);
-    let doc = fold_enum(fold, doc.topmod.enums[0]);
-    assert doc.brief == some("a");
-    assert doc.desc == some("b");
+    let doc = test::mk_doc("#[doc(brief = \"a\", desc = \"b\")]\
+                            enum a { v }");
+    assert doc.topmod.enums()[0].brief == some("a");
+    assert doc.topmod.enums()[0].desc == some("b");
 }
 
 #[test]
 fn fold_enum_should_extract_variant_docs() {
-    let source = "enum a { #[doc = \"c\"] v }";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let fold = fold::default_seq_fold(srv);
-    let doc = fold_enum(fold, doc.topmod.enums[0]);
-    assert doc.variants[0].desc == some("c");
+    let doc = test::mk_doc("enum a { #[doc = \"c\"] v }");
+    assert doc.topmod.enums()[0].variants[0].desc == some("c");
 }
 
 fn fold_res(
@@ -317,7 +289,7 @@ fn fold_res(
     let srv = fold.ctxt;
     let attrs = parse_item_attrs(srv, doc.id, attr_parser::parse_fn);
 
-    ~{
+    {
         brief: attrs.brief,
         desc: attrs.desc,
         args: vec::map(doc.args) {|doc|
@@ -325,38 +297,188 @@ fn fold_res(
                 attr.name == doc.name
             } {
                 some(attr) {
-                    ~{
+                    {
                         desc: some(attr.desc)
-                        with *doc
+                        with doc
                     }
                 }
                 none { doc }
             }
         }
-        with *doc
+        with doc
     }
 }
 
 #[test]
 fn fold_res_should_extract_docs() {
-    let source = "#[doc(brief = \"a\", desc = \"b\")]\
-                  resource r(b: bool) { }";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let fold = fold::default_seq_fold(srv);
-    let doc = fold_res(fold, doc.topmod.resources[0]);
-    assert doc.brief == some("a");
-    assert doc.desc == some("b");
+    let doc = test::mk_doc("#[doc(brief = \"a\", desc = \"b\")]\
+                            resource r(b: bool) { }");
+    assert doc.topmod.resources()[0].brief == some("a");
+    assert doc.topmod.resources()[0].desc == some("b");
 }
 
 #[test]
 fn fold_res_should_extract_arg_docs() {
-    let source = "#[doc(args(a = \"b\"))]\
-                  resource r(a: bool) { }";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let fold = fold::default_seq_fold(srv);
-    let doc = fold_res(fold, doc.topmod.resources[0]);
-    assert doc.args[0].name == "a";
-    assert doc.args[0].desc == some("b");
+    let doc = test::mk_doc("#[doc(args(a = \"b\"))]\
+                            resource r(a: bool) { }");
+    assert doc.topmod.resources()[0].args[0].name == "a";
+    assert doc.topmod.resources()[0].args[0].desc == some("b");
+}
+
+fn fold_iface(
+    fold: fold::fold<astsrv::srv>,
+    doc: doc::ifacedoc
+) -> doc::ifacedoc {
+    let srv = fold.ctxt;
+    let doc = fold::default_seq_fold_iface(fold, doc);
+    let attrs = parse_item_attrs(srv, doc.id, attr_parser::parse_iface);
+
+    {
+        brief: attrs.brief,
+        desc: attrs.desc,
+        methods: merge_method_attrs(srv, doc.id, doc.methods)
+        with doc
+    }
+}
+
+fn merge_method_attrs(
+    srv: astsrv::srv,
+    item_id: doc::ast_id,
+    docs: [doc::methoddoc]
+) -> [doc::methoddoc] {
+    // Create an assoc list from method name to attributes
+    let attrs = astsrv::exec(srv) {|ctxt|
+        alt ctxt.ast_map.get(item_id) {
+          ast_map::node_item(@{
+            node: ast::item_iface(_, methods), _
+          }, _) {
+            vec::map(methods) {|method|
+                (method.ident, attr_parser::parse_method(method.attrs))
+            }
+          }
+          ast_map::node_item(@{
+            node: ast::item_impl(_, _, _, methods), _
+          }, _) {
+            vec::map(methods) {|method|
+                (method.ident, attr_parser::parse_method(method.attrs))
+            }
+          }
+          _ { fail "unexpected item" }
+        }
+    };
+
+    vec::map2(docs, attrs) {|doc, attrs|
+        assert doc.name == tuple::first(attrs);
+        let attrs = tuple::second(attrs);
+
+        {
+            brief: attrs.brief,
+            desc: attrs.desc,
+            args: merge_arg_attrs(doc.args, attrs.args),
+            return: merge_ret_attrs(doc.return, attrs.return),
+            failure: attrs.failure
+            with doc
+        }
+    }
+}
+
+#[test]
+fn should_extract_iface_docs() {
+    let doc = test::mk_doc("#[doc = \"whatever\"] iface i { fn a(); }");
+    assert doc.topmod.ifaces()[0].desc == some("whatever");
+}
+
+#[test]
+fn should_extract_iface_method_docs() {
+    let doc = test::mk_doc(
+        "iface i {\
+         #[doc(\
+         brief = \"brief\",\
+         desc = \"desc\",\
+         args(a = \"a\"),\
+         return = \"return\",\
+         failure = \"failure\")]\
+         fn f(a: bool) -> bool;\
+         }");
+    assert doc.topmod.ifaces()[0].methods[0].brief == some("brief");
+    assert doc.topmod.ifaces()[0].methods[0].desc == some("desc");
+    assert doc.topmod.ifaces()[0].methods[0].args[0].desc == some("a");
+    assert doc.topmod.ifaces()[0].methods[0].return.desc == some("return");
+    assert doc.topmod.ifaces()[0].methods[0].failure == some("failure");
+}
+
+
+fn fold_impl(
+    fold: fold::fold<astsrv::srv>,
+    doc: doc::impldoc
+) -> doc::impldoc {
+    let srv = fold.ctxt;
+    let doc = fold::default_seq_fold_impl(fold, doc);
+    let attrs = parse_item_attrs(srv, doc.id, attr_parser::parse_impl);
+
+    {
+        brief: attrs.brief,
+        desc: attrs.desc,
+        methods: merge_method_attrs(srv, doc.id, doc.methods)
+        with doc
+    }
+}
+
+#[test]
+fn should_extract_impl_docs() {
+    let doc = test::mk_doc(
+        "#[doc = \"whatever\"] impl i for int { fn a() { } }");
+    assert doc.topmod.impls()[0].desc == some("whatever");
+}
+
+#[test]
+fn should_extract_impl_method_docs() {
+    let doc = test::mk_doc(
+        "impl i for int {\
+         #[doc(\
+         brief = \"brief\",\
+         desc = \"desc\",\
+         args(a = \"a\"),\
+         return = \"return\",\
+         failure = \"failure\")]\
+         fn f(a: bool) -> bool { }\
+         }");
+    assert doc.topmod.impls()[0].methods[0].brief == some("brief");
+    assert doc.topmod.impls()[0].methods[0].desc == some("desc");
+    assert doc.topmod.impls()[0].methods[0].args[0].desc == some("a");
+    assert doc.topmod.impls()[0].methods[0].return.desc == some("return");
+    assert doc.topmod.impls()[0].methods[0].failure == some("failure");
+}
+
+fn fold_type(
+    fold: fold::fold<astsrv::srv>,
+    doc: doc::tydoc
+) -> doc::tydoc {
+    let srv = fold.ctxt;
+    let doc = fold::default_seq_fold_type(fold, doc);
+    let attrs = parse_item_attrs(srv, doc.id, attr_parser::parse_type);
+
+    {
+        brief: attrs.brief,
+        desc: attrs.desc
+        with doc
+    }
+}
+
+#[test]
+fn should_extract_type_docs() {
+    let doc = test::mk_doc(
+        "#[doc(brief = \"brief\", desc = \"desc\")]\
+         type t = int;");
+    assert doc.topmod.types()[0].brief == some("brief");
+    assert doc.topmod.types()[0].desc == some("desc");
+}
+
+#[cfg(test)]
+mod test {
+    fn mk_doc(source: str) -> doc::cratedoc {
+        let srv = astsrv::mk_srv_from_str(source);
+        let doc = extract::from_srv(srv, "");
+        run(srv, doc)
+    }
 }
\ No newline at end of file
index f705f2b591578198f8202290674b54cc9d8c5071..4feae4106a5f9a2902fdcb6effb54a5ae2ce3617 100644 (file)
@@ -98,4 +98,84 @@ mod blade_runner {
 ")]
 resource bored(bored: bool) {
     log(error, bored);
+}
+
+#[doc(
+    brief = "The Shunned House",
+    desc = "
+
+From even the greatest of horrors irony is seldom absent. Sometimes it
+enters directly into the composition of the events, while sometimes it
+relates only to their fortuitous position among persons and
+places. The latter sort is splendidly exemplified by a case in the
+ancient city of Providence, where in the late forties Edgar Allan Poe
+used to sojourn often during his unsuccessful wooing of the gifted
+poetess, Mrs.  Whitman. Poe generally stopped at the Mansion House in
+Benefit Street--the renamed Golden Ball Inn whose roof has sheltered
+Washington, Jefferson, and Lafayette--and his favorite walk led
+northward along the same street to Mrs. Whitman's home and the
+neighboring hillside churchyard of St. John's, whose hidden expanse of
+Eighteenth Century gravestones had for him a peculiar fascination.
+
+")]
+iface the_shunned_house {
+    #[doc(
+        desc = "
+
+    Now the irony is this. In this walk, so many times repeated, the
+    world's greatest master of the terrible and the bizarre was
+    obliged to pass a particular house on the eastern side of the
+    street; a dingy, antiquated structure perched on the abruptly
+    rising side hill, with a great unkempt yard dating from a time
+    when the region was partly open country. It does not appear that
+    he ever wrote or spoke of it, nor is there any evidence that he
+    even noticed it. And yet that house, to the two persons in
+    possession of certain information, equals or outranks in horror
+    the wildest fantasy of the genius who so often passed it
+    unknowingly, and stands starkly leering as a symbol of all that is
+    unutterably hideous.
+
+    ",
+        args(
+            a =
+            "A yard dating from a time when the region was partly
+             open country"
+    ))]
+    fn dingy_house(unkempt_yard: int);
+
+    #[doc(
+        desc = "
+
+    The house was--and for that matter still is--of a kind to attract
+    the attention of the curious. Originally a farm or semi-farm
+    building, it followed the average New England colonial lines of
+    the middle Eighteenth Century--the prosperous peaked-roof sort,
+    with two stories and dormerless attic, and with the Georgian
+    doorway and interior panelling dictated by the progress of taste
+    at that time. It faced south, with one gable end buried to the
+    lower windows in the eastward rising hill, and the other exposed
+    to the foundations toward the street. Its construction, over a
+    century and a half ago, had followed the grading and straightening
+    of the road in that especial vicinity; for Benefit Street--at
+    first called Back Street--was laid out as a lane winding amongst
+    the graveyards of the first settlers, and straightened only when
+    the removal of the bodies to the North Burial Ground made it
+    decently possible to cut through the old family plots.
+
+    ",
+        return = "A dingy house with an unkempt yard",
+        failure = "Will fail if bodies are removed from premises"
+    )]
+    fn construct() -> bool;
+}
+
+#[doc = "Whatever"]
+impl of the_shunned_house for omnomnomy {
+    #[doc(args(_unkempt_yard = "Whatever"))]
+    fn dingy_house(_unkempt_yard: int) {
+    }
+
+    fn construct() -> bool {
+        fail;
+    }
 }
\ No newline at end of file
index 7168a0b4d874d02d8080543238ff72ff8bdb2daf..c7a204f53c5bcb135affabbebeea4feac99f9334 100644 (file)
@@ -20,7 +20,10 @@ fn run(
         fold_const: fold_const,
         fold_fn: fold_fn,
         fold_enum: fold_enum,
-        fold_res: fold_res
+        fold_res: fold_res,
+        fold_iface: fold_iface,
+        fold_impl: fold_impl,
+        fold_type: fold_type
         with *fold::default_seq_fold(op)
     });
     fold.fold_crate(fold, doc)
@@ -33,33 +36,33 @@ fn maybe_apply_op(op: op, s: option<str>) -> option<str> {
 fn fold_mod(fold: fold::fold<op>, doc: doc::moddoc) -> doc::moddoc {
     let doc = fold::default_seq_fold_mod(fold, doc);
 
-    ~{
+    {
         brief: maybe_apply_op(fold.ctxt, doc.brief),
         desc: maybe_apply_op(fold.ctxt, doc.desc)
-        with *doc
+        with doc
     }
 }
 
 fn fold_const(fold: fold::fold<op>, doc: doc::constdoc) -> doc::constdoc {
     let doc = fold::default_seq_fold_const(fold, doc);
 
-    ~{
+    {
         brief: maybe_apply_op(fold.ctxt, doc.brief),
         desc: maybe_apply_op(fold.ctxt, doc.desc)
-        with *doc
+        with doc
     }
 }
 
 fn fold_fn(fold: fold::fold<op>, doc: doc::fndoc) -> doc::fndoc {
     let doc = fold::default_seq_fold_fn(fold, doc);
 
-    ~{
+    {
         brief: maybe_apply_op(fold.ctxt, doc.brief),
         desc: maybe_apply_op(fold.ctxt, doc.desc),
         args: vec::map(doc.args) {|doc|
-            ~{
+            {
                 desc: maybe_apply_op(fold.ctxt, doc.desc)
-                with *doc
+                with doc
             }
         },
         return: {
@@ -67,94 +70,240 @@ fn fold_fn(fold: fold::fold<op>, doc: doc::fndoc) -> doc::fndoc {
             with doc.return
         },
         failure: maybe_apply_op(fold.ctxt, doc.failure)
-        with *doc
+        with doc
     }
 }
 
 fn fold_enum(fold: fold::fold<op>, doc: doc::enumdoc) -> doc::enumdoc {
-    ~{
+    {
         brief: maybe_apply_op(fold.ctxt, doc.brief),
         desc: maybe_apply_op(fold.ctxt, doc.desc),
         variants: vec::map(doc.variants) {|variant|
-            ~{
+            {
                 desc: maybe_apply_op(fold.ctxt, variant.desc)
-                with *variant
+                with variant
             }
         }
-        with *doc
+        with doc
     }
 }
 
 fn fold_res(fold: fold::fold<op>, doc: doc::resdoc) -> doc::resdoc {
-    ~{
+    {
         brief: maybe_apply_op(fold.ctxt, doc.brief),
         desc: maybe_apply_op(fold.ctxt, doc.desc),
         args: vec::map(doc.args) {|arg|
-            ~{
+            {
                 desc: maybe_apply_op(fold.ctxt, arg.desc)
-                with *arg
+                with arg
             }
         }
-        with *doc
+        with doc
+    }
+}
+
+fn fold_iface(fold: fold::fold<op>, doc: doc::ifacedoc) -> doc::ifacedoc {
+    {
+        brief: maybe_apply_op(fold.ctxt, doc.brief),
+        desc: maybe_apply_op(fold.ctxt, doc.desc),
+        methods: apply_to_methods(fold.ctxt, doc.methods)
+        with doc
+    }
+}
+
+fn apply_to_methods(op: op, docs: [doc::methoddoc]) -> [doc::methoddoc] {
+    vec::map(docs) {|doc|
+        {
+            brief: maybe_apply_op(op, doc.brief),
+            desc: maybe_apply_op(op, doc.desc),
+            args: vec::map(doc.args) {|doc|
+                {
+                    desc: maybe_apply_op(op, doc.desc)
+                    with doc
+                }
+            },
+            return: {
+                desc: maybe_apply_op(op, doc.return.desc)
+                with doc.return
+            },
+            failure: maybe_apply_op(op, doc.failure)
+            with doc
+        }
+    }
+}
+
+fn fold_impl(fold: fold::fold<op>, doc: doc::impldoc) -> doc::impldoc {
+    {
+        brief: maybe_apply_op(fold.ctxt, doc.brief),
+        desc: maybe_apply_op(fold.ctxt, doc.desc),
+        methods: apply_to_methods(fold.ctxt, doc.methods)
+        with doc
+    }
+}
+
+fn fold_type(fold: fold::fold<op>, doc: doc::tydoc) -> doc::tydoc {
+    {
+        brief: maybe_apply_op(fold.ctxt, doc.brief),
+        desc: maybe_apply_op(fold.ctxt, doc.desc)
+        with doc
     }
 }
 
 #[test]
 fn should_execute_op_on_enum_brief() {
-    let source = "#[doc(brief = \" a \")] enum a { b }";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let doc = attr_pass::mk_pass()(srv, doc);
-    let doc = mk_pass(str::trim)(srv, doc);
-    assert doc.topmod.enums[0].brief == some("a");
+    let doc = test::mk_doc("#[doc(brief = \" a \")] enum a { b }");
+    assert doc.topmod.enums()[0].brief == some("a");
 }
 
 #[test]
 fn should_execute_op_on_enum_desc() {
-    let source = "#[doc(desc = \" a \")] enum a { b }";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let doc = attr_pass::mk_pass()(srv, doc);
-    let doc = mk_pass(str::trim)(srv, doc);
-    assert doc.topmod.enums[0].desc == some("a");
+    let doc = test::mk_doc("#[doc(desc = \" a \")] enum a { b }");
+    assert doc.topmod.enums()[0].desc == some("a");
 }
 
 #[test]
 fn should_execute_op_on_variant_desc() {
-    let source = "enum a { #[doc = \" a \"] b }";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let doc = attr_pass::mk_pass()(srv, doc);
-    let doc = mk_pass(str::trim)(srv, doc);
-    assert doc.topmod.enums[0].variants[0].desc == some("a");
+    let doc = test::mk_doc("enum a { #[doc = \" a \"] b }");
+    assert doc.topmod.enums()[0].variants[0].desc == some("a");
 }
 
 #[test]
 fn should_execute_op_on_resource_brief() {
-    let source = "#[doc(brief = \" a \")] resource r(a: bool) { }";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let doc = attr_pass::mk_pass()(srv, doc);
-    let doc = mk_pass(str::trim)(srv, doc);
-    assert doc.topmod.resources[0].brief == some("a");
+    let doc = test::mk_doc("#[doc(brief = \" a \")] resource r(a: bool) { }");
+    assert doc.topmod.resources()[0].brief == some("a");
 }
 
 #[test]
 fn should_execute_op_on_resource_desc() {
-    let source = "#[doc(desc = \" a \")] resource r(a: bool) { }";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let doc = attr_pass::mk_pass()(srv, doc);
-    let doc = mk_pass(str::trim)(srv, doc);
-    assert doc.topmod.resources[0].desc == some("a");
+    let doc = test::mk_doc("#[doc(desc = \" a \")] resource r(a: bool) { }");
+    assert doc.topmod.resources()[0].desc == some("a");
 }
 
 #[test]
 fn should_execute_op_on_resource_args() {
-    let source = "#[doc(args(a = \" a \"))] resource r(a: bool) { }";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let doc = attr_pass::mk_pass()(srv, doc);
-    let doc = mk_pass(str::trim)(srv, doc);
-    assert doc.topmod.resources[0].args[0].desc == some("a");
+    let doc = test::mk_doc(
+        "#[doc(args(a = \" a \"))] resource r(a: bool) { }");
+    assert doc.topmod.resources()[0].args[0].desc == some("a");
+}
+
+#[test]
+fn should_execute_op_on_iface_brief() {
+    let doc = test::mk_doc(
+        "#[doc(brief = \" a \")] iface i { fn a(); }");
+    assert doc.topmod.ifaces()[0].brief == some("a");
+}
+
+#[test]
+fn should_execute_op_on_iface_desc() {
+    let doc = test::mk_doc(
+        "#[doc(desc = \" a \")] iface i { fn a(); }");
+    assert doc.topmod.ifaces()[0].desc == some("a");
+}
+
+#[test]
+fn should_execute_op_on_iface_method_brief() {
+    let doc = test::mk_doc(
+        "iface i { #[doc(brief = \" a \")] fn a(); }");
+    assert doc.topmod.ifaces()[0].methods[0].brief == some("a");
+}
+
+#[test]
+fn should_execute_op_on_iface_method_desc() {
+    let doc = test::mk_doc(
+        "iface i { #[doc(desc = \" a \")] fn a(); }");
+    assert doc.topmod.ifaces()[0].methods[0].desc == some("a");
+}
+
+#[test]
+fn should_execute_op_on_iface_method_args() {
+    let doc = test::mk_doc(
+        "iface i { #[doc(args(a = \" a \"))] fn a(a: bool); }");
+    assert doc.topmod.ifaces()[0].methods[0].args[0].desc == some("a");
+}
+
+#[test]
+fn should_execute_op_on_iface_method_return() {
+    let doc = test::mk_doc(
+        "iface i { #[doc(return = \" a \")] fn a() -> int; }");
+    assert doc.topmod.ifaces()[0].methods[0].return.desc == some("a");
+}
+
+#[test]
+fn should_execute_op_on_iface_method_failure_condition() {
+    let doc = test::mk_doc("iface i { #[doc(failure = \" a \")] fn a(); }");
+    assert doc.topmod.ifaces()[0].methods[0].failure == some("a");
+}
+
+#[test]
+fn should_execute_op_on_impl_brief() {
+    let doc = test::mk_doc(
+        "#[doc(brief = \" a \")] impl i for int { fn a() { } }");
+    assert doc.topmod.impls()[0].brief == some("a");
+}
+
+#[test]
+fn should_execute_op_on_impl_desc() {
+    let doc = test::mk_doc(
+        "#[doc(desc = \" a \")] impl i for int { fn a() { } }");
+    assert doc.topmod.impls()[0].desc == some("a");
+}
+
+#[test]
+fn should_execute_op_on_impl_method_brief() {
+    let doc = test::mk_doc(
+        "impl i for int { #[doc(brief = \" a \")] fn a() { } }");
+    assert doc.topmod.impls()[0].methods[0].brief == some("a");
+}
+
+#[test]
+fn should_execute_op_on_impl_method_desc() {
+    let doc = test::mk_doc(
+        "impl i for int { #[doc(desc = \" a \")] fn a() { } }");
+    assert doc.topmod.impls()[0].methods[0].desc == some("a");
+}
+
+#[test]
+fn should_execute_op_on_impl_method_args() {
+    let doc = test::mk_doc(
+        "impl i for int { #[doc(args(a = \" a \"))] fn a(a: bool) { } }");
+    assert doc.topmod.impls()[0].methods[0].args[0].desc == some("a");
+}
+
+#[test]
+fn should_execute_op_on_impl_method_return() {
+    let doc = test::mk_doc(
+        "impl i for int { #[doc(return = \" a \")] fn a() -> int { fail } }");
+    assert doc.topmod.impls()[0].methods[0].return.desc == some("a");
+}
+
+#[test]
+fn should_execute_op_on_impl_method_failure_condition() {
+    let doc = test::mk_doc(
+        "impl i for int { #[doc(failure = \" a \")] fn a() { } }");
+    assert doc.topmod.impls()[0].methods[0].failure == some("a");
+}
+
+
+#[test]
+fn should_execute_op_on_type_brief() {
+    let doc = test::mk_doc(
+        "#[doc(brief = \" a \")] type t = int;");
+    assert doc.topmod.types()[0].brief == some("a");
+}
+
+#[test]
+fn should_execute_op_on_type_desc() {
+    let doc = test::mk_doc(
+        "#[doc(desc = \" a \")] type t = int;");
+    assert doc.topmod.types()[0].desc == some("a");
+}
+
+#[cfg(test)]
+mod test {
+    fn mk_doc(source: str) -> doc::cratedoc {
+        let srv = astsrv::mk_srv_from_str(source);
+        let doc = extract::from_srv(srv, "");
+        let doc = attr_pass::mk_pass()(srv, doc);
+        mk_pass(str::trim)(srv, doc)
+    }
 }
\ No newline at end of file
index 3c2cc46dad1466f524ae472597d8853e06b94219..89b2b5d97bce73492fe3a13bc48db2eb75ca7e6e 100644 (file)
@@ -22,7 +22,10 @@ fn run(
         fold_const: fold_const,
         fold_fn: fold_fn,
         fold_enum: fold_enum,
-        fold_res: fold_res
+        fold_res: fold_res,
+        fold_iface: fold_iface,
+        fold_impl: fold_impl,
+        fold_type: fold_type
         with *fold::default_seq_fold(())
     });
     fold.fold_crate(fold, doc)
@@ -32,10 +35,10 @@ fn fold_mod(fold: fold::fold<()>, doc: doc::moddoc) -> doc::moddoc {
     let doc = fold::default_seq_fold_mod(fold, doc);
     let (brief, desc) = modify(doc.brief, doc.desc);
 
-    ~{
+    {
         brief: brief,
         desc: desc
-        with *doc
+        with doc
     }
 }
 
@@ -43,10 +46,10 @@ fn fold_const(fold: fold::fold<()>, doc: doc::constdoc) -> doc::constdoc {
     let doc = fold::default_seq_fold_const(fold, doc);
     let (brief, desc) = modify(doc.brief, doc.desc);
 
-    ~{
+    {
         brief: brief,
         desc: desc
-        with *doc
+        with doc
     }
 }
 
@@ -54,10 +57,10 @@ fn fold_fn(fold: fold::fold<()>, doc: doc::fndoc) -> doc::fndoc {
     let doc = fold::default_seq_fold_fn(fold, doc);
     let (brief, desc) = modify(doc.brief, doc.desc);
 
-    ~{
+    {
         brief: brief,
         desc: desc
-        with *doc
+        with doc
     }
 }
 
@@ -65,10 +68,10 @@ fn fold_enum(fold: fold::fold<()>, doc: doc::enumdoc) -> doc::enumdoc {
     let doc = fold::default_seq_fold_enum(fold, doc);
     let (brief, desc) = modify(doc.brief, doc.desc);
 
-    ~{
+    {
         brief: brief,
         desc: desc
-        with *doc
+        with doc
     }
 }
 
@@ -76,66 +79,145 @@ fn fold_res(fold: fold::fold<()>, doc: doc::resdoc) -> doc::resdoc {
     let doc = fold::default_seq_fold_res(fold, doc);
     let (brief, desc) = modify(doc.brief, doc.desc);
 
-    ~{
+    {
         brief: brief,
         desc: desc
-        with *doc
+        with doc
+    }
+}
+
+fn fold_iface(fold: fold::fold<()>, doc: doc::ifacedoc) -> doc::ifacedoc {
+    let doc =fold::default_seq_fold_iface(fold, doc);
+    let (brief, desc) = modify(doc.brief, doc.desc);
+
+    {
+        brief: brief,
+        desc: desc,
+        methods: vec::map(doc.methods) {|doc|
+            let (brief, desc) = modify(doc.brief, doc.desc);
+
+            {
+                brief: brief,
+                desc: desc
+                with doc
+            }
+        }
+        with doc
+    }
+}
+
+fn fold_impl(fold: fold::fold<()>, doc: doc::impldoc) -> doc::impldoc {
+    let doc =fold::default_seq_fold_impl(fold, doc);
+    let (brief, desc) = modify(doc.brief, doc.desc);
+
+    {
+        brief: brief,
+        desc: desc,
+        methods: vec::map(doc.methods) {|doc|
+            let (brief, desc) = modify(doc.brief, doc.desc);
+
+            {
+                brief: brief,
+                desc: desc
+                with doc
+            }
+        }
+        with doc
+    }
+}
+
+fn fold_type(fold: fold::fold<()>, doc: doc::tydoc) -> doc::tydoc {
+    let doc = fold::default_seq_fold_type(fold, doc);
+    let (brief, desc) = modify(doc.brief, doc.desc);
+
+    {
+        brief: brief,
+        desc: desc
+        with doc
     }
 }
 
 #[test]
 fn should_promote_mod_desc() {
-    let source = "#[doc(desc = \"desc\")] mod m { }";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let doc = attr_pass::mk_pass()(srv, doc);
-    let doc = run(srv, doc);
-    assert doc.topmod.mods[0].brief == some("desc");
-    assert doc.topmod.mods[0].desc == none;
+    let doc = test::mk_doc("#[doc(desc = \"desc\")] mod m { }");
+    assert doc.topmod.mods()[0].brief == some("desc");
+    assert doc.topmod.mods()[0].desc == none;
 }
 
 #[test]
 fn should_promote_const_desc() {
-    let source = "#[doc(desc = \"desc\")] const a: bool = true;";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let doc = attr_pass::mk_pass()(srv, doc);
-    let doc = run(srv, doc);
-    assert doc.topmod.consts[0].brief == some("desc");
-    assert doc.topmod.consts[0].desc == none;
+    let doc = test::mk_doc("#[doc(desc = \"desc\")] const a: bool = true;");
+    assert doc.topmod.consts()[0].brief == some("desc");
+    assert doc.topmod.consts()[0].desc == none;
 }
 
 #[test]
 fn should_promote_fn_desc() {
-    let source = "#[doc(desc = \"desc\")] fn a() { }";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let doc = attr_pass::mk_pass()(srv, doc);
-    let doc = run(srv, doc);
-    assert doc.topmod.fns[0].brief == some("desc");
-    assert doc.topmod.fns[0].desc == none;
+    let doc = test::mk_doc("#[doc(desc = \"desc\")] fn a() { }");
+    assert doc.topmod.fns()[0].brief == some("desc");
+    assert doc.topmod.fns()[0].desc == none;
 }
 
 #[test]
 fn should_promote_enum_desc() {
-    let source = "#[doc(desc = \"desc\")] enum a { b }";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let doc = attr_pass::mk_pass()(srv, doc);
-    let doc = run(srv, doc);
-    assert doc.topmod.enums[0].brief == some("desc");
-    assert doc.topmod.enums[0].desc == none;
+    let doc = test::mk_doc("#[doc(desc = \"desc\")] enum a { b }");
+    assert doc.topmod.enums()[0].brief == some("desc");
+    assert doc.topmod.enums()[0].desc == none;
 }
 
 #[test]
 fn should_promote_resource_desc() {
-    let source = "#[doc(desc = \"desc\")] resource r(a: bool) { }";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let doc = attr_pass::mk_pass()(srv, doc);
-    let doc = run(srv, doc);
-    assert doc.topmod.resources[0].brief == some("desc");
-    assert doc.topmod.resources[0].desc == none;
+    let doc = test::mk_doc(
+        "#[doc(desc = \"desc\")] resource r(a: bool) { }");
+    assert doc.topmod.resources()[0].brief == some("desc");
+    assert doc.topmod.resources()[0].desc == none;
+}
+
+#[test]
+fn should_promote_iface_desc() {
+    let doc = test::mk_doc("#[doc(desc = \"desc\")] iface i { fn a(); }");
+    assert doc.topmod.ifaces()[0].brief == some("desc");
+    assert doc.topmod.ifaces()[0].desc == none;
+}
+
+#[test]
+fn should_promote_iface_method_desc() {
+    let doc = test::mk_doc("iface i { #[doc(desc = \"desc\")] fn a(); }");
+    assert doc.topmod.ifaces()[0].methods[0].brief == some("desc");
+    assert doc.topmod.ifaces()[0].methods[0].desc == none;
+}
+
+#[test]
+fn should_promote_impl_desc() {
+    let doc = test::mk_doc(
+        "#[doc(desc = \"desc\")] impl i for int { fn a() { } }");
+    assert doc.topmod.impls()[0].brief == some("desc");
+    assert doc.topmod.impls()[0].desc == none;
+}
+
+#[test]
+fn should_promote_impl_method_desc() {
+    let doc = test::mk_doc(
+        "impl i for int { #[doc(desc = \"desc\")] fn a() { } }");
+    assert doc.topmod.impls()[0].methods[0].brief == some("desc");
+    assert doc.topmod.impls()[0].methods[0].desc == none;
+}
+
+#[test]
+fn should_promote_type_desc() {
+    let doc = test::mk_doc("#[doc(desc = \"desc\")] type t = int;");
+    assert doc.topmod.types()[0].brief == some("desc");
+    assert doc.topmod.types()[0].desc == none;
+}
+
+#[cfg(test)]
+mod test {
+    fn mk_doc(source: str) -> doc::cratedoc {
+        let srv = astsrv::mk_srv_from_str(source);
+        let doc = extract::from_srv(srv, "");
+        let doc = attr_pass::mk_pass()(srv, doc);
+        run(srv, doc)
+    }
 }
 
 fn modify(
index 0a54aea21f11a527bd2fec82913f61f18988e367..ed2aa2af1ccd318dc299e8b818daae264624be76 100644 (file)
@@ -2,24 +2,32 @@
 
 type ast_id = int;
 
-type cratedoc = ~{
+type cratedoc = {
     topmod: moddoc,
 };
 
-type moddoc = ~{
+enum itemtag {
+    modtag(moddoc),
+    consttag(constdoc),
+    fntag(fndoc),
+    enumtag(enumdoc),
+    restag(resdoc),
+    ifacetag(ifacedoc),
+    impltag(impldoc),
+    tytag(tydoc)
+}
+
+type moddoc = {
     id: ast_id,
     name: str,
     path: [str],
     brief: option<str>,
     desc: option<str>,
-    mods: modlist,
-    fns: fnlist,
-    consts: constlist,
-    enums: enumlist,
-    resources: reslist
+    // This box exists to break the structural recursion
+    items: ~[itemtag]
 };
 
-type constdoc = ~{
+type constdoc = {
     id: ast_id,
     name: str,
     brief: option<str>,
@@ -27,7 +35,7 @@
     ty: option<str>
 };
 
-type fndoc = ~{
+type fndoc = {
     id: ast_id,
     name: str,
     brief: option<str>,
@@ -38,7 +46,7 @@
     sig: option<str>
 };
 
-type argdoc = ~{
+type argdoc = {
     name: str,
     desc: option<str>,
     ty: option<str>
@@ -49,7 +57,7 @@
     ty: option<str>
 };
 
-type enumdoc = ~{
+type enumdoc = {
     id: ast_id,
     name: str,
     brief: option<str>,
     variants: [variantdoc]
 };
 
-type variantdoc = ~{
+type variantdoc = {
     name: str,
     desc: option<str>,
     sig: option<str>
 };
 
-type resdoc = ~{
+type resdoc = {
     id: ast_id,
     name: str,
     brief: option<str>,
     sig: option<str>
 };
 
-// Just to break the structural recursive types
-enum modlist = [moddoc];
-enum constlist = [constdoc];
-enum fnlist = [fndoc];
-enum enumlist = [enumdoc];
-enum reslist = [resdoc];
+type ifacedoc = {
+    id: ast_id,
+    name: str,
+    brief: option<str>,
+    desc: option<str>,
+    methods: [methoddoc]
+};
+
+type methoddoc = {
+    name: str,
+    brief: option<str>,
+    desc: option<str>,
+    args: [argdoc],
+    return: retdoc,
+    failure: option<str>,
+    sig: option<str>
+};
+
+type impldoc = {
+    id: ast_id,
+    name: str,
+    brief: option<str>,
+    desc: option<str>,
+    iface_ty: option<str>,
+    self_ty: option<str>,
+    methods: [methoddoc]
+};
+
+type tydoc = {
+    id: ast_id,
+    name: str,
+    brief: option<str>,
+    desc: option<str>,
+    sig: option<str>
+};
+
+#[doc = "Some helper methods on moddoc, mostly for testing"]
+impl util for moddoc {
+
+    fn mods() -> [moddoc] {
+        vec::filter_map(*self.items) {|itemtag|
+            alt itemtag {
+              modtag(moddoc) { some(moddoc) }
+              _ { none }
+            }
+        }
+    }
+
+    fn fns() -> [fndoc] {
+        vec::filter_map(*self.items) {|itemtag|
+            alt itemtag {
+              fntag(fndoc) { some(fndoc) }
+              _ { none }
+            }
+        }
+    }
+
+    fn consts() -> [constdoc] {
+        vec::filter_map(*self.items) {|itemtag|
+            alt itemtag {
+              consttag(constdoc) { some(constdoc) }
+              _ { none }
+            }
+        }
+    }
+
+    fn enums() -> [enumdoc] {
+        vec::filter_map(*self.items) {|itemtag|
+            alt itemtag {
+              enumtag(enumdoc) { some(enumdoc) }
+              _ { none }
+            }
+        }
+    }
+
+    fn resources() -> [resdoc] {
+        vec::filter_map(*self.items) {|itemtag|
+            alt itemtag {
+              restag(resdoc) { some(resdoc) }
+              _ { none }
+            }
+        }
+    }
+
+    fn ifaces() -> [ifacedoc] {
+        vec::filter_map(*self.items) {|itemtag|
+            alt itemtag {
+              ifacetag(ifacedoc) { some(ifacedoc) }
+              _ { none }
+            }
+        }
+    }
+
+    fn impls() -> [impldoc] {
+        vec::filter_map(*self.items) {|itemtag|
+            alt itemtag {
+              impltag(impldoc) { some(impldoc) }
+              _ { none }
+            }
+        }
+    }
+
+    fn types() -> [tydoc] {
+        vec::filter_map(*self.items) {|itemtag|
+            alt itemtag {
+              tytag(tydoc) { some(tydoc) }
+              _ { none }
+            }
+        }
+    }
+}
+
+#[doc = "Helper methods on itemtag"]
+impl util for itemtag {
+    fn name() -> str {
+        alt self {
+          doc::modtag({name, _}) { name }
+          doc::fntag({name, _}) { name }
+          doc::consttag({name, _}) { name }
+          doc::enumtag({name, _}) { name }
+          doc::restag({name, _}) { name }
+          doc::ifacetag({name, _}) { name }
+          doc::impltag({name, _}) { name }
+          doc::tytag({name, _}) { name }
+        }
+    }
+}
index f5d2f613aa73bd1090e3530112fe605e607d95e7..8e337e3d2366d0430e8470e44f3aa0c58d42d1cf 100644 (file)
@@ -20,7 +20,7 @@ fn extract(
     crate: @ast::crate,
     default_name: str
 ) -> doc::cratedoc {
-    ~{
+    {
         topmod: top_moddoc_from_crate(crate, default_name),
     }
 }
@@ -37,68 +37,59 @@ fn moddoc_from_mod(
     name: ast::ident,
     id: ast::node_id
 ) -> doc::moddoc {
-    ~{
+    {
         id: id,
         name: name,
         path: [],
         brief: none,
         desc: none,
-        mods: doc::modlist(
-            vec::filter_map(module.items) {|item|
-                alt item.node {
-                  ast::item_mod(m) {
-                    some(moddoc_from_mod(m, item.ident, item.id))
-                  }
-                  _ {
-                    none
-                  }
-                }
-            }),
-        fns: doc::fnlist(
-            vec::filter_map(module.items) {|item|
-                alt item.node {
-                  ast::item_fn(decl, _, _) {
-                    some(fndoc_from_fn(
-                        decl, item.ident, item.id))
-                  }
-                  _ {
-                    none
-                  }
-                }
-            }),
-        consts: doc::constlist(
-            vec::filter_map(module.items) {|item|
-                alt item.node {
-                  ast::item_const(_, _) {
-                    some(constdoc_from_const(item.ident, item.id))
-                  }
-                  _ {
-                    none
-                  }
-                }
-            }),
-        enums: doc::enumlist(
-            vec::filter_map(module.items) {|item|
-                alt item.node {
-                  ast::item_enum(variants, _) {
-                    some(enumdoc_from_enum(item.ident, item.id, variants))
-                  }
-                  _ {
-                    none
-                  }
-                }
-            }),
-        resources: doc::reslist(
-            vec::filter_map(module.items) {|item|
-                alt item.node {
-                  ast::item_res(decl, _, _, _, _) {
-                    some(resdoc_from_resource(decl, item.ident, item.id))
-                  }
-                  _ {
-                    none
-                  }
-                }
-            })
+        items: ~vec::filter_map(module.items) {|item|
+            alt item.node {
+              ast::item_mod(m) {
+                some(doc::modtag(
+                    moddoc_from_mod(m, item.ident, item.id)
+                ))
+              }
+              ast::item_fn(decl, _, _) {
+                some(doc::fntag(
+                    fndoc_from_fn(decl, item.ident, item.id)
+                ))
+              }
+              ast::item_const(_, _) {
+                some(doc::consttag(
+                    constdoc_from_const(item.ident, item.id)
+                ))
+              }
+              ast::item_enum(variants, _) {
+                some(doc::enumtag(
+                    enumdoc_from_enum(item.ident, item.id, variants)
+                ))
+              }
+              ast::item_res(decl, _, _, _, _) {
+                some(doc::restag(
+                    resdoc_from_resource(decl, item.ident, item.id)
+                ))
+              }
+              ast::item_iface(_, methods) {
+                some(doc::ifacetag(
+                    ifacedoc_from_iface(methods, item.ident, item.id)
+                ))
+              }
+              ast::item_impl(_, _, _, methods) {
+                some(doc::impltag(
+                    impldoc_from_impl(methods, item.ident, item.id)
+                ))
+              }
+              ast::item_ty(_, _) {
+                some(doc::tytag(
+                    tydoc_from_ty(item.ident, item.id)
+                ))
+              }
+              _ {
+                none
+              }
+            }
+        }
     }
 }
 
@@ -107,7 +98,7 @@ fn fndoc_from_fn(
     name: ast::ident,
     id: ast::node_id
 ) -> doc::fndoc {
-    ~{
+    {
         id: id,
         name: name,
         brief: none,
@@ -127,7 +118,7 @@ fn should_extract_fn_args() {
     let source = "fn a(b: int, c: int) { }";
     let ast = parse::from_str(source);
     let doc = extract(ast, "");
-    let fn_ = doc.topmod.fns[0];
+    let fn_ = doc.topmod.fns()[0];
     assert fn_.args[0].name == "b";
     assert fn_.args[1].name == "c";
 }
@@ -137,7 +128,7 @@ fn argdocs_from_args(args: [ast::arg]) -> [doc::argdoc] {
 }
 
 fn argdoc_from_arg(arg: ast::arg) -> doc::argdoc {
-    ~{
+    {
         name: arg.ident,
         desc: none,
         ty: none
@@ -148,7 +139,7 @@ fn constdoc_from_const(
     name: ast::ident,
     id: ast::node_id
 ) -> doc::constdoc {
-    ~{
+    {
         id: id,
         name: name,
         brief: none,
@@ -159,11 +150,9 @@ fn constdoc_from_const(
 
 #[test]
 fn should_extract_const_name_and_id() {
-    let source = "const a: int = 0;";
-    let ast = parse::from_str(source);
-    let doc = extract(ast, "");
-    assert doc.topmod.consts[0].id != 0;
-    assert doc.topmod.consts[0].name == "a";
+    let doc = test::mk_doc("const a: int = 0;");
+    assert doc.topmod.consts()[0].id != 0;
+    assert doc.topmod.consts()[0].name == "a";
 }
 
 fn enumdoc_from_enum(
@@ -171,7 +160,7 @@ fn enumdoc_from_enum(
     id: ast::node_id,
     variants: [ast::variant]
 ) -> doc::enumdoc {
-    ~{
+    {
         id: id,
         name: name,
         brief: none,
@@ -187,7 +176,7 @@ fn variantdocs_from_variants(
 }
 
 fn variantdoc_from_variant(variant: ast::variant) -> doc::variantdoc {
-    ~{
+    {
         name: variant.node.name,
         desc: none,
         sig: none
@@ -196,19 +185,15 @@ fn variantdoc_from_variant(variant: ast::variant) -> doc::variantdoc {
 
 #[test]
 fn should_extract_enums() {
-    let source = "enum e { v }";
-    let ast = parse::from_str(source);
-    let doc = extract(ast, "");
-    assert doc.topmod.enums[0].id != 0;
-    assert doc.topmod.enums[0].name == "e";
+    let doc = test::mk_doc("enum e { v }");
+    assert doc.topmod.enums()[0].id != 0;
+    assert doc.topmod.enums()[0].name == "e";
 }
 
 #[test]
 fn should_extract_enum_variants() {
-    let source = "enum e { v }";
-    let ast = parse::from_str(source);
-    let doc = extract(ast, "");
-    assert doc.topmod.enums[0].variants[0].name == "v";
+    let doc = test::mk_doc("enum e { v }");
+    assert doc.topmod.enums()[0].variants[0].name == "v";
 }
 
 fn resdoc_from_resource(
@@ -216,7 +201,7 @@ fn resdoc_from_resource(
     name: str,
     id: ast::node_id
 ) -> doc::resdoc {
-    ~{
+    {
         id: id,
         name: name,
         brief: none,
@@ -228,77 +213,182 @@ fn resdoc_from_resource(
 
 #[test]
 fn should_extract_resources() {
-    let source = "resource r(b: bool) { }";
-    let ast = parse::from_str(source);
-    let doc = extract(ast, "");
-    assert doc.topmod.resources[0].id != 0;
-    assert doc.topmod.resources[0].name == "r";
+    let doc = test::mk_doc("resource r(b: bool) { }");
+    assert doc.topmod.resources()[0].id != 0;
+    assert doc.topmod.resources()[0].name == "r";
 }
 
 #[test]
 fn should_extract_resource_args() {
-    let source = "resource r(b: bool) { }";
-    let ast = parse::from_str(source);
-    let doc = extract(ast, "");
-    assert doc.topmod.resources[0].args[0].name == "b";
+    let doc = test::mk_doc("resource r(b: bool) { }");
+    assert doc.topmod.resources()[0].args[0].name == "b";
+}
+
+fn ifacedoc_from_iface(
+    methods: [ast::ty_method],
+    name: str,
+    id: ast::node_id
+) -> doc::ifacedoc {
+    {
+        id: id,
+        name: name,
+        brief: none,
+        desc: none,
+        methods: vec::map(methods) {|method|
+            {
+                name: method.ident,
+                brief: none,
+                desc: none,
+                args: argdocs_from_args(method.decl.inputs),
+                return: {
+                    desc: none,
+                    ty: none
+                },
+                failure: none,
+                sig: none
+            }
+        }
+    }
+}
+
+#[test]
+fn should_extract_ifaces() {
+    let doc = test::mk_doc("iface i { fn f(); }");
+    assert doc.topmod.ifaces()[0].name == "i";
+}
+
+#[test]
+fn should_extract_iface_methods() {
+    let doc = test::mk_doc("iface i { fn f(); }");
+    assert doc.topmod.ifaces()[0].methods[0].name == "f";
+}
+
+#[test]
+fn should_extract_iface_method_args() {
+    let doc = test::mk_doc("iface i { fn f(a: bool); }");
+    assert doc.topmod.ifaces()[0].methods[0].args[0].name == "a";
+}
+
+fn impldoc_from_impl(
+    methods: [@ast::method],
+    name: str,
+    id: ast::node_id
+) -> doc::impldoc {
+    {
+        id: id,
+        name: name,
+        brief: none,
+        desc: none,
+        iface_ty: none,
+        self_ty: none,
+        methods: vec::map(methods) {|method|
+            {
+                name: method.ident,
+                brief: none,
+                desc: none,
+                args: argdocs_from_args(method.decl.inputs),
+                return: {
+                    desc: none,
+                    ty: none
+                },
+                failure: none,
+                sig: none
+            }
+        }
+    }
+}
+
+#[test]
+fn should_extract_impls_with_names() {
+    let doc = test::mk_doc("impl i for int { fn a() { } }");
+    assert doc.topmod.impls()[0].name == "i";
+}
+
+#[test]
+fn should_extract_impls_without_names() {
+    let doc = test::mk_doc("impl of i for int { fn a() { } }");
+    assert doc.topmod.impls()[0].name == "i";
+}
+
+#[test]
+fn should_extract_impl_methods() {
+    let doc = test::mk_doc("impl i for int { fn f() { } }");
+    assert doc.topmod.impls()[0].methods[0].name == "f";
+}
+
+#[test]
+fn should_extract_impl_method_args() {
+    let doc = test::mk_doc("impl i for int { fn f(a: bool) { } }");
+    assert doc.topmod.impls()[0].methods[0].args[0].name == "a";
+}
+
+fn tydoc_from_ty(
+    name: str,
+    id: ast::node_id
+) -> doc::tydoc {
+    {
+        id: id,
+        name: name,
+        brief: none,
+        desc: none,
+        sig: none
+    }
+}
+
+#[test]
+fn should_extract_tys() {
+    let doc = test::mk_doc("type a = int;");
+    assert doc.topmod.types()[0].name == "a";
 }
 
 #[cfg(test)]
-mod tests {
+mod test {
+
+    fn mk_doc(source: str) -> doc::cratedoc {
+        let ast = parse::from_str(source);
+        extract(ast, "")
+    }
 
     #[test]
     fn extract_empty_crate() {
-        let source = ""; // empty crate
-        let ast = parse::from_str(source);
-        let doc = extract(ast, "");
-        // FIXME #1535: These are boxed to prevent a crash
-        assert ~doc.topmod.mods == ~doc::modlist([]);
-        assert ~doc.topmod.fns == ~doc::fnlist([]);
+        let doc = mk_doc("");
+        assert vec::is_empty(doc.topmod.mods());
+        assert vec::is_empty(doc.topmod.fns());
     }
 
     #[test]
     fn extract_mods() {
-        let source = "mod a { mod b { } mod c { } }";
-        let ast = parse::from_str(source);
-        let doc = extract(ast, "");
-        assert doc.topmod.mods[0].name == "a";
-        assert doc.topmod.mods[0].mods[0].name == "b";
-        assert doc.topmod.mods[0].mods[1].name == "c";
+        let doc = mk_doc("mod a { mod b { } mod c { } }");
+        assert doc.topmod.mods()[0].name == "a";
+        assert doc.topmod.mods()[0].mods()[0].name == "b";
+        assert doc.topmod.mods()[0].mods()[1].name == "c";
     }
 
     #[test]
     fn extract_mods_deep() {
-        let source = "mod a { mod b { mod c { } } }";
-        let ast = parse::from_str(source);
-        let doc = extract(ast, "");
-        assert doc.topmod.mods[0].mods[0].mods[0].name == "c";
+        let doc = mk_doc("mod a { mod b { mod c { } } }");
+        assert doc.topmod.mods()[0].mods()[0].mods()[0].name == "c";
     }
 
     #[test]
     fn extract_should_set_mod_ast_id() {
-        let source = "mod a { }";
-        let ast = parse::from_str(source);
-        let doc = extract(ast, "");
-        assert doc.topmod.mods[0].id != 0;
+        let doc = mk_doc("mod a { }");
+        assert doc.topmod.mods()[0].id != 0;
     }
 
     #[test]
     fn extract_fns() {
-        let source =
+        let doc = mk_doc(
             "fn a() { } \
-             mod b { fn c() { } }";
-        let ast = parse::from_str(source);
-        let doc = extract(ast, "");
-        assert doc.topmod.fns[0].name == "a";
-        assert doc.topmod.mods[0].fns[0].name == "c";
+             mod b { fn c() { } }");
+        assert doc.topmod.fns()[0].name == "a";
+        assert doc.topmod.mods()[0].fns()[0].name == "c";
     }
 
     #[test]
     fn extract_should_set_fn_ast_id() {
-        let source = "fn a() { }";
-        let ast = parse::from_str(source);
-        let doc = extract(ast, "");
-        assert doc.topmod.fns[0].id != 0;
+        let doc = mk_doc("fn a() { }");
+        assert doc.topmod.fns()[0].id != 0;
     }
 
     #[test]
index 6f20870691e825acb1c9756223d55e23734fef26..667bb5d8580a4962275f575f18081ff106a9701d 100644 (file)
@@ -2,7 +2,7 @@
 import std;
 
 export fold;
-export fold_crate, fold_mod, fold_fn, fold_modlist, fold_fnlist;
+export fold_crate, fold_mod, fold_fn;
 export default_seq_fold;
 export default_seq_fold_crate;
 export default_seq_fold_mod;
@@ -10,7 +10,9 @@
 export default_seq_fold_const;
 export default_seq_fold_enum;
 export default_seq_fold_res;
-export default_seq_fold_fnlist;
+export default_seq_fold_iface;
+export default_seq_fold_impl;
+export default_seq_fold_type;
 
 enum fold<T> = t<T>;
 
 type fold_const<T> = fn~(fold: fold<T>, doc: doc::constdoc) -> doc::constdoc;
 type fold_enum<T> = fn~(fold: fold<T>, doc: doc::enumdoc) -> doc::enumdoc;
 type fold_res<T> = fn~(fold: fold<T>, doc: doc::resdoc) -> doc::resdoc;
-type fold_modlist<T> = fn~(fold: fold<T>, list: doc::modlist) -> doc::modlist;
-type fold_fnlist<T> = fn~(fold: fold<T>, list: doc::fnlist) -> doc::fnlist;
-type fold_constlist<T> = fn~(
-    fold: fold<T>, list: doc::constlist) -> doc::constlist;
-type fold_enumlist<T> = fn~(
-    fold: fold<T>, list: doc::enumlist) -> doc::enumlist;
-type fold_reslist<T> = fn~(
-    fold: fold<T>, list: doc::reslist) -> doc::reslist;
+type fold_iface<T> = fn~(fold: fold<T>, doc: doc::ifacedoc) -> doc::ifacedoc;
+type fold_impl<T> = fn~(fold: fold<T>, doc: doc::impldoc) -> doc::impldoc;
+type fold_type<T> = fn~(fold: fold<T>, doc: doc::tydoc) -> doc::tydoc;
 
 type t<T> = {
     ctxt: T,
     fold_const: fold_const<T>,
     fold_enum: fold_enum<T>,
     fold_res: fold_res<T>,
-    fold_modlist: fold_modlist<T>,
-    fold_fnlist: fold_fnlist<T>,
-    fold_constlist: fold_constlist<T>,
-    fold_enumlist: fold_enumlist<T>,
-    fold_reslist: fold_reslist<T>
+    fold_iface: fold_iface<T>,
+    fold_impl: fold_impl<T>,
+    fold_type: fold_type<T>
 };
 
 
@@ -55,11 +50,9 @@ fn mk_fold<T:copy>(
     fold_const: fold_const<T>,
     fold_enum: fold_enum<T>,
     fold_res: fold_res<T>,
-    fold_modlist: fold_modlist<T>,
-    fold_fnlist: fold_fnlist<T>,
-    fold_constlist: fold_constlist<T>,
-    fold_enumlist: fold_enumlist<T>,
-    fold_reslist: fold_reslist<T>
+    fold_iface: fold_iface<T>,
+    fold_impl: fold_impl<T>,
+    fold_type: fold_type<T>
 ) -> fold<T> {
     fold({
         ctxt: ctxt,
@@ -69,11 +62,9 @@ fn mk_fold<T:copy>(
         fold_const: fold_const,
         fold_enum: fold_enum,
         fold_res: fold_res,
-        fold_modlist: fold_modlist,
-        fold_fnlist: fold_fnlist,
-        fold_constlist: fold_constlist,
-        fold_enumlist: fold_enumlist,
-        fold_reslist: fold_reslist
+        fold_iface: fold_iface,
+        fold_impl: fold_impl,
+        fold_type: fold_type
     })
 }
 
@@ -86,11 +77,9 @@ fn default_seq_fold<T:copy>(ctxt: T) -> fold<T> {
         {|f, d| default_seq_fold_const(f, d)},
         {|f, d| default_seq_fold_enum(f, d)},
         {|f, d| default_seq_fold_res(f, d)},
-        {|f, d| default_seq_fold_modlist(f, d)},
-        {|f, d| default_seq_fold_fnlist(f, d)},
-        {|f, d| default_seq_fold_constlist(f, d)},
-        {|f, d| default_seq_fold_enumlist(f, d)},
-        {|f, d| default_seq_fold_reslist(f, d)}
+        {|f, d| default_seq_fold_iface(f, d)},
+        {|f, d| default_seq_fold_impl(f, d)},
+        {|f, d| default_seq_fold_type(f, d)}
     )
 }
 
@@ -98,7 +87,7 @@ fn default_seq_fold_crate<T>(
     fold: fold<T>,
     doc: doc::cratedoc
 ) -> doc::cratedoc {
-    ~{
+    {
         topmod: fold.fold_mod(fold, doc.topmod)
     }
 }
@@ -107,13 +96,36 @@ fn default_seq_fold_mod<T>(
     fold: fold<T>,
     doc: doc::moddoc
 ) -> doc::moddoc {
-    ~{
-        mods: fold.fold_modlist(fold, doc.mods),
-        fns: fold.fold_fnlist(fold, doc.fns),
-        consts: fold.fold_constlist(fold, doc.consts),
-        enums: fold.fold_enumlist(fold, doc.enums),
-        resources: fold.fold_reslist(fold, doc.resources)
-        with *doc
+    {
+        items: ~vec::map(*doc.items) {|itemtag|
+            alt itemtag {
+              doc::modtag(moddoc) {
+                doc::modtag(fold.fold_mod(fold, moddoc))
+              }
+              doc::fntag(fndoc) {
+                doc::fntag(fold.fold_fn(fold, fndoc))
+              }
+              doc::consttag(constdoc) {
+                doc::consttag(fold.fold_const(fold, constdoc))
+              }
+              doc::enumtag(enumdoc) {
+                doc::enumtag(fold.fold_enum(fold, enumdoc))
+              }
+              doc::restag(resdoc) {
+                doc::restag(fold.fold_res(fold, resdoc))
+              }
+              doc::ifacetag(ifacedoc) {
+                doc::ifacetag(fold.fold_iface(fold, ifacedoc))
+              }
+              doc::impltag(impldoc) {
+                doc::impltag(fold.fold_impl(fold, impldoc))
+              }
+              doc::tytag(tydoc) {
+                doc::tytag(fold.fold_type(fold, tydoc))
+              }
+            }
+        }
+        with doc
     }
 }
 
@@ -145,49 +157,25 @@ fn default_seq_fold_res<T>(
     doc
 }
 
-fn default_seq_fold_modlist<T>(
-    fold: fold<T>,
-    list: doc::modlist
-) -> doc::modlist {
-    doc::modlist(vec::map(*list) {|doc|
-        fold.fold_mod(fold, doc)
-    })
-}
-
-fn default_seq_fold_fnlist<T>(
-    fold: fold<T>,
-    list: doc::fnlist
-) -> doc::fnlist {
-    doc::fnlist(vec::map(*list) {|doc|
-        fold.fold_fn(fold, doc)
-    })
-}
-
-fn default_seq_fold_constlist<T>(
-    fold: fold<T>,
-    list: doc::constlist
-) -> doc::constlist {
-    doc::constlist(vec::map(*list) {|doc|
-        fold.fold_const(fold, doc)
-    })
+fn default_seq_fold_iface<T>(
+    _fold: fold<T>,
+    doc: doc::ifacedoc
+) -> doc::ifacedoc {
+    doc
 }
 
-fn default_seq_fold_enumlist<T>(
-    fold: fold<T>,
-    list: doc::enumlist
-) -> doc::enumlist {
-    doc::enumlist(vec::map(*list) {|doc|
-        fold.fold_enum(fold, doc)
-    })
+fn default_seq_fold_impl<T>(
+    _fold: fold<T>,
+    doc: doc::impldoc
+) -> doc::impldoc {
+    doc
 }
 
-fn default_seq_fold_reslist<T>(
-    fold: fold<T>,
-    list: doc::reslist
-) -> doc::reslist {
-    doc::reslist(vec::map(*list) {|doc|
-        fold.fold_res(fold, doc)
-    })
+fn default_seq_fold_type<T>(
+    _fold: fold<T>,
+    doc: doc::tydoc
+) -> doc::tydoc {
+    doc
 }
 
 #[test]
index 4082d969b5e578df549177065bf68156a3f7a584..c15d6adc7bac248d7e42c18040e181ff96c24376 100644 (file)
@@ -5,16 +5,65 @@
 
 export mk_pass;
 
+// FIXME: This is a really convoluted interface to work around trying
+// to get a writer into a unique closure and then being able to test
+// what was written afterward
 fn mk_pass(
-    writer: fn~() -> io::writer
+    give_writer: fn~(fn(io::writer))
 ) -> pass {
-    ret fn~(
-        _srv: astsrv::srv,
+    fn~(
+        srv: astsrv::srv,
         doc: doc::cratedoc
     ) -> doc::cratedoc {
-        write_markdown(doc, writer());
+
+        fn mods_last(item1: doc::itemtag, item2: doc::itemtag) -> bool {
+            fn is_mod(item: doc::itemtag) -> bool {
+                alt item {
+                  doc::modtag(_) { true }
+                  _ { false }
+                }
+            }
+
+            let lteq = !is_mod(item1) || is_mod(item2);
+            lteq
+        }
+
+        give_writer {|writer|
+            // Sort the items so mods come last. All mods will be
+            // output at the same header level so sorting mods last
+            // makes the headers come out nested correctly.
+            let sorted_doc = sort_pass::mk_pass(mods_last)(srv, doc);
+
+            write_markdown(sorted_doc, writer);
+        }
         doc
-    };
+    }
+}
+
+#[test]
+fn should_write_modules_last() {
+    /*
+    Because the markdown pass writes all modules at the same level of
+    indentation (it doesn't 'nest' them), we need to make sure that we
+    write all of the modules contained in each module after all other
+    types of items, or else the header nesting will end up wrong, with
+    modules appearing to contain items that they do not.
+    */
+    let markdown = test::render(
+        "mod a { }\
+         fn b() { }\
+         mod c { }\
+         fn d() { }"
+    );
+
+    let idx_a = str::find(markdown, "# Module `a`");
+    let idx_b = str::find(markdown, "## Function `b`");
+    let idx_c = str::find(markdown, "# Module `c`");
+    let idx_d = str::find(markdown, "## Function `d`");
+
+    assert idx_b < idx_d;
+    assert idx_d < idx_a;
+    assert idx_a < idx_c;
 }
 
 type ctxt = {
@@ -81,24 +130,17 @@ fn write_mod_contents(
     write_brief(ctxt, doc.brief);
     write_desc(ctxt, doc.desc);
 
-    for constdoc in *doc.consts {
-        write_const(ctxt, constdoc);
-    }
-
-    for enumdoc in *doc.enums {
-        write_enum(ctxt, enumdoc);
-    }
-
-    for fndoc in *doc.fns {
-        write_fn(ctxt, fndoc);
-    }
-
-    for resdoc in *doc.resources {
-        write_res(ctxt, resdoc);
-    }
-
-    for moddoc in *doc.mods {
-        write_mod(ctxt, moddoc);
+    for itemtag in *doc.items {
+        alt itemtag {
+          doc::modtag(moddoc) { write_mod(ctxt, moddoc) }
+          doc::fntag(fndoc) { write_fn(ctxt, fndoc) }
+          doc::consttag(constdoc) { write_const(ctxt, constdoc) }
+          doc::enumtag(enumdoc) { write_enum(ctxt, enumdoc) }
+          doc::restag(resdoc) { write_res(ctxt, resdoc) }
+          doc::ifacetag(ifacedoc) { write_iface(ctxt, ifacedoc) }
+          doc::impltag(impldoc) { write_impl(ctxt, impldoc) }
+          doc::tytag(tydoc) { write_type(ctxt, tydoc) }
+        }
     }
 }
 
@@ -119,12 +161,32 @@ fn write_fn(
     doc: doc::fndoc
 ) {
     write_header(ctxt, h2, #fmt("Function `%s`", doc.name));
-    write_sig(ctxt, doc.sig);
-    write_brief(ctxt, doc.brief);
-    write_desc(ctxt, doc.desc);
-    write_args(ctxt, doc.args);
-    write_return(ctxt, doc.return);
-    write_failure(ctxt, doc.failure);
+    write_fnlike(
+        ctxt,
+        doc.sig,
+        doc.brief,
+        doc.desc,
+        doc.args,
+        doc.return,
+        doc.failure
+    );
+}
+
+fn write_fnlike(
+    ctxt: ctxt,
+    sig: option<str>,
+    brief: option<str>,
+    desc: option<str>,
+    args: [doc::argdoc],
+    return: doc::retdoc,
+    failure: option<str>
+) {
+    write_sig(ctxt, sig);
+    write_brief(ctxt, brief);
+    write_desc(ctxt, desc);
+    write_args(ctxt, args);
+    write_return(ctxt, return);
+    write_failure(ctxt, failure);
 }
 
 fn write_sig(ctxt: ctxt, sig: option<str>) {
@@ -164,15 +226,15 @@ fn should_insert_blank_line_after_fn_signature() {
 #[test]
 fn should_correctly_indent_fn_signature() {
     let doc = test::create_doc("fn a() { }");
-    let doc = ~{
-        topmod: ~{
-            fns: doc::fnlist([~{
+    let doc = {
+        topmod: {
+            items: ~[doc::fntag({
                 sig: some("line 1\nline 2")
-                with *doc.topmod.fns[0]
-            }])
-            with *doc.topmod
+                with doc.topmod.fns()[0]
+            })]
+            with doc.topmod
         }
-        with *doc
+        with doc
     };
     let markdown = test::write_markdown_str(doc);
     assert str::contains(markdown, "    line 1\n    line 2");
@@ -494,16 +556,240 @@ fn should_write_resource_args() {
     assert str::contains(markdown, "Arguments:\n\n* `a`: `bool` - b");
 }
 
+fn write_iface(ctxt: ctxt, doc: doc::ifacedoc) {
+    write_header(ctxt, h2, #fmt("Interface `%s`", doc.name));
+    write_brief(ctxt, doc.brief);
+    write_desc(ctxt, doc.desc);
+    write_methods(ctxt, doc.methods);
+}
+
+fn write_methods(ctxt: ctxt, docs: [doc::methoddoc]) {
+    vec::iter(docs) {|doc| write_method(ctxt, doc) }
+}
+
+fn write_method(ctxt: ctxt, doc: doc::methoddoc) {
+    write_header(ctxt, h3, #fmt("Method `%s`", doc.name));
+    write_fnlike(
+        ctxt,
+        doc.sig,
+        doc.brief,
+        doc.desc,
+        doc.args,
+        doc.return,
+        doc.failure
+    );
+}
+
+#[test]
+fn should_write_iface_header() {
+    let markdown = test::render("iface i { fn a(); }");
+    assert str::contains(markdown, "## Interface `i`");
+}
+
+#[test]
+fn should_write_iface_brief() {
+    let markdown = test::render(
+        "#[doc(brief = \"brief\")] iface i { fn a(); }");
+    assert str::contains(markdown, "brief");
+}
+
+#[test]
+fn should_write_iface_desc() {
+    let markdown = test::render(
+        "#[doc(desc = \"desc\")] iface i { fn a(); }");
+    assert str::contains(markdown, "desc");
+}
+
+#[test]
+fn should_write_iface_method_header() {
+    let markdown = test::render(
+        "iface i { fn a(); }");
+    assert str::contains(markdown, "### Method `a`");
+}
+
+#[test]
+fn should_write_iface_method_signature() {
+    let markdown = test::render(
+        "iface i { fn a(); }");
+    assert str::contains(markdown, "\n    fn a()");
+}
+
+#[test]
+fn should_write_iface_method_argument_header() {
+    let markdown = test::render(
+        "iface a { fn a(b: int); }");
+    assert str::contains(markdown, "\n\nArguments:\n\n");
+}
+
+#[test]
+fn should_write_iface_method_arguments() {
+    let markdown = test::render(
+        "iface a { fn a(b: int); }");
+    assert str::contains(markdown, "* `b`: `int`\n");
+}
+
+#[test]
+fn should_not_write_iface_method_arguments_if_none() {
+    let markdown = test::render(
+        "iface a { fn a(); }");
+    assert !str::contains(markdown, "Arguments");
+}
+
+#[test]
+fn should_write_iface_method_return_info() {
+    let markdown = test::render(
+        "iface a { fn a() -> int; }");
+    assert str::contains(markdown, "Returns `int`");
+}
+
+#[test]
+fn should_write_iface_method_failure_conditions() {
+    let markdown = test::render(
+        "iface a { #[doc(failure = \"nuked\")] fn a(); }");
+    assert str::contains(markdown, "Failure conditions: nuked");
+}
+
+fn write_impl(ctxt: ctxt, doc: doc::impldoc) {
+    assert option::is_some(doc.self_ty);
+    let self_ty = option::get(doc.self_ty);
+    alt doc.iface_ty {
+      some(iface_ty) {
+        write_header(ctxt, h2,
+                     #fmt("Implementation `%s` of `%s` for `%s`",
+                          doc.name, iface_ty, self_ty));
+      }
+      none {
+        write_header(ctxt, h2,
+                     #fmt("Implementation `%s` for `%s`",
+                          doc.name, self_ty));
+      }
+    }
+    write_brief(ctxt, doc.brief);
+    write_desc(ctxt, doc.desc);
+    write_methods(ctxt, doc.methods);
+}
+
+#[test]
+fn should_write_impl_header() {
+    let markdown = test::render("impl i for int { fn a() { } }");
+    assert str::contains(markdown, "## Implementation `i` for `int`");
+}
+
+#[test]
+fn should_write_impl_header_with_iface() {
+    let markdown = test::render("impl i of j for int { fn a() { } }");
+    assert str::contains(markdown, "## Implementation `i` of `j` for `int`");
+}
+
+#[test]
+fn should_write_impl_brief() {
+    let markdown = test::render(
+        "#[doc(brief = \"brief\")] impl i for int { fn a() { } }");
+    assert str::contains(markdown, "brief");
+}
+
+#[test]
+fn should_write_impl_desc() {
+    let markdown = test::render(
+        "#[doc(desc = \"desc\")] impl i for int { fn a() { } }");
+    assert str::contains(markdown, "desc");
+}
+
+#[test]
+fn should_write_impl_method_header() {
+    let markdown = test::render(
+        "impl i for int { fn a() { } }");
+    assert str::contains(markdown, "### Method `a`");
+}
+
+#[test]
+fn should_write_impl_method_signature() {
+    let markdown = test::render(
+        "impl i for int { fn a() { } }");
+    assert str::contains(markdown, "\n    fn a()");
+}
+
+#[test]
+fn should_write_impl_method_argument_header() {
+    let markdown = test::render(
+        "impl a for int { fn a(b: int) { } }");
+    assert str::contains(markdown, "\n\nArguments:\n\n");
+}
+
+#[test]
+fn should_write_impl_method_arguments() {
+    let markdown = test::render(
+        "impl a for int { fn a(b: int) { } }");
+    assert str::contains(markdown, "* `b`: `int`\n");
+}
+
+#[test]
+fn should_not_write_impl_method_arguments_if_none() {
+    let markdown = test::render(
+        "impl a for int { fn a() { } }");
+    assert !str::contains(markdown, "Arguments");
+}
+
+#[test]
+fn should_write_impl_method_return_info() {
+    let markdown = test::render(
+        "impl a for int { fn a() -> int { } }");
+    assert str::contains(markdown, "Returns `int`");
+}
+
+#[test]
+fn should_write_impl_method_failure_conditions() {
+    let markdown = test::render(
+        "impl a for int { #[doc(failure = \"nuked\")] fn a() { } }");
+    assert str::contains(markdown, "Failure conditions: nuked");
+}
+
+fn write_type(
+    ctxt: ctxt,
+    doc: doc::tydoc
+) {
+    write_header(ctxt, h2, #fmt("Type `%s`", doc.name));
+    write_sig(ctxt, doc.sig);
+    write_brief(ctxt, doc.brief);
+    write_desc(ctxt, doc.desc);
+}
+
+#[test]
+fn should_write_type_header() {
+    let markdown = test::render("type t = int;");
+    assert str::contains(markdown, "## Type `t`");
+}
+
+#[test]
+fn should_write_type_brief() {
+    let markdown = test::render(
+        "#[doc(brief = \"brief\")] type t = int;");
+    assert str::contains(markdown, "\n\nbrief\n\n");
+}
+
+#[test]
+fn should_write_type_desc() {
+    let markdown = test::render(
+        "#[doc(desc = \"desc\")] type t = int;");
+    assert str::contains(markdown, "\n\ndesc\n\n");
+}
+
+#[test]
+fn should_write_type_signature() {
+    let markdown = test::render("type t = int;");
+    assert str::contains(markdown, "\n\n    type t = int\n\n");
+}
+
 #[cfg(test)]
 mod test {
     fn render(source: str) -> str {
-        let doc = create_doc(source);
-        let markdown = write_markdown_str(doc);
+        let (srv, doc) = create_doc_srv(source);
+        let markdown = write_markdown_str_srv(srv, doc);
         #debug("markdown: %s", markdown);
         markdown
     }
 
-    fn create_doc(source: str) -> doc::cratedoc {
+    fn create_doc_srv(source: str) -> (astsrv::srv, doc::cratedoc) {
         let srv = astsrv::mk_srv_from_str(source);
         let doc = extract::from_srv(srv, "");
         #debug("doc (extract): %?", doc);
@@ -513,6 +799,11 @@ fn create_doc(source: str) -> doc::cratedoc {
         #debug("doc (path): %?", doc);
         let doc = attr_pass::mk_pass()(srv, doc);
         #debug("doc (attr): %?", doc);
+        (srv, doc)
+    }
+
+    fn create_doc(source: str) -> doc::cratedoc {
+        let (_, doc) = create_doc_srv(source);
         doc
     }
 
@@ -525,6 +816,24 @@ fn write_markdown_str(
         ret io::mem_buffer_str(buffer);
     }
 
+    fn write_markdown_str_srv(
+        srv: astsrv::srv,
+        doc: doc::cratedoc
+    ) -> str {
+        let port = comm::port();
+        let chan = comm::chan(port);
+
+        let pass = mk_pass {|f|
+            let buffer = io::mk_mem_buffer();
+            let writer = io::mem_buffer_writer(buffer);
+            f(writer);
+            let result = io::mem_buffer_str(buffer);
+            comm::send(chan, result);
+        };
+        pass(srv, doc);
+        ret comm::recv(port);
+    }
+
     #[test]
     fn write_markdown_should_write_crate_header() {
         let srv = astsrv::mk_srv_from_str("");
index 5bc867dd036ca3f1fda8f2e9fdce684030164f5d..c8b13d92769e755d85ee0ba47ae6b75afdfd5ac7 100644 (file)
@@ -43,4 +43,4 @@ fn from_str_sess(sess: session::session, source: str) -> @ast::crate {
 
 fn cfg(sess: session::session) -> ast::crate_cfg {
     driver::default_configuration(sess, "rustdoc", "<anon>")
-}
\ No newline at end of file
+}
index 9bcdde561c4e342f45e2014cc48bdedc4db4b3a3..0da88fbac42002a5d368a2b9e0d3d3bb4227a0b8 100644 (file)
@@ -32,9 +32,9 @@ fn fold_mod(fold: fold::fold<ctxt>, doc: doc::moddoc) -> doc::moddoc {
     if !is_topmod { vec::push(fold.ctxt.path, doc.name); }
     let doc = fold::default_seq_fold_mod(fold, doc);
     if !is_topmod { vec::pop(fold.ctxt.path); }
-    ~{
+    {
         path: fold.ctxt.path
-        with *doc
+        with doc
     }
 }
 
@@ -44,6 +44,6 @@ fn should_record_mod_paths() {
     let srv = astsrv::mk_srv_from_str(source);
     let doc = extract::from_srv(srv, "");
     let doc = run(srv, doc);
-    assert doc.topmod.mods[0].mods[0].mods[0].path == ["a", "b"];
-    assert doc.topmod.mods[0].mods[1].mods[0].path == ["a", "d"];
+    assert doc.topmod.mods()[0].mods()[0].mods()[0].path == ["a", "b"];
+    assert doc.topmod.mods()[0].mods()[1].mods()[0].path == ["a", "d"];
 }
\ No newline at end of file
diff --git a/src/rustdoc/prune_undoc_details_pass.rs b/src/rustdoc/prune_undoc_details_pass.rs
new file mode 100644 (file)
index 0000000..0dd66ff
--- /dev/null
@@ -0,0 +1,162 @@
+#[doc = "Prunes args, retvals of the document tree that \
+         contain no documentation"];
+
+export mk_pass;
+
+fn mk_pass() -> pass {
+    run
+}
+
+fn run(
+    _srv: astsrv::srv,
+    doc: doc::cratedoc
+) -> doc::cratedoc {
+    let fold = fold::fold({
+        fold_fn: fold_fn,
+        fold_res: fold_res,
+        fold_iface: fold_iface,
+        fold_impl: fold_impl
+        with *fold::default_seq_fold(())
+    });
+    fold.fold_crate(fold, doc)
+}
+
+fn fold_fn(
+    fold: fold::fold<()>,
+    doc: doc::fndoc
+) -> doc::fndoc {
+    let doc = fold::default_seq_fold_fn(fold, doc);
+
+    {
+        args: prune_args(doc.args),
+        return: prune_return(doc.return)
+        with doc
+    }
+}
+
+fn prune_args(docs: [doc::argdoc]) -> [doc::argdoc] {
+    vec::filter_map(docs) {|doc|
+        if option::is_some(doc.desc) {
+            some(doc)
+        } else {
+            none
+        }
+    }
+}
+
+fn prune_return(doc: doc::retdoc) -> doc::retdoc {
+    {
+        ty: if option::is_some(doc.desc) {
+            doc.ty
+        } else {
+            none
+        }
+        with doc
+    }
+}
+
+#[test]
+fn should_elide_undocumented_arguments() {
+    let doc = test::mk_doc("#[doc = \"hey\"] fn a(b: int) { }");
+    assert vec::is_empty(doc.topmod.fns()[0].args);
+}
+
+#[test]
+fn should_elide_undocumented_return_values() {
+    let source = "#[doc = \"fonz\"] fn a() -> int { }";
+    let srv = astsrv::mk_srv_from_str(source);
+    let doc = extract::from_srv(srv, "");
+    let doc = tystr_pass::mk_pass()(srv, doc);
+    let doc = attr_pass::mk_pass()(srv, doc);
+    let doc = run(srv, doc);
+    assert doc.topmod.fns()[0].return.ty == none;
+}
+
+fn fold_res(
+    fold: fold::fold<()>,
+    doc: doc::resdoc
+) -> doc::resdoc {
+    let doc = fold::default_seq_fold_res(fold, doc);
+
+    {
+        args: prune_args(doc.args)
+        with doc
+    }
+}
+
+#[test]
+fn should_elide_undocumented_resource_args() {
+    let doc = test::mk_doc("#[doc = \"drunk\"]\
+                            resource r(a: bool) { }");
+    assert vec::is_empty(doc.topmod.resources()[0].args);
+}
+
+fn fold_iface(
+    fold: fold::fold<()>,
+    doc: doc::ifacedoc
+) -> doc::ifacedoc {
+    let doc = fold::default_seq_fold_iface(fold, doc);
+
+    {
+        methods: prune_methods(doc.methods)
+        with doc
+    }
+}
+
+fn prune_methods(docs: [doc::methoddoc]) -> [doc::methoddoc] {
+    vec::map(docs) {|doc|
+        {
+            args: prune_args(doc.args),
+            return: prune_return(doc.return)
+            with doc
+        }
+    }
+}
+
+#[test]
+fn should_elide_undocumented_iface_method_args() {
+    let doc = test::mk_doc("#[doc = \"hey\"] iface i { fn a(); }");
+    assert vec::is_empty(doc.topmod.ifaces()[0].methods[0].args);
+}
+
+#[test]
+fn should_elide_undocumented_iface_method_return_values() {
+    let doc = test::mk_doc("#[doc = \"hey\"] iface i { fn a() -> int; }");
+    assert doc.topmod.ifaces()[0].methods[0].return.ty == none;
+}
+
+fn fold_impl(
+    fold: fold::fold<()>,
+    doc: doc::impldoc
+) -> doc::impldoc {
+    let doc = fold::default_seq_fold_impl(fold, doc);
+
+    {
+        methods: prune_methods(doc.methods)
+        with doc
+    }
+}
+
+#[test]
+fn should_elide_undocumented_impl_method_args() {
+    let doc = test::mk_doc(
+        "#[doc = \"hey\"] impl i for int { fn a(b: bool) { } }");
+    assert vec::is_empty(doc.topmod.impls()[0].methods[0].args);
+}
+
+#[test]
+fn should_elide_undocumented_impl_method_return_values() {
+    let doc = test::mk_doc(
+        "#[doc = \"hey\"] impl i for int { fn a() -> int { } }");
+    assert doc.topmod.impls()[0].methods[0].return.ty == none;
+}
+
+#[cfg(test)]
+mod test {
+    fn mk_doc(source: str) -> doc::cratedoc {
+        let srv = astsrv::mk_srv_from_str(source);
+        let doc = extract::from_srv(srv, "");
+        let doc = attr_pass::mk_pass()(srv, doc);
+        run(srv, doc)
+    }
+}
diff --git a/src/rustdoc/prune_undoc_items_pass.rs b/src/rustdoc/prune_undoc_items_pass.rs
new file mode 100644 (file)
index 0000000..3ff29bd
--- /dev/null
@@ -0,0 +1,373 @@
+#[doc = "Prunes items of the document tree that contain no documentation"];
+
+export mk_pass;
+
+fn mk_pass() -> pass {
+    run
+}
+
+type ctxt = {
+    mutable have_docs: bool
+};
+
+fn run(
+    _srv: astsrv::srv,
+    doc: doc::cratedoc
+) -> doc::cratedoc {
+    let ctxt = {
+        mutable have_docs: true
+    };
+    let fold = fold::fold({
+        fold_mod: fold_mod,
+        fold_fn: fold_fn,
+        fold_const: fold_const,
+        fold_enum: fold_enum,
+        fold_res: fold_res,
+        fold_iface: fold_iface,
+        fold_impl: fold_impl,
+        fold_type: fold_type
+        with *fold::default_seq_fold(ctxt)
+    });
+    fold.fold_crate(fold, doc)
+}
+
+fn fold_mod(
+    fold: fold::fold<ctxt>,
+    doc: doc::moddoc
+) -> doc::moddoc {
+    let doc = {
+        items: ~vec::filter_map(*doc.items) {|itemtag|
+            alt itemtag {
+              doc::modtag(moddoc) {
+                let doc = fold.fold_mod(fold, moddoc);
+                if fold.ctxt.have_docs {
+                    some(doc::modtag(doc))
+                } else {
+                    none
+                }
+              }
+              doc::fntag(fndoc) {
+                let doc = fold.fold_fn(fold, fndoc);
+                if fold.ctxt.have_docs {
+                    some(doc::fntag(doc))
+                } else {
+                    none
+                }
+              }
+              doc::consttag(constdoc) {
+                let doc = fold.fold_const(fold, constdoc);
+                if fold.ctxt.have_docs {
+                    some(doc::consttag(doc))
+                } else {
+                    none
+                }
+              }
+              doc::enumtag(enumdoc) {
+                let doc = fold.fold_enum(fold, enumdoc);
+                if fold.ctxt.have_docs {
+                    some(doc::enumtag(doc))
+                } else {
+                    none
+                }
+              }
+              doc::restag(resdoc) {
+                let doc = fold.fold_res(fold, resdoc);
+                if fold.ctxt.have_docs {
+                    some(doc::restag(doc))
+                } else {
+                    none
+                }
+              }
+              doc::ifacetag(ifacedoc) {
+                let doc = fold.fold_iface(fold, ifacedoc);
+                if fold.ctxt.have_docs {
+                    some(doc::ifacetag(doc))
+                } else {
+                    none
+                }
+              }
+              doc::impltag(impldoc) {
+                let doc = fold.fold_impl(fold, impldoc);
+                if fold.ctxt.have_docs {
+                    some(doc::impltag(doc))
+                } else {
+                    none
+                }
+              }
+              doc::tytag(tydoc) {
+                let doc = fold.fold_type(fold, tydoc);
+                if fold.ctxt.have_docs {
+                    some(doc::tytag(doc))
+                } else {
+                    none
+                }
+              }
+              _ { some(itemtag) }
+            }
+        }
+        with fold::default_seq_fold_mod(fold, doc)
+    };
+    fold.ctxt.have_docs =
+        doc.brief != none
+        || doc.desc != none
+        || vec::is_not_empty(*doc.items);
+    ret doc;
+}
+
+fn fold_fn(
+    fold: fold::fold<ctxt>,
+    doc: doc::fndoc
+) -> doc::fndoc {
+    let doc = fold::default_seq_fold_fn(fold, doc);
+
+    fold.ctxt.have_docs =
+        doc.brief != none
+        || doc.desc != none
+        || args_have_docs(doc.args)
+        || doc.return.desc != none
+        || doc.failure != none;
+    ret doc;
+}
+
+fn args_have_docs(docs: [doc::argdoc]) -> bool {
+    vec::foldl(false, docs) {|accum, doc|
+        accum || doc.desc != none
+    }
+}
+
+#[test]
+fn should_elide_fns_with_undocumented_arguments() {
+    let doc = test::mk_doc("fn a(a: int) { }");
+    assert vec::is_empty(doc.topmod.fns());
+}
+
+#[test]
+fn should_not_elide_fns_with_documented_arguments() {
+    let doc = test::mk_doc("#[doc(args(a = \"b\"))] fn a(a: int) { }");
+    assert vec::is_not_empty(doc.topmod.fns());
+}
+
+#[test]
+fn should_not_elide_fns_with_documented_failure_conditions() {
+    let doc = test::mk_doc("#[doc(failure = \"yup\")] fn a() { }");
+    assert vec::is_not_empty(doc.topmod.fns());
+}
+
+#[test]
+fn should_elide_undocumented_mods() {
+    let doc = test::mk_doc("mod a { }");
+    assert vec::is_empty(doc.topmod.mods());
+}
+
+#[test]
+fn should_not_elide_undocument_mods_with_documented_mods() {
+    let doc = test::mk_doc("mod a { #[doc = \"b\"] mod b { } }");
+    assert vec::is_not_empty(doc.topmod.mods());
+}
+
+#[test]
+fn should_not_elide_undocument_mods_with_documented_fns() {
+    let doc = test::mk_doc("mod a { #[doc = \"b\"] fn b() { } }");
+    assert vec::is_not_empty(doc.topmod.mods());
+}
+
+#[test]
+fn should_elide_undocumented_fns() {
+    let doc = test::mk_doc("fn a() { }");
+    assert vec::is_empty(doc.topmod.fns());
+}
+
+fn fold_const(
+    fold: fold::fold<ctxt>,
+    doc: doc::constdoc
+) -> doc::constdoc {
+    let doc = fold::default_seq_fold_const(fold, doc);
+    fold.ctxt.have_docs =
+        doc.brief != none
+        || doc.desc != none;
+    ret doc;
+}
+
+#[test]
+fn should_elide_undocumented_consts() {
+    let doc = test::mk_doc("const a: bool = true;");
+    assert vec::is_empty(doc.topmod.consts());
+}
+
+fn fold_enum(fold: fold::fold<ctxt>, doc: doc::enumdoc) -> doc::enumdoc {
+    let doc = {
+        variants: vec::filter_map(doc.variants) {|variant|
+            if variant.desc != none {
+                some(variant)
+            } else {
+                none
+            }
+        }
+        with fold::default_seq_fold_enum(fold, doc)
+    };
+    fold.ctxt.have_docs =
+        doc.brief != none
+        || doc.desc != none
+        || vec::is_not_empty(doc.variants);
+    ret doc;
+}
+
+#[test]
+fn should_elide_undocumented_enums() {
+    let doc = test::mk_doc("enum a { b }");
+    assert vec::is_empty(doc.topmod.enums());
+}
+
+#[test]
+fn should_elide_undocumented_variants() {
+    let doc = test::mk_doc("#[doc = \"a\"] enum a { b }");
+    assert vec::is_empty(doc.topmod.enums()[0].variants);
+}
+
+#[test]
+fn should_not_elide_enums_with_documented_variants() {
+    let doc = test::mk_doc("enum a { #[doc = \"a\"] b }");
+    assert vec::is_not_empty(doc.topmod.enums());
+}
+
+fn fold_res(fold: fold::fold<ctxt>, doc: doc::resdoc) -> doc::resdoc {
+    let doc = fold::default_seq_fold_res(fold, doc);
+
+    fold.ctxt.have_docs =
+        doc.brief != none
+        || doc.desc != none
+        || args_have_docs(doc.args);
+    ret doc;
+}
+
+#[test]
+fn should_elide_undocumented_resources() {
+    let doc = test::mk_doc("resource r(a: bool) { }");
+    assert vec::is_empty(doc.topmod.resources());
+}
+
+#[test]
+fn should_not_elide_resources_with_documented_args() {
+    let doc = test::mk_doc("#[doc(args(a = \"drunk\"))]\
+                            resource r(a: bool) { }");
+    assert vec::is_not_empty(doc.topmod.resources());
+}
+
+fn fold_iface(
+    fold: fold::fold<ctxt>,
+    doc: doc::ifacedoc
+) -> doc::ifacedoc {
+    let doc = fold::default_seq_fold_iface(fold, doc);
+
+    fold.ctxt.have_docs =
+        doc.brief != none
+        || doc.desc != none
+        || methods_have_docs(doc.methods);
+    ret doc;
+}
+
+fn methods_have_docs(docs: [doc::methoddoc]) -> bool {
+    vec::foldl(false, docs) {|accum, doc|
+        accum
+            || doc.brief != none
+            || doc.desc != none
+            || args_have_docs(doc.args)
+            || doc.return.desc != none
+            || doc.failure != none
+    }
+}
+
+#[test]
+fn should_elide_undocumented_ifaces() {
+    let doc = test::mk_doc("iface i { fn a(); }");
+    assert vec::is_empty(doc.topmod.ifaces());
+}
+
+#[test]
+fn should_not_elide_documented_ifaces() {
+    let doc = test::mk_doc("#[doc = \"hey\"] iface i { fn a(); }");
+    assert vec::is_not_empty(doc.topmod.ifaces());
+}
+
+#[test]
+fn should_elide_ifaces_with_undocumented_args() {
+    let doc = test::mk_doc("iface i { fn a(b: bool); }");
+    assert vec::is_empty(doc.topmod.ifaces());
+}
+
+#[test]
+fn should_not_elide_ifaces_with_documented_methods() {
+    let doc = test::mk_doc("iface i { #[doc = \"hey\"] fn a(); }");
+    assert vec::is_not_empty(doc.topmod.ifaces());
+}
+
+#[test]
+fn should_not_elide_undocumented_iface_methods() {
+    let doc = test::mk_doc("#[doc = \"hey\"] iface i { fn a(); }");
+    assert vec::is_not_empty(doc.topmod.ifaces()[0].methods);
+}
+
+fn fold_impl(
+    fold: fold::fold<ctxt>,
+    doc: doc::impldoc
+) -> doc::impldoc {
+    let doc = fold::default_seq_fold_impl(fold, doc);
+
+    fold.ctxt.have_docs =
+        doc.brief != none
+        || doc.desc != none
+        || methods_have_docs(doc.methods);
+    ret doc;
+}
+
+#[test]
+fn should_elide_undocumented_impls() {
+    let doc = test::mk_doc("impl i for int { fn a() { } }");
+    assert vec::is_empty(doc.topmod.impls());
+}
+
+#[test]
+fn should_not_elide_documented_impls() {
+    let doc = test::mk_doc("#[doc = \"hey\"] impl i for int { fn a() { } }");
+    assert vec::is_not_empty(doc.topmod.impls());
+}
+
+#[test]
+fn should_not_elide_impls_with_documented_methods() {
+    let doc = test::mk_doc("impl i for int { #[doc = \"hey\"] fn a() { } }");
+    assert vec::is_not_empty(doc.topmod.impls());
+}
+
+#[test]
+fn should_not_elide_undocumented_impl_methods() {
+    let doc = test::mk_doc("#[doc = \"hey\"] impl i for int { fn a() { } }");
+    assert vec::is_not_empty(doc.topmod.impls()[0].methods);
+}
+
+fn fold_type(
+    fold: fold::fold<ctxt>,
+    doc: doc::tydoc
+) -> doc::tydoc {
+    let doc = fold::default_seq_fold_type(fold, doc);
+
+    fold.ctxt.have_docs =
+        doc.brief != none
+        || doc.desc != none;
+    ret doc;
+}
+
+#[test]
+fn should_elide_undocumented_types() {
+    let doc = test::mk_doc("type t = int;");
+    assert vec::is_empty(doc.topmod.types());
+}
+
+#[cfg(test)]
+mod test {
+    fn mk_doc(source: str) -> doc::cratedoc {
+        let srv = astsrv::mk_srv_from_str(source);
+        let doc = extract::from_srv(srv, "");
+        let doc = attr_pass::mk_pass()(srv, doc);
+        run(srv, doc)
+    }
+}
diff --git a/src/rustdoc/prune_undoc_pass.rs b/src/rustdoc/prune_undoc_pass.rs
deleted file mode 100644 (file)
index 11be00e..0000000
+++ /dev/null
@@ -1,347 +0,0 @@
-#[doc = "Prunes branches of the document tree that contain no documentation"];
-
-export mk_pass;
-
-fn mk_pass() -> pass {
-    run
-}
-
-type ctxt = {
-    mutable have_docs: bool
-};
-
-fn run(
-    _srv: astsrv::srv,
-    doc: doc::cratedoc
-) -> doc::cratedoc {
-    let ctxt = {
-        mutable have_docs: true
-    };
-    let fold = fold::fold({
-        fold_mod: fold_mod,
-        fold_fn: fold_fn,
-        fold_const: fold_const,
-        fold_enum: fold_enum,
-        fold_res: fold_res,
-        fold_modlist: fold_modlist,
-        fold_fnlist: fold_fnlist,
-        fold_constlist: fold_constlist,
-        fold_enumlist: fold_enumlist,
-        fold_reslist: fold_reslist
-        with *fold::default_seq_fold(ctxt)
-    });
-    fold.fold_crate(fold, doc)
-}
-
-fn fold_mod(
-    fold: fold::fold<ctxt>,
-    doc: doc::moddoc
-) -> doc::moddoc {
-    let doc = fold::default_seq_fold_mod(fold, doc);
-    fold.ctxt.have_docs =
-        doc.brief != none
-        || doc.desc != none
-        || vec::is_not_empty(*doc.mods)
-        || vec::is_not_empty(*doc.fns);
-    ret doc;
-}
-
-fn fold_fn(
-    fold: fold::fold<ctxt>,
-    doc: doc::fndoc
-) -> doc::fndoc {
-    let have_arg_docs = false;
-    let doc = ~{
-        args: vec::filter_map(doc.args) {|doc|
-            if option::is_some(doc.desc) {
-                have_arg_docs = true;
-                some(doc)
-            } else {
-                none
-            }
-        },
-        return: {
-            ty: if option::is_some(doc.return.desc) {
-                doc.return.ty
-            } else {
-                none
-            }
-            with doc.return
-        }
-        with *doc
-    };
-
-    fold.ctxt.have_docs =
-        doc.brief != none
-        || doc.desc != none
-        || have_arg_docs
-        || doc.return.desc != none
-        || doc.failure != none;
-    ret doc;
-}
-
-#[test]
-fn should_elide_undocumented_arguments() {
-    let source = "#[doc = \"hey\"] fn a(b: int) { }";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let doc = attr_pass::mk_pass()(srv, doc);
-    let doc = run(srv, doc);
-    assert vec::is_empty(doc.topmod.fns[0].args);
-}
-
-#[test]
-fn should_not_elide_fns_with_documented_arguments() {
-    let source = "#[doc(args(a = \"b\"))] fn a(a: int) { }";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let doc = attr_pass::mk_pass()(srv, doc);
-    let doc = run(srv, doc);
-    assert vec::is_not_empty(*doc.topmod.fns);
-}
-
-#[test]
-fn should_elide_undocumented_return_values() {
-    let source = "#[doc = \"fonz\"] fn a() -> int { }";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let doc = tystr_pass::mk_pass()(srv, doc);
-    let doc = attr_pass::mk_pass()(srv, doc);
-    let doc = run(srv, doc);
-    assert doc.topmod.fns[0].return.ty == none;
-}
-
-#[test]
-fn should_not_elide_fns_with_documented_failure_conditions() {
-    let source = "#[doc(failure = \"yup\")] fn a() { }";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let doc = attr_pass::mk_pass()(srv, doc);
-    let doc = run(srv, doc);
-    assert vec::is_not_empty(*doc.topmod.fns);
-}
-
-fn fold_modlist(
-    fold: fold::fold<ctxt>,
-    list: doc::modlist
-) -> doc::modlist {
-    doc::modlist(vec::filter_map(*list) {|doc|
-        let doc = fold.fold_mod(fold, doc);
-        if fold.ctxt.have_docs {
-            some(doc)
-        } else {
-            none
-        }
-    })
-}
-
-#[test]
-fn should_elide_undocumented_mods() {
-    let source = "mod a { }";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let doc = run(srv, doc);
-    assert vec::is_empty(*doc.topmod.mods);
-}
-
-#[test]
-fn should_not_elide_undocument_mods_with_documented_mods() {
-    let source = "mod a { #[doc = \"b\"] mod b { } }";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let doc = attr_pass::mk_pass()(srv, doc);
-    let doc = run(srv, doc);
-    assert vec::is_not_empty(*doc.topmod.mods);
-}
-
-#[test]
-fn should_not_elide_undocument_mods_with_documented_fns() {
-    let source = "mod a { #[doc = \"b\"] fn b() { } }";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let doc = attr_pass::mk_pass()(srv, doc);
-    let doc = run(srv, doc);
-    assert vec::is_not_empty(*doc.topmod.mods);
-}
-
-fn fold_fnlist(
-    fold: fold::fold<ctxt>,
-    list: doc::fnlist
-) -> doc::fnlist {
-    doc::fnlist(vec::filter_map(*list) {|doc|
-        let doc = fold.fold_fn(fold, doc);
-        if fold.ctxt.have_docs {
-            some(doc)
-        } else {
-            none
-        }
-    })
-}
-
-#[test]
-fn should_elide_undocumented_fns() {
-    let source = "fn a() { }";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let doc = run(srv, doc);
-    assert vec::is_empty(*doc.topmod.fns);
-}
-
-fn fold_const(
-    fold: fold::fold<ctxt>,
-    doc: doc::constdoc
-) -> doc::constdoc {
-    let doc = fold::default_seq_fold_const(fold, doc);
-    fold.ctxt.have_docs =
-        doc.brief != none
-        || doc.desc != none;
-    ret doc;
-}
-
-fn fold_constlist(
-    fold: fold::fold<ctxt>,
-    list: doc::constlist
-) -> doc::constlist {
-    doc::constlist(vec::filter_map(*list) {|doc|
-        let doc = fold.fold_const(fold, doc);
-        if fold.ctxt.have_docs {
-            some(doc)
-        } else {
-            none
-        }
-    })
-}
-
-#[test]
-fn should_elide_undocumented_consts() {
-    let source = "const a: bool = true;";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let doc = run(srv, doc);
-    assert vec::is_empty(*doc.topmod.consts);
-}
-
-fn fold_enum(fold: fold::fold<ctxt>, doc: doc::enumdoc) -> doc::enumdoc {
-    let doc = ~{
-        variants: vec::filter_map(doc.variants) {|variant|
-            if variant.desc != none {
-                some(variant)
-            } else {
-                none
-            }
-        }
-        with *fold::default_seq_fold_enum(fold, doc)
-    };
-    fold.ctxt.have_docs =
-        doc.brief != none
-        || doc.desc != none
-        || vec::is_not_empty(doc.variants);
-    ret doc;
-}
-
-fn fold_enumlist(
-    fold: fold::fold<ctxt>,
-    list: doc::enumlist
-) -> doc::enumlist {
-    doc::enumlist(vec::filter_map(*list) {|doc|
-        let doc = fold.fold_enum(fold, doc);
-        if fold.ctxt.have_docs {
-            some(doc)
-        } else {
-            none
-        }
-    })
-}
-
-#[test]
-fn should_elide_undocumented_enums() {
-    let source = "enum a { b }";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let doc = attr_pass::mk_pass()(srv, doc);
-    let doc = run(srv, doc);
-    assert vec::is_empty(*doc.topmod.enums);
-}
-
-#[test]
-fn should_elide_undocumented_variants() {
-    let source = "#[doc = \"a\"] enum a { b }";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let doc = attr_pass::mk_pass()(srv, doc);
-    let doc = run(srv, doc);
-    assert vec::is_empty(doc.topmod.enums[0].variants);
-}
-
-#[test]
-fn should_not_elide_enums_with_documented_variants() {
-    let source = "enum a { #[doc = \"a\"] b }";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let doc = attr_pass::mk_pass()(srv, doc);
-    let doc = run(srv, doc);
-    assert vec::is_not_empty(*doc.topmod.enums);
-}
-
-fn fold_res(fold: fold::fold<ctxt>, doc: doc::resdoc) -> doc::resdoc {
-    let doc = ~{
-        args: vec::filter_map(doc.args) {|arg|
-            if arg.desc != none {
-                some(arg)
-            } else {
-                none
-            }
-        }
-        with *fold::default_seq_fold_res(fold, doc)
-    };
-    fold.ctxt.have_docs =
-        doc.brief != none
-        || doc.desc != none
-        || vec::is_not_empty(doc.args);
-    ret doc;
-}
-
-fn fold_reslist(
-    fold: fold::fold<ctxt>,
-    list: doc::reslist
-) -> doc::reslist {
-    doc::reslist(vec::filter_map(*list) {|doc|
-        let doc = fold.fold_res(fold, doc);
-        if fold.ctxt.have_docs {
-            some(doc)
-        } else {
-            none
-        }
-    })
-}
-
-#[test]
-fn should_elide_undocumented_resources() {
-    let source = "resource r(a: bool) { }";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let doc = run(srv, doc);
-    assert vec::is_empty(*doc.topmod.resources);
-}
-
-#[test]
-fn should_elide_undocumented_resource_args() {
-    let source = "#[doc = \"drunk\"]\
-                  resource r(a: bool) { }";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let doc = attr_pass::mk_pass()(srv, doc);
-    let doc = run(srv, doc);
-    assert vec::is_empty(doc.topmod.resources[0].args);
-}
-
-#[test]
-fn should_not_elide_resources_with_documented_args() {
-    let source = "#[doc(args(a = \"drunk\"))]\
-                  resource r(a: bool) { }";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let doc = attr_pass::mk_pass()(srv, doc);
-    let doc = run(srv, doc);
-    assert vec::is_not_empty(*doc.topmod.resources);
-}
index c865d8bd06fce571e22ebd38ffdbd5c9357b5a62..41a035770b64bbd0899953eae096c7812f54f829 100644 (file)
@@ -20,44 +20,17 @@ fn run(srv: astsrv::srv, doc: doc::cratedoc) -> doc::cratedoc {
 
 fn fold_mod(fold: fold::fold<astsrv::srv>, doc: doc::moddoc) -> doc::moddoc {
     let doc = fold::default_seq_fold_mod(fold, doc);
-    ~{
-        mods: doc::modlist(exported_mods(fold.ctxt, doc)),
-        fns: doc::fnlist(exported_fns(fold.ctxt, doc)),
-        consts: doc::constlist(exported_consts(fold.ctxt, doc)),
-        enums: doc::enumlist(exported_enums(fold.ctxt, doc))
-        with *doc
+    {
+        items: ~exported_items(fold.ctxt, doc)
+        with doc
     }
 }
 
-fn exported_mods(srv: astsrv::srv, doc: doc::moddoc) -> [doc::moddoc] {
+fn exported_items(srv: astsrv::srv, doc: doc::moddoc) -> [doc::itemtag] {
     exported_things(
         srv, doc,
-        exported_mods_from_crate,
-        exported_mods_from_mod
-    )
-}
-
-fn exported_fns(srv: astsrv::srv, doc: doc::moddoc) -> [doc::fndoc] {
-    exported_things(
-        srv, doc,
-        exported_fns_from_crate,
-        exported_fns_from_mod
-    )
-}
-
-fn exported_consts(srv: astsrv::srv, doc: doc::moddoc) -> [doc::constdoc] {
-    exported_things(
-        srv, doc,
-        exported_consts_from_crate,
-        exported_consts_from_mod
-    )
-}
-
-fn exported_enums(srv: astsrv::srv, doc: doc::moddoc) -> [doc::enumdoc] {
-    exported_things(
-        srv, doc,
-        exported_enums_from_crate,
-        exported_enums_from_mod
+        exported_items_from_crate,
+        exported_items_from_mod
     )
 }
 
@@ -74,116 +47,38 @@ fn exported_things<T>(
     }
 }
 
-fn exported_mods_from_crate(
-    srv: astsrv::srv,
-    doc: doc::moddoc
-) -> [doc::moddoc] {
-    exported_mods_from(srv, doc, is_exported_from_crate)
-}
-
-fn exported_mods_from_mod(
-    srv: astsrv::srv,
-    doc: doc::moddoc
-) -> [doc::moddoc] {
-    exported_mods_from(srv, doc, bind is_exported_from_mod(_, doc.id, _))
-}
-
-fn exported_fns_from_crate(
+fn exported_items_from_crate(
     srv: astsrv::srv,
     doc: doc::moddoc
-) -> [doc::fndoc] {
-    exported_fns_from(srv, doc, is_exported_from_crate)
+) -> [doc::itemtag] {
+    exported_items_from(srv, doc, is_exported_from_crate)
 }
 
-fn exported_fns_from_mod(
+fn exported_items_from_mod(
     srv: astsrv::srv,
     doc: doc::moddoc
-) -> [doc::fndoc] {
-    exported_fns_from(srv, doc, bind is_exported_from_mod(_, doc.id, _))
-}
-
-fn exported_consts_from_crate(
-    srv: astsrv::srv,
-    doc: doc::moddoc
-) -> [doc::constdoc] {
-    exported_consts_from(srv, doc, is_exported_from_crate)
-}
-
-fn exported_consts_from_mod(
-    srv: astsrv::srv,
-    doc: doc::moddoc
-) -> [doc::constdoc] {
-    exported_consts_from(srv, doc, bind is_exported_from_mod(_, doc.id, _))
-}
-
-fn exported_enums_from_crate(
-    srv: astsrv::srv,
-    doc: doc::moddoc
-) -> [doc::enumdoc] {
-    exported_enums_from(srv, doc, is_exported_from_crate)
-}
-
-fn exported_enums_from_mod(
-    srv: astsrv::srv,
-    doc: doc::moddoc
-) -> [doc::enumdoc] {
-    exported_enums_from(srv, doc, bind is_exported_from_mod(_, doc.id, _))
-}
-
-fn exported_fns_from(
-    srv: astsrv::srv,
-    doc: doc::moddoc,
-    is_exported: fn(astsrv::srv, str) -> bool
-) -> [doc::fndoc] {
-    vec::filter_map(*doc.fns) { |doc|
-        if is_exported(srv, doc.name) {
-            some(doc)
-        } else {
-            none
-        }
-    }
-}
-
-fn exported_mods_from(
-    srv: astsrv::srv,
-    doc: doc::moddoc,
-    is_exported: fn(astsrv::srv, str) -> bool
-) -> [doc::moddoc] {
-    vec::filter_map(*doc.mods) { |doc|
-        if is_exported(srv, doc.name) {
-            some(doc)
-        } else {
-            none
-        }
-    }
-}
-
-fn exported_consts_from(
-    srv: astsrv::srv,
-    doc: doc::moddoc,
-    is_exported: fn(astsrv::srv, str) -> bool
-) -> [doc::constdoc] {
-    vec::filter_map(*doc.consts) { |doc|
-        if is_exported(srv, doc.name) {
-            some(doc)
-        } else {
-            none
-        }
-    }
+) -> [doc::itemtag] {
+    exported_items_from(srv, doc, bind is_exported_from_mod(_, doc.id, _))
 }
 
-fn exported_enums_from(
+fn exported_items_from(
     srv: astsrv::srv,
     doc: doc::moddoc,
     is_exported: fn(astsrv::srv, str) -> bool
-) -> [doc::enumdoc] {
-    vec::filter_map(*doc.enums) { |doc|
-        if is_exported(srv, doc.name) {
-            some(~{
-                variants: exported_variants_from(
-                    srv, doc, is_exported)
-                with *doc
+) -> [doc::itemtag] {
+    vec::filter_map(*doc.items) { |itemtag|
+        let itemtag = alt itemtag {
+          doc::enumtag(enumdoc) {
+            // Also need to check variant exportedness
+            doc::enumtag({
+                variants: exported_variants_from(srv, enumdoc, is_exported)
+                with enumdoc
             })
+          }
+          _ { itemtag }
+        };
+        if is_exported(srv, itemtag.name()) {
+            some(itemtag)
         } else {
             none
         }
@@ -211,13 +106,17 @@ fn is_exported_from_mod(
 ) -> bool {
     astsrv::exec(srv) {|ctxt|
         alt ctxt.ast_map.get(mod_id) {
-          ast_map::node_item(item) {
+          ast_map::node_item(item, _) {
             alt item.node {
               ast::item_mod(m) {
                 ast_util::is_exported(item_name, m)
               }
+              _ {
+                fail "is_exported_from_mod: not a mod";
+              }
             }
           }
+          _ { fail "is_exported_from_mod: not an item"; }
         }
     }
 }
@@ -233,92 +132,105 @@ fn is_exported_from_crate(
 
 #[test]
 fn should_prune_unexported_fns() {
-    let source = "mod b { export a; fn a() { } fn b() { } }";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let doc = run(srv, doc);
-    assert vec::len(*doc.topmod.mods[0].fns) == 1u;
+    let doc = test::mk_doc("mod b { export a; fn a() { } fn b() { } }");
+    assert vec::len(doc.topmod.mods()[0].fns()) == 1u;
 }
 
 #[test]
 fn should_prune_unexported_fns_from_top_mod() {
-    let source = "export a; fn a() { } fn b() { }";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let doc = run(srv, doc);
-    assert vec::len(*doc.topmod.fns) == 1u;
+    let doc = test::mk_doc("export a; fn a() { } fn b() { }");
+    assert vec::len(doc.topmod.fns()) == 1u;
 }
 
 #[test]
 fn should_prune_unexported_modules() {
-    let source = "mod a { export a; mod a { } mod b { } }";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let doc = run(srv, doc);
-    assert vec::len(*doc.topmod.mods[0].mods) == 1u;
+    let doc = test::mk_doc("mod a { export a; mod a { } mod b { } }");
+    assert vec::len(doc.topmod.mods()[0].mods()) == 1u;
 }
 
 #[test]
 fn should_prune_unexported_modules_from_top_mod() {
-    let source = "export a; mod a { } mod b { }";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let doc = run(srv, doc);
-    assert vec::len(*doc.topmod.mods) == 1u;
+    let doc = test::mk_doc("export a; mod a { } mod b { }");
+    assert vec::len(doc.topmod.mods()) == 1u;
 }
 
 #[test]
 fn should_prune_unexported_consts() {
-    let source = "mod a { export a; \
-                  const a: bool = true; \
-                  const b: bool = true; }";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let doc = run(srv, doc);
-    assert vec::len(*doc.topmod.mods[0].consts) == 1u;
+    let doc = test::mk_doc(
+        "mod a { export a; \
+         const a: bool = true; \
+         const b: bool = true; }");
+    assert vec::len(doc.topmod.mods()[0].consts()) == 1u;
 }
 
 #[test]
 fn should_prune_unexported_consts_from_top_mod() {
-    let source = "export a; const a: bool = true; const b: bool = true;";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let doc = run(srv, doc);
-    assert vec::len(*doc.topmod.consts) == 1u;
+    let doc = test::mk_doc(
+        "export a; const a: bool = true; const b: bool = true;");
+    assert vec::len(doc.topmod.consts()) == 1u;
 }
 
 #[test]
 fn should_prune_unexported_enums_from_top_mod() {
-    let source = "export a; mod a { } enum b { c }";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let doc = run(srv, doc);
-    assert vec::len(*doc.topmod.enums) == 0u;
+    let doc = test::mk_doc("export a; mod a { } enum b { c }");
+    assert vec::len(doc.topmod.enums()) == 0u;
 }
 
 #[test]
 fn should_prune_unexported_enums() {
-    let source = "mod a { export a; mod a { } enum b { c } }";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let doc = run(srv, doc);
-    assert vec::len(*doc.topmod.mods[0].enums) == 0u;
+    let doc = test::mk_doc("mod a { export a; mod a { } enum b { c } }");
+    assert vec::len(doc.topmod.mods()[0].enums()) == 0u;
 }
 
 #[test]
 fn should_prune_unexported_variants_from_top_mod() {
-    let source = "export b::{}; enum b { c }";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let doc = run(srv, doc);
-    assert vec::len(doc.topmod.enums[0].variants) == 0u;
+    let doc = test::mk_doc("export b::{}; enum b { c }");
+    assert vec::len(doc.topmod.enums()[0].variants) == 0u;
 }
 
 #[test]
 fn should_prune_unexported_variants() {
-    let source = "mod a { export b::{}; enum b { c } }";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let doc = run(srv, doc);
-    assert vec::len(doc.topmod.mods[0].enums[0].variants) == 0u;
+    let doc = test::mk_doc("mod a { export b::{}; enum b { c } }");
+    assert vec::len(doc.topmod.mods()[0].enums()[0].variants) == 0u;
+}
+
+#[test]
+fn should_prune_unexported_resources_from_top_mod() {
+    let doc = test::mk_doc("export a; mod a { } resource r(a: bool) { }");
+    assert vec::is_empty(doc.topmod.resources());
+}
+
+#[test]
+fn should_prune_unexported_resources() {
+    let doc = test::mk_doc(
+        "mod a { export a; mod a { } resource r(a: bool) { } }");
+    assert vec::is_empty(doc.topmod.mods()[0].resources());
 }
+
+#[test]
+fn should_prune_unexported_ifaces_from_top_mod() {
+    let doc = test::mk_doc("export a; mod a { } iface b { fn c(); }");
+    assert vec::is_empty(doc.topmod.ifaces());
+}
+
+#[test]
+fn should_prune_unexported_impls_from_top_mod() {
+    let doc = test::mk_doc(
+        "export a; mod a { } impl b for int { fn c() { } }");
+    assert vec::is_empty(doc.topmod.impls())
+}
+
+#[test]
+fn should_prune_unexported_types() {
+    let doc = test::mk_doc("export a; mod a { } type b = int;");
+    assert vec::is_empty(doc.topmod.types());
+}
+
+#[cfg(test)]
+mod test {
+    fn mk_doc(source: str) -> doc::cratedoc {
+        let srv = astsrv::mk_srv_from_str(source);
+        let doc = extract::from_srv(srv, "");
+        run(srv, doc)
+    }
+}
\ No newline at end of file
index 055ce07209fa5fe04fbfab3bc14295bcd58eb98f..036a21906571dca35c0ae2e372608ec8ce294b8b 100644 (file)
@@ -21,7 +21,8 @@ mod fold;
 mod path_pass;
 mod attr_pass;
 mod tystr_pass;
-mod prune_undoc_pass;
+mod prune_undoc_details_pass;
+mod prune_undoc_items_pass;
 mod prune_unexported_pass;
 mod desc_to_brief_pass;
 mod desc_pass;
@@ -29,3 +30,6 @@ mod unindent_pass;
 mod trim_pass;
 mod astsrv;
 mod demo;
+mod sort_pass;
+mod sort_item_name_pass;
+mod sort_item_type_pass;
\ No newline at end of file
index 6c9d05260b327136f6a34ce190d3d695284b5b48..eb210d2f4ac6c583bae5f20fa15b0f8280a72da6 100755 (executable)
@@ -2,6 +2,8 @@
  * Copyright 2011 Google Inc.
  */
 
+import doc::util;
+
 #[doc = "A single operation on the document model"]
 type pass = fn~(srv: astsrv::srv, doc: doc::cratedoc) -> doc::cratedoc;
 
@@ -42,18 +44,14 @@ fn pass1(
         _srv: astsrv::srv,
         doc: doc::cratedoc
     ) -> doc::cratedoc {
-        ~{
-            topmod: ~{
+        {
+            topmod: {
                 id: 0,
                 name: doc.topmod.name + "two",
                 path: [],
                 brief: none,
                 desc: none,
-                mods: doc::modlist([]),
-                fns: doc::fnlist([]),
-                consts: doc::constlist([]),
-                enums: doc::enumlist([]),
-                resources: doc::reslist([])
+                items: ~[]
             }
         }
     }
@@ -61,18 +59,14 @@ fn pass2(
         _srv: astsrv::srv,
         doc: doc::cratedoc
     ) -> doc::cratedoc {
-        ~{
-            topmod: ~{
+        {
+            topmod: {
                 id: 0,
                 name: doc.topmod.name + "three",
                 path: [],
                 brief: none,
                 desc: none,
-                mods: doc::modlist([]),
-                fns: doc::fnlist([]),
-                consts: doc::constlist([]),
-                enums: doc::enumlist([]),
-                resources: doc::reslist([])
+                items: ~[]
             }
         }
     }
@@ -106,11 +100,14 @@ fn run(source_file: str) {
         tystr_pass::mk_pass(),
         path_pass::mk_pass(),
         attr_pass::mk_pass(),
+        prune_undoc_details_pass::mk_pass(),
         // FIXME: This pass should be optional
-        prune_undoc_pass::mk_pass(),
+        // prune_undoc_items_pass::mk_pass(),
         desc_to_brief_pass::mk_pass(),
         trim_pass::mk_pass(),
         unindent_pass::mk_pass(),
-        markdown_pass::mk_pass {|| std::io:: stdout()}
+        sort_item_name_pass::mk_pass(),
+        sort_item_type_pass::mk_pass(),
+        markdown_pass::mk_pass {|f| f(std::io:: stdout()) }
     ]);
 }
\ No newline at end of file
diff --git a/src/rustdoc/sort_item_name_pass.rs b/src/rustdoc/sort_item_name_pass.rs
new file mode 100644 (file)
index 0000000..be0478f
--- /dev/null
@@ -0,0 +1,19 @@
+#[doc = "Sorts items by name"];
+
+export mk_pass;
+
+fn mk_pass() -> pass {
+    sort_pass::mk_pass { |item1, item2|
+        str::le(item1.name(), item2.name())
+    }
+}
+
+#[test]
+fn test() {
+    let source = "mod z { } fn y() { }";
+    let srv = astsrv::mk_srv_from_str(source);
+    let doc = extract::from_srv(srv, "");
+    let doc = mk_pass()(srv, doc);
+    assert doc.topmod.items[0].name() == "y";
+    assert doc.topmod.items[1].name() == "z";
+}
diff --git a/src/rustdoc/sort_item_type_pass.rs b/src/rustdoc/sort_item_type_pass.rs
new file mode 100644 (file)
index 0000000..af6212c
--- /dev/null
@@ -0,0 +1,47 @@
+#[doc = "Sorts items by type"];
+
+export mk_pass;
+
+fn mk_pass() -> pass {
+    sort_pass::mk_pass { |item1, item2|
+        fn score(item: doc::itemtag) -> int {
+            alt item {
+              doc::consttag(_) { 0 }
+              doc::tytag(_) { 1 }
+              doc::enumtag(_) { 2 }
+              doc::restag(_) { 3 }
+              doc::ifacetag(_) { 4 }
+              doc::impltag(_) { 5 }
+              doc::fntag(_) { 6 }
+              doc::modtag(_) { 7 }
+              _ { fail }
+            }
+        }
+
+        score(item1) <= score(item2)
+    }
+}
+
+#[test]
+fn test() {
+    let source =
+        "mod imod { } \
+         const iconst: int = 0; \
+         fn ifn() { } \
+         enum ienum { ivar } \
+         resource ires(a: bool) { } \
+         iface iiface { fn a(); } \
+         impl iimpl for int { fn a() { } } \
+         type itype = int;";
+    let srv = astsrv::mk_srv_from_str(source);
+    let doc = extract::from_srv(srv, "");
+    let doc = mk_pass()(srv, doc);
+    assert doc.topmod.items[0].name() == "iconst";
+    assert doc.topmod.items[1].name() == "itype";
+    assert doc.topmod.items[2].name() == "ienum";
+    assert doc.topmod.items[3].name() == "ires";
+    assert doc.topmod.items[4].name() == "iiface";
+    assert doc.topmod.items[5].name() == "iimpl";
+    assert doc.topmod.items[6].name() == "ifn";
+    assert doc.topmod.items[7].name() == "imod";
+}
diff --git a/src/rustdoc/sort_pass.rs b/src/rustdoc/sort_pass.rs
new file mode 100644 (file)
index 0000000..674b028
--- /dev/null
@@ -0,0 +1,69 @@
+#[doc = "A general sorting pass"];
+
+import std::sort;
+
+export item_lteq, mk_pass;
+
+type item_lteq = fn~(doc::itemtag, doc::itemtag) -> bool;
+
+fn mk_pass(lteq: item_lteq) -> pass {
+    fn~(srv: astsrv::srv, doc: doc::cratedoc) -> doc::cratedoc {
+        run(srv, doc, lteq)
+    }
+}
+
+fn run(
+    _srv: astsrv::srv,
+    doc: doc::cratedoc,
+    lteq: item_lteq
+) -> doc::cratedoc {
+    let fold = fold::fold({
+        fold_mod: fold_mod
+        with *fold::default_seq_fold(lteq)
+    });
+    fold.fold_crate(fold, doc)
+}
+
+fn fold_mod(
+    fold: fold::fold<item_lteq>,
+    doc: doc::moddoc
+) -> doc::moddoc {
+    let doc = fold::default_seq_fold_mod(fold, doc);
+    {
+        items: ~sort::merge_sort(fold.ctxt, *doc.items)
+        with doc
+    }
+}
+
+#[test]
+fn test() {
+    fn name_lteq(item1: doc::itemtag, item2: doc::itemtag) -> bool {
+        str::le(item1.name(), item2.name())
+    }
+
+    let source = "mod z { mod y { } fn x() { } } mod w { }";
+    let srv = astsrv::mk_srv_from_str(source);
+    let doc = extract::from_srv(srv, "");
+    let doc = mk_pass(name_lteq)(srv, doc);
+    assert doc.topmod.mods()[0].name == "w";
+    assert doc.topmod.mods()[1].items[0].name() == "x";
+    assert doc.topmod.mods()[1].items[1].name() == "y";
+    assert doc.topmod.mods()[1].name == "z";
+}
+
+#[test]
+fn should_be_stable() {
+    fn always_eq(_item1: doc::itemtag, _item2: doc::itemtag) -> bool {
+        true
+    }
+
+    let source = "mod a { mod b { } } mod c { mod d { } }";
+    let srv = astsrv::mk_srv_from_str(source);
+    let doc = extract::from_srv(srv, "");
+    let doc = mk_pass(always_eq)(srv, doc);
+    assert doc.topmod.mods()[0].items[0].name() == "b";
+    assert doc.topmod.mods()[1].items[0].name() == "d";
+    let doc = mk_pass(always_eq)(srv, doc);
+    assert doc.topmod.mods()[0].items[0].name() == "b";
+    assert doc.topmod.mods()[1].items[0].name() == "d";
+}
index 871605e555473657d50e248e6a9b50911cc78e5a..bec08afdbd2bd58997aa58fbf5226f18655aae1c 100644 (file)
@@ -15,69 +15,55 @@ fn mk_pass() -> pass {
 
 #[test]
 fn should_trim_mod() {
-    let source = "#[doc(brief = \"\nbrief\n\", \
-                  desc = \"\ndesc\n\")] \
-                  mod m { }";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let doc = attr_pass::mk_pass()(srv, doc);
-    let doc = mk_pass()(srv, doc);
-    assert doc.topmod.mods[0].brief == some("brief");
-    assert doc.topmod.mods[0].desc == some("desc");
+    let doc = test::mk_doc("#[doc(brief = \"\nbrief\n\", \
+                            desc = \"\ndesc\n\")] \
+                            mod m { }");
+    assert doc.topmod.mods()[0].brief == some("brief");
+    assert doc.topmod.mods()[0].desc == some("desc");
 }
 
 #[test]
 fn should_trim_const() {
-    let source = "#[doc(brief = \"\nbrief\n\", \
-                  desc = \"\ndesc\n\")] \
-                  const a: bool = true;";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let doc = attr_pass::mk_pass()(srv, doc);
-    let doc = mk_pass()(srv, doc);
-    assert doc.topmod.consts[0].brief == some("brief");
-    assert doc.topmod.consts[0].desc == some("desc");
+    let doc = test::mk_doc("#[doc(brief = \"\nbrief\n\", \
+                            desc = \"\ndesc\n\")] \
+                            const a: bool = true;");
+    assert doc.topmod.consts()[0].brief == some("brief");
+    assert doc.topmod.consts()[0].desc == some("desc");
 }
 
 #[test]
 fn should_trim_fn() {
-    let source = "#[doc(brief = \"\nbrief\n\", \
-                  desc = \"\ndesc\n\")] \
-                  fn a() { }";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let doc = attr_pass::mk_pass()(srv, doc);
-    let doc = mk_pass()(srv, doc);
-    assert doc.topmod.fns[0].brief == some("brief");
-    assert doc.topmod.fns[0].desc == some("desc");
+    let doc = test::mk_doc("#[doc(brief = \"\nbrief\n\", \
+                            desc = \"\ndesc\n\")] \
+                            fn a() { }");
+    assert doc.topmod.fns()[0].brief == some("brief");
+    assert doc.topmod.fns()[0].desc == some("desc");
 }
 
 #[test]
 fn should_trim_args() {
-    let source = "#[doc(args(a = \"\na\n\"))] fn a(a: int) { }";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let doc = attr_pass::mk_pass()(srv, doc);
-    let doc = mk_pass()(srv, doc);
-    assert doc.topmod.fns[0].args[0].desc == some("a");
+    let doc = test::mk_doc("#[doc(args(a = \"\na\n\"))] fn a(a: int) { }");
+    assert doc.topmod.fns()[0].args[0].desc == some("a");
 }
 
 #[test]
 fn should_trim_ret() {
-    let source = "#[doc(return = \"\na\n\")] fn a() -> int { }";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let doc = attr_pass::mk_pass()(srv, doc);
-    let doc = mk_pass()(srv, doc);
-    assert doc.topmod.fns[0].return.desc == some("a");
+    let doc = test::mk_doc("#[doc(return = \"\na\n\")] fn a() -> int { }");
+    assert doc.topmod.fns()[0].return.desc == some("a");
 }
 
 #[test]
 fn should_trim_failure_conditions() {
-    let source = "#[doc(failure = \"\na\n\")] fn a() -> int { }";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let doc = attr_pass::mk_pass()(srv, doc);
-    let doc = mk_pass()(srv, doc);
-    assert doc.topmod.fns[0].failure == some("a");
+    let doc = test::mk_doc("#[doc(failure = \"\na\n\")] fn a() -> int { }");
+    assert doc.topmod.fns()[0].failure == some("a");
+}
+
+#[cfg(test)]
+mod test {
+    fn mk_doc(source: str) -> doc::cratedoc {
+        let srv = astsrv::mk_srv_from_str(source);
+        let doc = extract::from_srv(srv, "");
+        let doc = attr_pass::mk_pass()(srv, doc);
+        mk_pass()(srv, doc)
+    }
 }
\ No newline at end of file
index 12a1e68b42bb399b61de9ebb1b2d3bc1257ce87f..58cbff8edb28aa99b426d623ab3a71ef0f4cf947 100644 (file)
@@ -19,7 +19,10 @@ fn run(
         fold_fn: fold_fn,
         fold_const: fold_const,
         fold_enum: fold_enum,
-        fold_res: fold_res
+        fold_res: fold_res,
+        fold_iface: fold_iface,
+        fold_impl: fold_impl,
+        fold_type: fold_type
         with *fold::default_seq_fold(srv)
     });
     fold.fold_crate(fold, doc)
@@ -32,11 +35,11 @@ fn fold_fn(
 
     let srv = fold.ctxt;
 
-    ~{
+    {
         args: merge_arg_tys(srv, doc.id, doc.args),
         return: merge_ret_ty(srv, doc.id, doc.return),
         sig: get_fn_sig(srv, doc.id)
-        with *doc
+        with doc
     }
 }
 
@@ -46,20 +49,20 @@ fn get_fn_sig(srv: astsrv::srv, fn_id: doc::ast_id) -> option<str> {
           ast_map::node_item(@{
             ident: ident,
             node: ast::item_fn(decl, _, blk), _
-          }) {
+          }, _) {
             some(pprust::fun_to_str(decl, ident, []))
           }
+          _ {
+            fail "get_fn_sig: undocumented invariant";
+          }
         }
     }
 }
 
 #[test]
 fn should_add_fn_sig() {
-    let source = "fn a() -> int { }";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let doc = run(srv, doc);
-    assert doc.topmod.fns[0].sig == some("fn a() -> int");
+    let doc = test::mk_doc("fn a() -> int { }");
+    assert doc.topmod.fns()[0].sig == some("fn a() -> int");
 }
 
 fn merge_ret_ty(
@@ -83,34 +86,33 @@ fn get_ret_ty(srv: astsrv::srv, fn_id: doc::ast_id) -> option<str> {
         alt ctxt.ast_map.get(fn_id) {
           ast_map::node_item(@{
             node: ast::item_fn(decl, _, _), _
-          }) {
-            if decl.output.node != ast::ty_nil {
-                some(pprust::ty_to_str(decl.output))
-            } else {
-                // Nil-typed return values are not interesting
-                none
-            }
+          }, _) {
+            ret_ty_to_str(decl)
           }
+          _ { fail "get_ret_ty: undocumented invariant"; }
         }
     }
 }
 
+fn ret_ty_to_str(decl: ast::fn_decl) -> option<str> {
+    if decl.output.node != ast::ty_nil {
+        some(pprust::ty_to_str(decl.output))
+    } else {
+        // Nil-typed return values are not interesting
+        none
+    }
+}
+
 #[test]
 fn should_add_fn_ret_types() {
-    let source = "fn a() -> int { }";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let doc = run(srv, doc);
-    assert doc.topmod.fns[0].return.ty == some("int");
+    let doc = test::mk_doc("fn a() -> int { }");
+    assert doc.topmod.fns()[0].return.ty == some("int");
 }
 
 #[test]
 fn should_not_add_nil_ret_type() {
-    let source = "fn a() { }";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let doc = run(srv, doc);
-    assert doc.topmod.fns[0].return.ty == none;
+    let doc = test::mk_doc("fn a() { }");
+    assert doc.topmod.fns()[0].return.ty == none;
 }
 
 fn merge_arg_tys(
@@ -122,9 +124,9 @@ fn merge_arg_tys(
     vec::map2(args, tys) {|arg, ty|
         // Sanity check that we're talking about the same args
         assert arg.name == tuple::first(ty);
-        ~{
+        {
             ty: some(tuple::second(ty))
-            with *arg
+            with arg
         }
     }
 }
@@ -134,25 +136,29 @@ fn get_arg_tys(srv: astsrv::srv, fn_id: doc::ast_id) -> [(str, str)] {
         alt ctxt.ast_map.get(fn_id) {
           ast_map::node_item(@{
             node: ast::item_fn(decl, _, _), _
-          }) |
+          }, _) |
           ast_map::node_item(@{
             node: ast::item_res(decl, _, _, _, _), _
-          }) {
-            vec::map(decl.inputs) {|arg|
-                (arg.ident, pprust::ty_to_str(arg.ty))
-            }
+          }, _) {
+            decl_arg_tys(decl)
+          }
+          _ {
+            fail "get_arg_tys: undocumented invariant";
           }
         }
     }
 }
 
+fn decl_arg_tys(decl: ast::fn_decl) -> [(str, str)] {
+    vec::map(decl.inputs) {|arg|
+        (arg.ident, pprust::ty_to_str(arg.ty))
+    }
+}
+
 #[test]
 fn should_add_arg_types() {
-    let source = "fn a(b: int, c: bool) { }";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let doc = run(srv, doc);
-    let fn_ = doc.topmod.fns[0];
+    let doc = test::mk_doc("fn a(b: int, c: bool) { }");
+    let fn_ = doc.topmod.fns()[0];
     assert fn_.args[0].ty == some("int");
     assert fn_.args[1].ty == some("bool");
 }
@@ -163,27 +169,27 @@ fn fold_const(
 ) -> doc::constdoc {
     let srv = fold.ctxt;
 
-    ~{
+    {
         ty: some(astsrv::exec(srv) {|ctxt|
             alt ctxt.ast_map.get(doc.id) {
               ast_map::node_item(@{
                 node: ast::item_const(ty, _), _
-              }) {
+              }, _) {
                 pprust::ty_to_str(ty)
               }
+              _ {
+                fail "fold_const: undocumented invariant";
+              }
             }
         })
-        with *doc
+        with doc
     }
 }
 
 #[test]
 fn should_add_const_types() {
-    let source = "const a: bool = true;";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let doc = run(srv, doc);
-    assert doc.topmod.consts[0].ty == some("bool");
+    let doc = test::mk_doc("const a: bool = true;");
+    assert doc.topmod.consts()[0].ty == some("bool");
 }
 
 fn fold_enum(
@@ -192,13 +198,13 @@ fn fold_enum(
 ) -> doc::enumdoc {
     let srv = fold.ctxt;
 
-    ~{
+    {
         variants: vec::map(doc.variants) {|variant|
             let sig = astsrv::exec(srv) {|ctxt|
                 alt ctxt.ast_map.get(doc.id) {
                   ast_map::node_item(@{
                     node: ast::item_enum(ast_variants, _), _
-                  }) {
+                  }, _) {
                     let ast_variant = option::get(
                         vec::find(ast_variants) {|v|
                             v.node.name == variant.name
@@ -206,25 +212,23 @@ fn fold_enum(
 
                     pprust::variant_to_str(ast_variant)
                   }
+                  _ { fail "fold_enum: undocumented invariant"; }
                 }
             };
 
-            ~{
+            {
                 sig: some(sig)
-                with *variant
+                with variant
             }
         }
-        with *doc
+        with doc
     }
 }
 
 #[test]
 fn should_add_variant_sigs() {
-    let source = "enum a { b(int) }";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let doc = run(srv, doc);
-    assert doc.topmod.enums[0].variants[0].sig == some("b(int)");
+    let doc = test::mk_doc("enum a { b(int) }");
+    assert doc.topmod.enums()[0].variants[0].sig == some("b(int)");
 }
 
 fn fold_res(
@@ -233,35 +237,346 @@ fn fold_res(
 ) -> doc::resdoc {
     let srv = fold.ctxt;
 
-    ~{
+    {
         args: merge_arg_tys(srv, doc.id, doc.args),
         sig: some(astsrv::exec(srv) {|ctxt|
             alt ctxt.ast_map.get(doc.id) {
               ast_map::node_item(@{
                 node: ast::item_res(decl, _, _, _, _), _
-              }) {
+              }, _) {
                 pprust::res_to_str(decl, doc.name, [])
               }
+              _ { fail "fold_res: undocumented invariant"; }
             }
         })
-        with *doc
+        with doc
     }
 }
 
 #[test]
 fn should_add_resource_sigs() {
-    let source = "resource r(b: bool) { }";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let doc = run(srv, doc);
-    assert doc.topmod.resources[0].sig == some("resource r(b: bool)");
+    let doc = test::mk_doc("resource r(b: bool) { }");
+    assert doc.topmod.resources()[0].sig == some("resource r(b: bool)");
 }
 
 #[test]
 fn should_add_resource_arg_tys() {
-    let source = "resource r(a: bool) { }";
-    let srv = astsrv::mk_srv_from_str(source);
-    let doc = extract::from_srv(srv, "");
-    let doc = run(srv, doc);
-    assert doc.topmod.resources[0].args[0].ty == some("bool");
+    let doc = test::mk_doc("resource r(a: bool) { }");
+    assert doc.topmod.resources()[0].args[0].ty == some("bool");
+}
+
+fn fold_iface(
+    fold: fold::fold<astsrv::srv>,
+    doc: doc::ifacedoc
+) -> doc::ifacedoc {
+    {
+        methods: merge_methods(fold.ctxt, doc.id, doc.methods)
+        with doc
+    }
+}
+
+fn merge_methods(
+    srv: astsrv::srv,
+    item_id: doc::ast_id,
+    docs: [doc::methoddoc]
+) -> [doc::methoddoc] {
+    vec::map(docs) {|doc|
+        {
+            args: merge_method_arg_tys(
+                srv,
+                item_id,
+                doc.args,
+                doc.name),
+            return: merge_method_ret_ty(
+                srv,
+                item_id,
+                doc.return,
+                doc.name),
+            sig: get_method_sig(srv, item_id, doc.name)
+            with doc
+        }
+    }
+}
+
+fn merge_method_ret_ty(
+    srv: astsrv::srv,
+    item_id: doc::ast_id,
+    doc: doc::retdoc,
+    method_name: str
+) -> doc::retdoc {
+    alt get_method_ret_ty(srv, item_id, method_name) {
+      some(ty) {
+        {
+            ty: some(ty)
+            with doc
+        }
+      }
+      none { doc }
+    }
+}
+
+fn get_method_ret_ty(
+    srv: astsrv::srv,
+    item_id: doc::ast_id,
+    method_name: str
+) -> option<str> {
+    astsrv::exec(srv) {|ctxt|
+        alt ctxt.ast_map.get(item_id) {
+          ast_map::node_item(@{
+            node: ast::item_iface(_, methods), _
+          }, _) {
+            alt vec::find(methods) {|method|
+                method.ident == method_name
+            } {
+                some(method) {
+                    ret_ty_to_str(method.decl)
+                }
+                _ { fail "get_method_ret_ty: undocumented invariant"; }
+            }
+          }
+          ast_map::node_item(@{
+            node: ast::item_impl(_, _, _, methods), _
+          }, _) {
+            alt vec::find(methods) {|method|
+                method.ident == method_name
+            } {
+                some(method) {
+                    ret_ty_to_str(method.decl)
+                }
+                _ { fail "get_method_ret_ty: undocumented invariant"; }
+            }
+          }
+          _ { fail }
+        }
+    }
+}
+
+fn get_method_sig(
+    srv: astsrv::srv,
+    item_id: doc::ast_id,
+    method_name: str
+) -> option<str> {
+    astsrv::exec(srv) {|ctxt|
+        alt ctxt.ast_map.get(item_id) {
+          ast_map::node_item(@{
+            node: ast::item_iface(_, methods), _
+          }, _) {
+            alt vec::find(methods) {|method|
+                method.ident == method_name
+            } {
+                some(method) {
+                    some(pprust::fun_to_str(method.decl, method.ident, []))
+                }
+                _ { fail "get_method_sig: undocumented invariant"; }
+            }
+          }
+          ast_map::node_item(@{
+            node: ast::item_impl(_, _, _, methods), _
+          }, _) {
+            alt vec::find(methods) {|method|
+                method.ident == method_name
+            } {
+                some(method) {
+                    some(pprust::fun_to_str(method.decl, method.ident, []))
+                }
+                _ { fail "get_method_sig: undocumented invariant"; }
+            }
+          }
+          _ { fail "get_method_sig: undocumented invariant"; }
+        }
+    }
+}
+
+fn merge_method_arg_tys(
+    srv: astsrv::srv,
+    item_id: doc::ast_id,
+    args: [doc::argdoc],
+    method_name: str
+) -> [doc::argdoc] {
+    let tys = get_method_arg_tys(srv, item_id, method_name);
+    vec::map2(args, tys) {|arg, ty|
+        assert arg.name == tuple::first(ty);
+        {
+            ty: some(tuple::second(ty))
+            with arg
+        }
+    }
+}
+
+fn get_method_arg_tys(
+    srv: astsrv::srv,
+    item_id: doc::ast_id,
+    method_name: str
+) -> [(str, str)] {
+    astsrv::exec(srv) {|ctxt|
+        alt ctxt.ast_map.get(item_id) {
+          ast_map::node_item(@{
+            node: ast::item_iface(_, methods), _
+          }, _) {
+            alt vec::find(methods) {|method|
+                method.ident == method_name
+            } {
+                some(method) {
+                    decl_arg_tys(method.decl)
+                }
+                _ { fail "get_method_arg_tys: expected method"; }
+            }
+          }
+          ast_map::node_item(@{
+            node: ast::item_impl(_, _, _, methods), _
+          }, _) {
+            alt vec::find(methods) {|method|
+                method.ident == method_name
+            } {
+                some(method) {
+                    decl_arg_tys(method.decl)
+                }
+                _ { fail "get_method_arg_tys: expected method"; }
+            }
+          }
+          _ { fail }
+        }
+    }
+}
+
+#[test]
+fn should_add_iface_method_sigs() {
+    let doc = test::mk_doc("iface i { fn a() -> int; }");
+    assert doc.topmod.ifaces()[0].methods[0].sig == some("fn a() -> int");
+}
+
+#[test]
+fn should_add_iface_method_ret_types() {
+    let doc = test::mk_doc("iface i { fn a() -> int; }");
+    assert doc.topmod.ifaces()[0].methods[0].return.ty == some("int");
+}
+
+#[test]
+fn should_not_add_iface_method_nil_ret_type() {
+    let doc = test::mk_doc("iface i { fn a(); }");
+    assert doc.topmod.ifaces()[0].methods[0].return.ty == none;
+}
+
+#[test]
+fn should_add_iface_method_arg_types() {
+    let doc = test::mk_doc("iface i { fn a(b: int, c: bool); }");
+    let fn_ = doc.topmod.ifaces()[0].methods[0];
+    assert fn_.args[0].ty == some("int");
+    assert fn_.args[1].ty == some("bool");
+}
+
+fn fold_impl(
+    fold: fold::fold<astsrv::srv>,
+    doc: doc::impldoc
+) -> doc::impldoc {
+
+    let srv = fold.ctxt;
+
+    let (iface_ty, self_ty) = astsrv::exec(srv) {|ctxt|
+        alt ctxt.ast_map.get(doc.id) {
+          ast_map::node_item(@{
+            node: ast::item_impl(_, iface_ty, self_ty, _), _
+          }, _) {
+            let iface_ty = option::map(iface_ty) {|iface_ty|
+                pprust::ty_to_str(iface_ty)
+            };
+            (iface_ty, some(pprust::ty_to_str(self_ty)))
+          }
+          _ { fail "expected impl" }
+        }
+    };
+
+    {
+        iface_ty: iface_ty,
+        self_ty: self_ty,
+        methods: merge_methods(fold.ctxt, doc.id, doc.methods)
+        with doc
+    }
+}
+
+#[test]
+fn should_add_impl_iface_ty() {
+    let doc = test::mk_doc("impl i of j for int { fn a() { } }");
+    assert doc.topmod.impls()[0].iface_ty == some("j");
+}
+
+#[test]
+fn should_not_add_impl_iface_ty_if_none() {
+    let doc = test::mk_doc("impl i for int { fn a() { } }");
+    assert doc.topmod.impls()[0].iface_ty == none;
+}
+
+#[test]
+fn should_add_impl_self_ty() {
+    let doc = test::mk_doc("impl i for int { fn a() { } }");
+    assert doc.topmod.impls()[0].self_ty == some("int");
+}
+
+#[test]
+fn should_add_impl_method_sigs() {
+    let doc = test::mk_doc("impl i for int { fn a() -> int { fail } }");
+    assert doc.topmod.impls()[0].methods[0].sig == some("fn a() -> int");
+}
+
+#[test]
+fn should_add_impl_method_ret_types() {
+    let doc = test::mk_doc("impl i for int { fn a() -> int { fail } }");
+    assert doc.topmod.impls()[0].methods[0].return.ty == some("int");
+}
+
+#[test]
+fn should_not_add_impl_method_nil_ret_type() {
+    let doc = test::mk_doc("impl i for int { fn a() { } }");
+    assert doc.topmod.impls()[0].methods[0].return.ty == none;
+}
+
+#[test]
+fn should_add_impl_method_arg_types() {
+    let doc = test::mk_doc("impl i for int { fn a(b: int, c: bool) { } }");
+    let fn_ = doc.topmod.impls()[0].methods[0];
+    assert fn_.args[0].ty == some("int");
+    assert fn_.args[1].ty == some("bool");
+}
+
+fn fold_type(
+    fold: fold::fold<astsrv::srv>,
+    doc: doc::tydoc
+) -> doc::tydoc {
+
+    let srv = fold.ctxt;
+
+    {
+        sig: astsrv::exec(srv) {|ctxt|
+            alt ctxt.ast_map.get(doc.id) {
+              ast_map::node_item(@{
+                ident: ident,
+                node: ast::item_ty(ty, params), _
+              }, _) {
+                some(#fmt(
+                    "type %s%s = %s",
+                    ident,
+                    pprust::typarams_to_str(params),
+                    pprust::ty_to_str(ty)
+                ))
+              }
+              _ { fail "expected type" }
+            }
+        }
+        with doc
+    }
+}
+
+#[test]
+fn should_add_type_signatures() {
+    let doc = test::mk_doc("type t<T> = int;");
+    assert doc.topmod.types()[0].sig == some("type t<T> = int");
+}
+
+#[cfg(test)]
+mod test {
+    fn mk_doc(source: str) -> doc::cratedoc {
+        let srv = astsrv::mk_srv_from_str(source);
+        let doc = extract::from_srv(srv, "");
+        run(srv, doc)
+    }
 }
\ No newline at end of file
index ea439fd94c47029a3578d274292a7b80376852b7..9c43ce4486414f68220b7fd80293a47894af28be 100644 (file)
@@ -47,7 +47,7 @@ fn unindent(s: str) -> str {
         } else {
             saw_first_line = true;
             let spaces = 0u;
-            str::loop_chars(line) {|char|
+            str::all(line) {|char|
                 // Only comparing against space because I wouldn't
                 // know what to do with mixed whitespace chars
                 if char == ' ' {
@@ -68,7 +68,7 @@ fn unindent(s: str) -> str {
                 line
             } else {
                 assert str::byte_len(line) >= min_indent;
-                str::char_slice(line, min_indent, str::char_len(line))
+                str::slice(line, min_indent, str::char_len(line))
             }
         };
         str::connect(unindented, "\n")
@@ -117,4 +117,4 @@ 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";
-}
\ No newline at end of file
+}
index d9f300f90239e042969e22aa08b1a07fd01f9db3..78b32a6e244d6cc481d233acbc7823cb366c4a78 100644 (file)
@@ -1,3 +1,17 @@
+S 2012-02-01 196d69b
+  winnt-i386 25f5906994ea01dc322a4b52b2b9a4b1264a6c2d
+  linux-i386 8d4aef1320b62043997a10d28005a2c0c592da6d
+  macos-i386 55d70915501a65e16588c1c2e73632a930c12092
+  linux-x86_64 9a030fc6a649127f55aace94152275c0ee7b1e69
+  macos-x86_64 0d0259cd6e52f30121044f36fd64167ced6d4f09
+
+S 2012-01-31 e5d095d
+  winnt-i386 4d80e3c51fa7bb0f8933eece86dc469016dc020a
+  linux-i386 9e2632c68104fd371b173f130472d6424394a957
+  macos-i386 c74a126bd8367779c2d5914c98f262fc095dab6d
+  linux-x86_64 91618dfd51cc7681854ffb5a0eb41d71b8283d4a
+  macos-x86_64 89c3d55bba1d7d25e2553e2f511afb6d81541ee9
+
 S 2012-01-26 28fbb19
   winnt-i386 34428e930722e75b1bc7a313ade232052cf95a5d
   linux-i386 beefec8535c52d614df22664fd75165f6cec3034
index 2c5803686a15663a169cb882c7d477791f8e8c13..ca0555ca49d57601e2a2106a511c43bcf8aa81d6 100644 (file)
@@ -13,8 +13,6 @@ fn ack(m: int, n: int) -> int {
 }
 
 fn main(args: [str]) {
-    // FIXME: #1527
-    sys::set_min_stack(1000000u);
     let n = if vec::len(args) == 2u {
         int::from_str(args[1])
     } else {
index a174557c4ea4bf40cd91c28b3cff805c233abcb0..ad31289a1094839c935d1c20c9a3534b5845276f 100644 (file)
@@ -9,8 +9,6 @@ fn fib(n: int) -> int {
 }
 
 fn main(args: [str]) {
-    // FIXME: #1527
-    sys::set_min_stack(1000000u);
     let n = if vec::len(args) == 2u {
         int::from_str(args[1])
     } else {
diff --git a/src/test/bench/shootout-mandelbrot.rs b/src/test/bench/shootout-mandelbrot.rs
new file mode 100644 (file)
index 0000000..985b2e8
--- /dev/null
@@ -0,0 +1,174 @@
+//  based on:
+//  http://shootout.alioth.debian.org/
+//   u64q/program.php?test=mandelbrot&lang=python3&id=2
+//
+//  takes 3 optional args:
+//   square image size, defaults to 80_u
+//   yield frequency, defaults to 10_u (yield every 10 spawns)
+//   output path, default is "" (no output), "-" means stdout
+//
+//  in the shootout, they use 16000 as image size
+//  yield frequency doesn't seem to have much effect
+//
+//  writes pbm image to output path
+
+use std;
+import std::io::writer_util;
+
+type cmplx = {re: f64, im: f64};
+type line = {i: uint, b: [u8]};
+
+impl arith for cmplx {
+    fn *(x: cmplx) -> cmplx {
+        {re: self.re*x.re - self.im*x.im, im: self.re*x.im + self.im*x.re}
+    }
+
+    fn +(x: cmplx) -> cmplx {
+        {re: self.re + x.re, im: self.im + x.im}
+    }
+}
+
+pure fn cabs(x: cmplx) -> f64
+{
+    x.re*x.re + x.im*x.im
+}
+
+fn mb(x: cmplx) -> bool
+{
+    let z = {re: 0., im: 0.};
+    let i = 0;
+    let in = true;
+    while i < 50 {
+        z = z*z + x;
+        if cabs(z) >= 4. {
+            in = false;
+            break;
+        }
+        i += 1;
+    }
+    in
+}
+
+fn fillbyte(x: cmplx, incr: f64) -> u8 {
+    let rv = 0_u8;
+    let i = 0_u8;
+    while i < 8_u8 {
+        let z = {re: x.re + (i as f64)*incr, im: x.im};
+        if mb(z) {
+            rv += 1_u8 << (7_u8 - i);
+        }
+        i += 1_u8;
+    }
+    rv
+}
+
+fn chanmb(i: uint, size: uint, ch: comm::chan<line>) -> ()
+{
+    let crv = [];
+    let incr = 2./(size as f64);
+    let y = incr*(i as f64) - 1.;
+    let xincr = 8.*incr;
+    uint::range(0_u, size/8_u) {
+        |j|
+        let x = {re: xincr*(j as f64) - 1.5, im: y};
+        crv += [fillbyte(x, incr)];
+    };
+    comm::send(ch, {i:i, b:crv});
+}
+
+type devnull = {dn: int};
+
+impl of std::io::writer for devnull {
+    fn write(_b: [const u8]) {}
+    fn seek(_i: int, _s: std::io::seek_style) {}
+    fn tell() -> uint {0_u}
+    fn flush() -> int {0}
+}
+
+fn writer(path: str, writech: comm::chan<comm::chan<line>>, size: uint)
+{
+    let p: comm::port<line> = comm::port();
+    let ch = comm::chan(p);
+    comm::send(writech, ch);
+    let cout: std::io::writer = alt path {
+        "" {
+            {dn: 0} as std::io::writer
+        }
+        "-" {
+            std::io::stdout()
+        }
+        _ {
+            result::get(
+                std::io::file_writer(path,
+                [std::io::create, std::io::truncate]))
+        }
+    };
+    cout.write_line("P4");
+    cout.write_line(#fmt("%u %u", size, size));
+    let lines = std::map::new_uint_hash();
+    let done = 0_u;
+    let i = 0_u;
+    while i < size {
+        let aline = comm::recv(p);
+        if aline.i == done {
+            #debug("W %u", aline.i);
+            cout.write(aline.b);
+            done += 1_u;
+            let prev = done;
+            while prev <= i {
+                if lines.contains_key(prev) {
+                    #debug("WS %u", prev);
+                    cout.write(lines.get(prev));
+                    done += 1_u;
+                    lines.remove(prev);
+                    prev += 1_u;
+                }
+                else {
+                    break
+                }
+            };
+        }
+        else {
+            #debug("S %u", aline.i);
+            lines.insert(aline.i, aline.b);
+        };
+        i += 1_u;
+    }
+}
+
+fn main(argv: [str])
+{
+    let size = if vec::len(argv) < 2_u {
+        80u
+    }
+    else {
+        uint::from_str(argv[1])
+    };
+    let yieldevery = if vec::len(argv) < 3_u {
+        10_u
+    }
+    else {
+        uint::from_str(argv[2])
+    };
+    let path = if vec::len(argv) < 4_u {
+        ""
+    }
+    else {
+        argv[3]
+    };
+    let writep = comm::port();
+    let writech = comm::chan(writep);
+    task::spawn {
+        || writer(path, writech, size);
+    };
+    let ch = comm::recv(writep);
+    uint::range(0_u, size) {
+        |j| task::spawn {
+            || chanmb(j, size, ch);
+        };
+        if j % yieldevery == 0_u {
+            #debug("Y %u", j);
+            task::yield();
+        };
+    };
+}
diff --git a/src/test/bench/shootout-threadring.rs b/src/test/bench/shootout-threadring.rs
new file mode 100644 (file)
index 0000000..4b73413
--- /dev/null
@@ -0,0 +1,48 @@
+// Based on threadring.erlang by Jira Isa
+use std;
+
+const n_threads: int = 503;
+
+fn start(+token: int) {
+    import iter::*;
+
+    let p = comm::port();
+    let ch = iter::foldl(bind int::range(2, n_threads + 1, _),
+                         comm::chan(p)) { |ch, i|
+        let id = n_threads + 2 - i;
+        let {to_child, _} = task::spawn_connected::<int, int> {|p, _ch|
+            roundtrip(id, p, ch)
+        };
+        to_child
+    };
+    comm::send(ch, token);
+    roundtrip(1, p, ch);
+}
+
+fn roundtrip(id: int, p: comm::port<int>, ch: comm::chan<int>) {
+    while (true) {
+        alt comm::recv(p) {
+          1 {
+            std::io::println(#fmt("%d\n", id));
+            ret;
+          }
+          token {
+            #debug("%d %d", id, token);
+            comm::send(ch, token - 1);
+            if token <= n_threads {
+                ret;
+            }
+          }
+        }
+    }
+}
+
+fn main(args: [str]) {
+    let token = if vec::len(args) < 2u {
+        1000
+    } else {
+        int::from_str(args[1])
+    };
+
+    start(token);
+}
\ No newline at end of file
index 8be28fabd79435fc9209911e0cfada3e96b1c785..338a494ad160d10c7e3dfae6f4e95d4913722349 100644 (file)
@@ -12,7 +12,7 @@
 
 use std;
 
-import option = option::t;
+import option = option;
 import option::some;
 import option::none;
 import str;
index 357b062471e61a807b1f60624fa6fe7faf5e6a46..67b1505afd9ce2976c9d463db2544db806cf59ed 100644 (file)
@@ -10,7 +10,7 @@
 
 use std;
 
-import option = option::t;
+import option = option;
 import option::{some, none};
 import std::{map, io, time};
 import io::reader_util;
index 82395c710a8f38f1d00e1895f0e61e458c512831..6771a219d1dd7489ad185302b5376d2088c0ea87 100644 (file)
@@ -1,5 +1,6 @@
+// xfail-test
 // error-pattern:expected a syntax expander name
 
 fn main() {
   #();
-}
\ No newline at end of file
+}
index aadbecc40a7c185600b19c7ab617d78c387a691c..b8a4a164c7eecbfda57f096a7f506843639a0387 100644 (file)
@@ -2,8 +2,8 @@
 use std;
 import str::*;
 
-fn main() {
+fn main() unsafe {
     let a: uint = 4u;
     let b: uint = 1u;
-    log(error, safe_slice("kitties", a, b));
+    log(error, str::unsafe::slice_bytes_safe_range("kitties", a, b));
 }
diff --git a/src/test/compile-fail/mode-inference-fail.rs b/src/test/compile-fail/mode-inference-fail.rs
new file mode 100644 (file)
index 0000000..732c9a4
--- /dev/null
@@ -0,0 +1,11 @@
+// In this test, the mode gets inferred to ++ due to the apply_int(),
+// but then we get a failure in the generic apply().
+
+fn apply<A>(f: fn(A) -> A, a: A) -> A { f(a) }
+fn apply_int(f: fn(int) -> int, a: int) -> int { f(a) }
+
+fn main() {
+    let f = {|i| i};
+    assert apply_int(f, 2) == 2;
+    assert apply(f, 2) == 2; //! ERROR expected argument mode ++
+}
diff --git a/src/test/compile-fail/native-type-mismatch.rs b/src/test/compile-fail/native-type-mismatch.rs
deleted file mode 100644 (file)
index 47e5286..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-// error-pattern:expected `sbuf` but found `FILE`
-use std;
-
-fn main() unsafe {
-    let f: std::os::libc::FILE = std::io::rustrt::rust_get_stdin();
-    std::os::libc::fopen(f, f);
-}
index 2a03395f1c161a96fa0496bcc98825b0f007caef..75e4d67028f39a534b68194c22b1abd31c5dd0b5 100644 (file)
@@ -1,20 +1,17 @@
-// error-pattern:Unsatisfied precondition constraint (for example, le(b, d
-use std;
-import str::*;
-import uint::*;
+// error-pattern:Unsatisfied precondition constraint (for example, uint::le
 
-fn main() {
+fn main() unsafe {
     let a: uint = 1u;
     let b: uint = 4u;
     let c: uint = 5u;
     // make sure that the constraint le(b, a) exists...
-    check (le(b, a));
+    check (uint::le(b, a));
     // ...invalidate it...
     b += 1u;
-    check (le(c, a));
+    check (uint::le(c, a));
     // ...and check that it doesn't get set in the poststate of
     // the next statement, since it's not true in the
     // prestate.
     let d <- a;
-    log(debug, safe_slice("kitties", b, d));
+    log(debug, str::unsafe::slice_bytes_safe_range("kitties", b, d));
 }
diff --git a/src/test/compile-fail/non-exhaustive-match-nested.rs b/src/test/compile-fail/non-exhaustive-match-nested.rs
new file mode 100644 (file)
index 0000000..b3b854f
--- /dev/null
@@ -0,0 +1,13 @@
+// -*- rust -*-
+// error-pattern: Non-exhaustive pattern
+enum t { a(u), b }
+enum u { c, d }
+
+fn main() {
+  let x = a(c);
+  alt x {
+      a(d) { fail "hello"; }
+      b { fail "goodbye"; }
+    }
+}
+
diff --git a/src/test/compile-fail/non-exhaustive-match.rs b/src/test/compile-fail/non-exhaustive-match.rs
new file mode 100644 (file)
index 0000000..7beb7f1
--- /dev/null
@@ -0,0 +1,5 @@
+// -*- rust -*-
+// error-pattern: Non-exhaustive pattern
+enum t { a, b, }
+
+fn main() { let x = a; alt x { b { } } }
index 4e7087268644b7566ff64374b9d35f93c3baebe1..6ebc4a2762671f7467db72861c616f6bf174437c 100644 (file)
@@ -6,7 +6,7 @@
 
 // error-pattern: mismatched types
 
-enum bar { t1((), option::t<[int]>), t2, }
+enum bar { t1((), option<[int]>), t2, }
 
 fn foo(t: bar) -> int { alt t { t1(_, some(x)) { ret x * 3; } _ { fail; } } }
 
index 05028b7a3edfd358b5a833a28e48b5d86be08c62..607e32685f3275f11e3d4e5d0dd5ca23ec128648 100644 (file)
@@ -5,7 +5,7 @@
 
 // error-pattern: mismatched types
 
-enum bar { t1((), option::t<[int]>), t2, }
+enum bar { t1((), option<[int]>), t2, }
 
 fn foo(t: bar) {
     alt t {
index 0c0ea02164cf49de34cbc253d521f6fea435d3ca..e429db659ab1915af5831f819dbc24648d152ac2 100644 (file)
@@ -1,6 +1,6 @@
 // -*- rust -*-
 // xfail-test
-// error-pattern:option::t
+// error-pattern:option
 use std;
 import vec::*;
 
index 6beb247e931225c10aaf2691bd52c6212218efbc..2bdc2bad126d37d9491c7d438907f98328d061f7 100644 (file)
@@ -4,5 +4,5 @@
 import std::os;
 
 fn main() {
-  log(debug, 1.0 as os::libc::FILE); // Can't cast float to native.
+  log(debug, 1.0 as os::FILE); // Can't cast float to native.
 }
index 7913f1e33bec0848872e4df325a2f34cf68c263f..d1a7a9b85acfc52c6747752236a4c674f9ca34c3 100644 (file)
@@ -24,7 +24,17 @@ fn test7() -> uint {
     (*regs < 2) as uint
 }
 
-fn test8() -> int { let val = @0; alt true { true { } } *val < 1 ? 0 : 1 }
+fn test8() -> int {
+    let val = @0;
+    alt true {
+        true { }
+    }
+    if *val < 1 {
+        0
+    } else {
+        1
+    }
+}
 
 fn test9() { let regs = @mutable 0; alt true { true { } } *regs += 1; }
 
index a60d72988e6e615db0fb5028f82b46f8341c6fb7..d603c1d8e57bd4c3ecd0cb9b261cb34419f53d0c 100644 (file)
@@ -4,5 +4,5 @@
 fn main() {
     let sth = {x: 0, y: 1,};
     let sth2 = {y: 9 with sth};
-    assert (sth.x + sth2.y == 9);
+    assert sth.x + sth2.y == 9;
 }
index 40e259a0446a030b5aa18b6d7874e315b908d546..2c7934fdffca0b42ff5ad54dbb07ba1a31fe9852 100644 (file)
@@ -1,11 +1,8 @@
-// error-pattern:Predicate le(a, b) failed
-use std;
-import str::*;
-import uint::le;
+// error-pattern:Predicate uint::le(a, b) failed
 
-fn main() {
+fn main() unsafe {
     let a: uint = 4u;
     let b: uint = 1u;
-    check (le(a, b));
-    log(error, safe_slice("kitties", a, b));
+    check (uint::le(a, b));
+    log(error, str::unsafe::slice_bytes_safe_range("kitties", a, b));
 }
index 60b79ee153706281201351c0a700f1b22c2cd4f4..15123a0540df652fe5e3108282a3b68652df63b8 100644 (file)
@@ -8,14 +8,14 @@
 use std;
 
 native mod rustrt {
-    fn pin_task();
+    fn last_os_error() -> str;
 }
 
 fn getbig_call_c_and_fail(i: int) {
     if i != 0 {
         getbig_call_c_and_fail(i - 1);
     } else {
-        rustrt::pin_task();
+        rustrt::last_os_error();
         fail;
     }
 }
index b36372d74e1ced0a278367394c627d69ba8685ea..8f0ccec560f7164bf4ab6e15ac0a503f863bff56 100644 (file)
@@ -4,10 +4,6 @@
 
 use std;
 
-native mod rustrt {
-    fn set_min_stack(size: uint);
-}
-
 fn getbig_and_fail(&&i: int) {
     let r = and_then_get_big_again(@0);
     if i != 0 {
@@ -21,7 +17,6 @@ fn getbig_and_fail(&&i: int) {
 }
 
 fn main() {
-    rustrt::set_min_stack(256u);
     task::spawn {||
         getbig_and_fail(1);
     };
diff --git a/src/test/run-fail/non-exhaustive-match.rs b/src/test/run-fail/non-exhaustive-match.rs
deleted file mode 100644 (file)
index c6127d1..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-// -*- rust -*-
-
-// error-pattern:non-exhaustive match failure
-enum t { a, b, }
-
-fn main() { let x = a; alt x { b { } } }
index 01b850dabeb94b6af713fb4b08816ccd8542d3cd..0679022d37a9879309d3054288928148a5d9a050 100644 (file)
@@ -7,9 +7,9 @@
 
 enum sty { ty_nil, }
 
-type raw_t = {struct: sty, cname: option::t<str>, hash: uint};
+type raw_t = {struct: sty, cname: option<str>, hash: uint};
 
-fn mk_raw_ty(st: sty, cname: option::t<str>) -> raw_t {
+fn mk_raw_ty(st: sty, cname: option<str>) -> raw_t {
     ret {struct: st, cname: cname, hash: 0u};
 }
 
index 687cf30f97fe95676ef73fc59405b3d4fc9d37c9..77b52da4acfc660593d17080b76dc77fc8046fbb 100644 (file)
@@ -1,11 +1,8 @@
 
 use std;
 import option;
-import option::t;
-import option::none;
-import option::some;
 
-fn foo<T>(y: option::t<T>) {
+fn foo<T>(y: option<T>) {
     let x: int;
     let rs: [int] = [];
     /* tests that x doesn't get put in the precondition for the
index cd7497aeda466ce39532ed9adcdb15949cca7b3d..aa3ccfcbafd6690c2b51b1dc9fdbc6cc94260162 100644 (file)
@@ -4,6 +4,6 @@ mod m1 {
     enum foo { foo1, foo2, }
 }
 
-fn bar(x: m1::foo) { alt x { m1::foo1 { } } }
+fn bar(x: m1::foo) { alt x { m1::foo1 { } m1::foo2 { } } }
 
 fn main() { }
index dddbf575d8075b6071ba0795091306443cc5c012..7451055f0a6287b2faa4b1757754bae84ac1a212 100644 (file)
@@ -4,7 +4,7 @@
 
 #[abi = "cdecl"]
 native mod rustrt {
-    fn pin_task();
+    fn rand_new() -> *ctypes::void;
 }
 
-fn main() { bind rustrt::pin_task(); }
+fn main() { bind rustrt::rand_new(); }
index 2f0430cda57b66f0831f7f5ccbf3e9543ebdedef..11fc041d08f23588858ad30df3abe9dbc5b81d70 100644 (file)
@@ -120,15 +120,13 @@ fn h(i: int) { }
 #[abi = "cdecl"]
 #[nolink]
 native mod test {
-    fn do_gc();
     fn unsupervise();
 }
 
 // FIXME (#1058): comparison of native fns
 fn test_native_fn() {
     /*
-    assert (native_mod::do_gc == native_mod::do_gc);
-    assert (native_mod::do_gc != native_mod::unsupervise);
+    assert (native_mod::last_os_error != native_mod::unsupervise);
     */
 }
 
diff --git a/src/test/run-pass/block-arg-in-ternary.rs b/src/test/run-pass/block-arg-in-ternary.rs
deleted file mode 100644 (file)
index 84ad2da..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-// Allow block arguments with ternary... why not, no chance of ambig.
-fn main() {
-    let v = [-1f, 1f];
-    let foo = vec::any(v) { |e| float::is_negative(e) } ? true : false;
-    assert foo;
-}
diff --git a/src/test/run-pass/classes.rs b/src/test/run-pass/classes.rs
new file mode 100644 (file)
index 0000000..2d67bc2
--- /dev/null
@@ -0,0 +1,29 @@
+// xfail-test
+class cat {
+  priv {
+    let mutable meows : uint;
+    fn meow() {
+      #error("Meow");
+      meows += 1;
+      if meows % 5 == 0 {
+          how_hungry += 1;
+      }
+    }
+  }
+
+  let how_hungry : int;
+
+  new(in_x : uint, in_y : int) { meows = in_x; how_hungry = in_y; }
+
+  fn speak() { meow(); }
+
+  fn eat() {
+    if how_hungry > 0 {
+        #error("OM NOM NOM");
+        how_hungry -= 2;
+    }
+    else {
+        #error("Not hungry!");
+    }
+  }
+}
\ No newline at end of file
diff --git a/src/test/run-pass/closure-inference.rs b/src/test/run-pass/closure-inference.rs
new file mode 100644 (file)
index 0000000..72d08a5
--- /dev/null
@@ -0,0 +1,8 @@
+fn foo(i: int) -> int { i + 1 }
+
+fn apply<A>(f: fn(A) -> A, v: A) -> A { f(v) }
+
+fn main() {
+    let f = {|i| foo(i)};
+    assert apply(f, 2) == 3;
+}
diff --git a/src/test/run-pass/closure-inference2.rs b/src/test/run-pass/closure-inference2.rs
new file mode 100644 (file)
index 0000000..159bd7c
--- /dev/null
@@ -0,0 +1,7 @@
+// Test a rather underspecified example:
+
+fn main() {
+    let f = {|i| i};
+    assert f(2) == 2;
+    assert f(5) == 5;
+}
index 7848d9b9bd5392f9c9c826d3f1f640835b4b34e0..e4a2badb9ec847d81d0cc64fd7a59454e6c29ff3 100644 (file)
@@ -1,12 +1,9 @@
-use std;
-import str::*;
-import uint::*;
 
-fn main() {
+fn main() unsafe {
     let a: uint = 1u;
     let b: uint = 4u;
     let c: uint = 17u;
-    check (le(a, b));
+    check (uint::le(a, b));
     c <- a;
-    log(debug, safe_slice("kitties", c, b));
+    log(debug, str::unsafe::slice_bytes_safe_range("kitties", c, b));
 }
index 347ea13f0051d5c93863af6033513949ce53e16e..a12ba6b04d58b91e49198d59737fc1864eb93e64 100644 (file)
@@ -1,11 +1,7 @@
-use std;
-import str::*;
-import uint::*;
-
-fn main() {
+fn main() unsafe {
     let a: uint = 1u;
     let b: uint = 4u;
-    check (le(a, b));
+    check (uint::le(a, b));
     let c <- a;
-    log(debug, safe_slice("kitties", c, b));
+    log(debug, str::unsafe::slice_bytes_safe_range("kitties", c, b));
 }
index 748044893ed5f53928c7f5c9e2412a16bc3548fb..a20702954872d82e8fc1903e62db581de50919d5 100644 (file)
@@ -1,11 +1,7 @@
-use std;
-import str::*;
-import uint::*;
-
-fn main() {
+fn main() unsafe {
     let a: uint = 4u;
     let b: uint = 1u;
-    check (le(b, a));
+    check (uint::le(b, a));
     b <-> a;
-    log(debug, safe_slice("kitties", a, b));
+    log(debug, str::unsafe::slice_bytes_safe_range("kitties", a, b));
 }
index f15c0f4121d77000c6dfa1f2c39c6edd61f63efd..2bbff1342d28627871059e59a2f6ed59b56ea59d 100644 (file)
@@ -1,11 +1,7 @@
-use std;
-import str::*;
-import uint::*;
-
-fn main() {
+fn main() unsafe {
     let a: uint = 1u;
     let b: uint = 4u;
-    check (le(a, b));
+    check (uint::le(a, b));
     let c = b;
-    log(debug, safe_slice("kitties", a, c));
+    log(debug, str::unsafe::slice_bytes_safe_range("kitties", a, c));
 }
index afb63b7f406edd89fc7feee5a2b4473363164950..b050b4d2b862befdfc4f61d47a435435b3cb7ff3 100644 (file)
@@ -10,7 +10,7 @@ fn main() {
 }
 
 fn test_color(color: color, val: int, name: str) {
-    assert (color as int == val);
-    assert (color as float == val as float);
+    assert color as int == val;
+    assert color as float == val as float;
 }
 
index 68106f298617f2ccfb8c566982f2e09b7bf86647..20cca31e2a19903649ef106b294968e2d9663553 100644 (file)
@@ -1,10 +1,6 @@
-use std;
-import str::*;
-import uint::*;
-
-fn main() {
+fn main() unsafe {
     let a: uint = 1u;
     let b: uint = 4u;
-    check (le(a, b));
-    log(debug, safe_slice("kitties", a, b));
+    check (uint::le(a, b));
+    log(debug, str::unsafe::slice_bytes_safe_range("kitties", a, b));
 }
index 9301d93874ebed0e4ed623a7f007df05e3b04fb8..eeed3d32800a559594103ee30388b618fc130738 100644 (file)
@@ -6,7 +6,7 @@
 
 use std;
 
-import option = option::t;
+import option = option;
 import option::some;
 import option::none;
 import str;
index f95f5c85eed95852c3d46745d4a549ad58e585a1..c37dc989f389b8b057bcf931cf49752c0072e7cf 100644 (file)
@@ -12,11 +12,9 @@ fn to_str() -> str { "()" }
 }
 
 iface map<T> {
-    fn iter(fn(T));
     fn map<U>(f: fn(T) -> U) -> [U];
 }
 impl <T> of map<T> for [T] {
-    fn iter(_f: fn(T)) {}
     fn map<U>(f: fn(T) -> U) -> [U] {
         let r = [];
         for x in self { r += [f(x)]; }
diff --git a/src/test/run-pass/issue-1660.rs b/src/test/run-pass/issue-1660.rs
new file mode 100644 (file)
index 0000000..0f4958e
--- /dev/null
@@ -0,0 +1,3 @@
+fn main() {
+    const _x: int = 1<<2;
+}
index 36b2e65897ee5ec74dd44f148588758421ff6068..34e8a8e47b920c3430fa6539104006cf094e6410 100644 (file)
@@ -1,7 +1,7 @@
 use std;
 import option;
 
-fn f<T>(&o: option::t<T>) {
+fn f<T>(&o: option<T>) {
     assert o == option::none;
 }
 
index ba00bb4a3020a28377bb0f7c758a67ac9a56d7b9..4333fa3d57332a57e2a0c07b377935349157182f 100644 (file)
@@ -162,9 +162,6 @@ mod test_native_items {
     native mod rustrt {
         #[attr];
 
-        #[attr]
-        type sbuf;
-
         #[attr]
         fn unsupervise();
     }
diff --git a/src/test/run-pass/method-attributes.rs b/src/test/run-pass/method-attributes.rs
new file mode 100644 (file)
index 0000000..32230df
--- /dev/null
@@ -0,0 +1,24 @@
+// pp-exact - Make sure we print all the attributes
+
+#[frobable]
+iface frobable {
+    #[frob_attr]
+    fn frob();
+    #[defrob_attr]
+    fn defrob();
+}
+
+#[int_frobable]
+impl frobable for int {
+    #[frob_attr1]
+    fn frob() {
+        #[frob_attr2];
+    }
+
+    #[defrob_attr1]
+    fn defrob() {
+        #[defrob_attr2];
+    }
+}
+
+fn main() { }
index 6c1d906e1e6cfcbfcbf87fdaef04f445801aea96..ecd187ae44ad44944086d15356a0e5645f31917d 100644 (file)
@@ -3,10 +3,6 @@
 use std;
 import task;
 
-native mod rustrt {
-    fn set_min_stack(size: uint);
-}
-
 fn getbig(&&i: int) {
     if i != 0 {
         getbig(i - 1);
@@ -16,7 +12,6 @@ fn getbig(&&i: int) {
 fn main() {
     let sz = 400u;
     while sz < 500u {
-        rustrt::set_min_stack(sz);
         task::join(task::spawn_joinable {|| getbig(200) });
         sz += 1u;
     }
index 2e30b942c1e4097432025d75bb7c986a877b7d54..87ff60f13a7bf8517bb1ddde4cb45fc0bf30859e 100644 (file)
@@ -6,16 +6,12 @@
 import std::rand;
 
 native mod rustrt {
-    fn set_min_stack(size: uint);
     fn debug_get_stk_seg() -> *u8;
 
     fn unsupervise();
     fn last_os_error() -> str;
     fn rust_getcwd() -> str;
     fn refcount(box: @int);
-    fn do_gc();
-    fn pin_task();
-    fn unpin_task();
     fn get_task_id();
     fn sched_threads();
     fn rust_get_task();
@@ -25,9 +21,6 @@
 fn calllink02() { rustrt::last_os_error(); }
 fn calllink03() { rustrt::rust_getcwd(); }
 fn calllink04() { rustrt::refcount(@0); }
-fn calllink05() { rustrt::do_gc(); }
-fn calllink06() { rustrt::pin_task(); }
-fn calllink07() { rustrt::unpin_task(); }
 fn calllink08() { rustrt::get_task_id(); }
 fn calllink09() { rustrt::sched_threads(); }
 fn calllink10() { rustrt::rust_get_task(); }
@@ -60,9 +53,6 @@ fn main() {
         calllink02,
         calllink03,
         calllink04,
-        calllink05,
-        calllink06,
-        calllink07,
         calllink08,
         calllink09,
         calllink10
@@ -71,7 +61,6 @@ fn main() {
     for f in fns {
         let sz = rng.next() % 256u32 + 256u32;
         let frame_backoff = rng.next() % 10u32 + 1u32;
-        rustrt::set_min_stack(sz as uint);
         task::join(task::spawn_joinable {|| runtest(f, frame_backoff);});
     }
 }
\ No newline at end of file
index 22c53fda4f396c33078cb873608f0c506bd1f23a..139189f4b9c28e5b8eca8ad98e0415e5bcb4e141 100644 (file)
@@ -4,16 +4,16 @@
 #[abi = "cdecl"]
 #[link_name = "rustrt"]
 native mod rustrt1 {
-    fn pin_task();
+    fn last_os_error() -> str;
 }
 
 #[abi = "cdecl"]
 #[link_name = "rustrt"]
 native mod rustrt2 {
-    fn pin_task();
+    fn last_os_error() -> str;
 }
 
 fn main() {
-    rustrt1::pin_task();
-    rustrt2::pin_task();
+    rustrt1::last_os_error();
+    rustrt2::last_os_error();
 }
diff --git a/src/test/run-pass/native-opaque-type.rs b/src/test/run-pass/native-opaque-type.rs
deleted file mode 100644 (file)
index e91b4e6..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-#[abi = "cdecl"]
-#[nolink]
-native mod libc {
-    type file_handle;
-}
-
-fn main() { assert (true); }
index 2bd5e9ff33039e245c603b64e3ac60e29a7d5af6..6eda8f11489c9d68b28e97df6235ea5be95b2665 100644 (file)
@@ -6,7 +6,7 @@
 import option::some;
 import option::none;
 
-enum t { foo(int, uint), bar(int, option::t<int>), }
+enum t { foo(int, uint), bar(int, option<int>), }
 
 fn nested(o: t) {
     alt o {
index 42933578b3bc3d4d9b069511df3b8ce7b37fdb08..a04b2272e37ff590711c146c48cdfe195b56733b 100644 (file)
@@ -11,7 +11,7 @@ fn unary-() -> point {
         {x: -self.x, y: -self.y}
     }
     fn [](x: bool) -> int {
-        x ? self.x : self.y
+        if x { self.x } else { self.y }
     }
 }
 
@@ -23,4 +23,6 @@ fn main() {
     assert -p == {x: -11, y: -22};
     assert p[true] == 11;
     assert p[false] == 22;
+    // Issue #1733
+    fn~(_x: int){}(p[true]);
 }
diff --git a/src/test/run-pass/qquote.rs b/src/test/run-pass/qquote.rs
new file mode 100644 (file)
index 0000000..f307d64
--- /dev/null
@@ -0,0 +1,93 @@
+// xfail-pretty
+
+use std;
+use rustc;
+
+import rustc::*;
+import std::io::*;
+
+import rustc::driver::diagnostic;
+import rustc::syntax::ast;
+import rustc::syntax::codemap;
+import rustc::syntax::parse::parser;
+import rustc::syntax::print::*;
+
+fn new_parse_sess() -> parser::parse_sess {
+    let cm = codemap::new_codemap();
+    let handler = diagnostic::mk_handler(option::none);
+    let sess = @{
+        cm: cm,
+        mutable next_id: 1,
+        span_diagnostic: diagnostic::mk_span_handler(handler, cm),
+        mutable chpos: 0u,
+        mutable byte_pos: 0u
+    };
+    ret sess;
+}
+
+iface fake_ext_ctxt {
+    fn session() -> fake_session;
+}
+
+type fake_options = {cfg: ast::crate_cfg};
+
+type fake_session = {opts: @fake_options,
+                     parse_sess: parser::parse_sess};
+
+impl of fake_ext_ctxt for fake_session {
+    fn session() -> fake_session {self}
+}
+
+fn mk_ctxt() -> fake_ext_ctxt {
+    let opts : fake_options = {cfg: []};
+    {opts: @opts, parse_sess: new_parse_sess()} as fake_ext_ctxt
+}
+
+
+fn main() {
+    let ext_cx = mk_ctxt();
+
+    let abc = #ast{23};
+    check_pp(abc,  pprust::print_expr, "23");
+
+    let expr3 = #ast{2 - $(abc) + 7};
+    check_pp(expr3,  pprust::print_expr, "2 - 23 + 7");
+
+    let expr4 = #ast{2 - $(#(3)) + 9};
+    check_pp(expr4,  pprust::print_expr, "2 - 3 + 9");
+
+    let ty = #ast(ty){int};
+    check_pp(ty, pprust::print_type, "int");
+
+    let ty2 = #ast(ty){option<$(ty)>};
+    check_pp(ty2, pprust::print_type, "option<int>");
+
+    let item = #ast(item){const x : int = 10;};
+    check_pp(item, pprust::print_item, "const x: int = 10;");
+
+    let item2: @ast::item = #ast(item){const x : int = $(abc);};
+    check_pp(item2, pprust::print_item, "const x: int = 23;");
+
+    let stmt = #ast(stmt){let x = 20;};
+    check_pp(*stmt, pprust::print_stmt, "let x = 20;");
+
+    let stmt2 = #ast(stmt){let x : $(ty) = $(abc);};
+    check_pp(*stmt2, pprust::print_stmt, "let x: int = 23;");
+
+    let pat = #ast(pat){some(_)};
+    check_pp(pat, pprust::print_pat, "some(_)");
+}
+
+fn check_pp<T>(expr: T, f: fn(pprust::ps, T), expect: str) {
+    let buf = mk_mem_buffer();
+    let pp = pprust::rust_printer(buf as std::io::writer);
+    f(pp, expr);
+    pp::eof(pp.s);
+    let str = mem_buffer_str(buf);
+    stdout().write_line(str);
+    if expect != "" {
+        #error("expect: '%s', got: '%s'", expect, str);
+        assert str == expect;
+    }
+}
+
index 9777de4b1460157251063ab9b7e2da13d150a382..65b793564ad876de246770ba9d3a25fead74cc19 100644 (file)
@@ -9,7 +9,7 @@
 
 enum opt_span {
 
-    //hack (as opposed to option::t), to make `span` compile
+    //hack (as opposed to option), to make `span` compile
     os_none,
     os_some(@span),
 }
index de9dffbaca33951a3cfa81eabda68e9115464867..84f279bca5d1d7923d294dd023563bd385e57125 100644 (file)
@@ -2,7 +2,7 @@
 import std::os;
 
 fn main() {
-  let f = 1 as os::libc::FILE;
+  let f = 1 as os::FILE;
   log(debug, f as int);
   log(debug, f as uint);
   log(debug, f as i8);
@@ -18,7 +18,7 @@ fn main() {
   log(debug, 1 as uint);
   log(debug, 1 as float);
   log(debug, 1 as bool);
-  log(debug, 1 as os::libc::FILE);
+  log(debug, 1 as os::FILE);
   log(debug, 1 as i8);
   log(debug, 1 as i16);
   log(debug, 1 as i32);
@@ -34,7 +34,7 @@ fn main() {
   log(debug, 1u as uint);
   log(debug, 1u as float);
   log(debug, 1u as bool);
-  log(debug, 1u as os::libc::FILE);
+  log(debug, 1u as os::FILE);
   log(debug, 1u as i8);
   log(debug, 1u as i16);
   log(debug, 1u as i32);
@@ -50,7 +50,7 @@ fn main() {
   log(debug, 1i8 as uint);
   log(debug, 1i8 as float);
   log(debug, 1i8 as bool);
-  log(debug, 1i8 as os::libc::FILE);
+  log(debug, 1i8 as os::FILE);
   log(debug, 1i8 as i8);
   log(debug, 1i8 as i16);
   log(debug, 1i8 as i32);
@@ -66,7 +66,7 @@ fn main() {
   log(debug, 1u8 as uint);
   log(debug, 1u8 as float);
   log(debug, 1u8 as bool);
-  log(debug, 1u8 as os::libc::FILE);
+  log(debug, 1u8 as os::FILE);
   log(debug, 1u8 as i8);
   log(debug, 1u8 as i16);
   log(debug, 1u8 as i32);
@@ -82,7 +82,7 @@ fn main() {
   log(debug, 1i16 as uint);
   log(debug, 1i16 as float);
   log(debug, 1i16 as bool);
-  log(debug, 1i16 as os::libc::FILE);
+  log(debug, 1i16 as os::FILE);
   log(debug, 1i16 as i8);
   log(debug, 1i16 as i16);
   log(debug, 1i16 as i32);
@@ -98,7 +98,7 @@ fn main() {
   log(debug, 1u16 as uint);
   log(debug, 1u16 as float);
   log(debug, 1u16 as bool);
-  log(debug, 1u16 as os::libc::FILE);
+  log(debug, 1u16 as os::FILE);
   log(debug, 1u16 as i8);
   log(debug, 1u16 as i16);
   log(debug, 1u16 as i32);
@@ -114,7 +114,7 @@ fn main() {
   log(debug, 1i32 as uint);
   log(debug, 1i32 as float);
   log(debug, 1i32 as bool);
-  log(debug, 1i32 as os::libc::FILE);
+  log(debug, 1i32 as os::FILE);
   log(debug, 1i32 as i8);
   log(debug, 1i32 as i16);
   log(debug, 1i32 as i32);
@@ -130,7 +130,7 @@ fn main() {
   log(debug, 1u32 as uint);
   log(debug, 1u32 as float);
   log(debug, 1u32 as bool);
-  log(debug, 1u32 as os::libc::FILE);
+  log(debug, 1u32 as os::FILE);
   log(debug, 1u32 as i8);
   log(debug, 1u32 as i16);
   log(debug, 1u32 as i32);
@@ -146,7 +146,7 @@ fn main() {
   log(debug, 1i64 as uint);
   log(debug, 1i64 as float);
   log(debug, 1i64 as bool);
-  log(debug, 1i64 as os::libc::FILE);
+  log(debug, 1i64 as os::FILE);
   log(debug, 1i64 as i8);
   log(debug, 1i64 as i16);
   log(debug, 1i64 as i32);
@@ -162,7 +162,7 @@ fn main() {
   log(debug, 1u64 as uint);
   log(debug, 1u64 as float);
   log(debug, 1u64 as bool);
-  log(debug, 1u64 as os::libc::FILE);
+  log(debug, 1u64 as os::FILE);
   log(debug, 1u64 as i8);
   log(debug, 1u64 as i16);
   log(debug, 1u64 as i32);
@@ -178,7 +178,7 @@ fn main() {
   log(debug, 1u64 as uint);
   log(debug, 1u64 as float);
   log(debug, 1u64 as bool);
-  log(debug, 1u64 as os::libc::FILE);
+  log(debug, 1u64 as os::FILE);
   log(debug, 1u64 as i8);
   log(debug, 1u64 as i16);
   log(debug, 1u64 as i32);
@@ -194,7 +194,7 @@ fn main() {
   log(debug, true as uint);
   log(debug, true as float);
   log(debug, true as bool);
-  log(debug, true as os::libc::FILE);
+  log(debug, true as os::FILE);
   log(debug, true as i8);
   log(debug, true as i16);
   log(debug, true as i32);
index f92585cd2542793af106b8ff48d84c52bcd1928b..beaa93c02e0d021f72bb204f28e0bbd3a0a886bf 100644 (file)
@@ -10,7 +10,11 @@ fn test00() {
     let t = task::spawn_joinable {|| start(i); };
 
     // Sleep long enough for the task to finish.
-    task::sleep(10000u);
+    let i = 0;
+    while i < 10000 {
+        task::yield();
+        i += 1;
+    }
 
     // Try joining tasks that have already finished.
     task::join(t);
diff --git a/src/test/run-pass/task-pin.rs b/src/test/run-pass/task-pin.rs
deleted file mode 100644 (file)
index f989c12..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-/**
-   Exercises task pinning and unpinning. Doesn't really ensure it
-   works, just makes sure it runs.
-*/
-
-use std;
-
-import task;
-
-fn main() { task::pin(); task::unpin(); }
diff --git a/src/test/run-pass/ternary.rs b/src/test/run-pass/ternary.rs
deleted file mode 100644 (file)
index 6adfada..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-fn test_simple() { let x = true ? 10 : 11; assert (x == 10); }
-
-fn test_precedence() {
-    let x;
-
-    x = true || true ? 10 : 11;
-    assert (x == 10);
-
-    x = true == false ? 10 : 11;
-    assert (x == 11);
-
-    x = true ? false ? 10 : 11 : 12;
-    assert (x == 11);
-
-    let y = true ? 0xF0 : 0x0 | 0x0F;
-    assert (y == 0xF0);
-
-    y = true ? 0xF0 | 0x0F : 0x0;
-    assert (y == 0xFF);
-}
-
-fn test_associativity() {
-    // Ternary is right-associative
-    let x = false ? 10 : false ? 11 : 12;
-    assert (x == 12);
-}
-
-fn test_lval() {
-    let box1: @mutable int = @mutable 10;
-    let box2: @mutable int = @mutable 10;
-    *(true ? box1 : box2) = 100;
-    assert (*box1 == 100);
-}
-
-fn test_as_stmt() { let s; true ? s = 10 : s = 12; assert (s == 10); }
-
-fn main() {
-    test_simple();
-    test_precedence();
-    test_associativity();
-    test_lval();
-    test_as_stmt();
-}
index 67e3dbcb46cfea2120e5e163a2789f933127f43d..7b4e9bf6d1c4d1065d7e5516182632ef388e1489 100644 (file)
@@ -9,8 +9,8 @@ fn main() {
 
     assert (str::byte_len(s) == 10u);
     assert (str::char_len(s) == 4u);
-    assert (vec::len::<char>(str::to_chars(s)) == 4u);
-    assert (str::eq(str::from_chars(str::to_chars(s)), s));
+    assert (vec::len::<char>(str::chars(s)) == 4u);
+    assert (str::eq(str::from_chars(str::chars(s)), s));
     assert (str::char_at(s, 0u) == 'e');
     assert (str::char_at(s, 1u) == 'é');
 
index 6b110e9e275a62038df0209842048040baae12dc..4093a311b097448e44b4c8043a8333c9b09c8503 100644 (file)
@@ -19,7 +19,15 @@ fn zombiejesus() {
     do  {
         while (ret) {
             if (ret) {
-                alt (ret) { _ { ret ? ret : ret } };
+                alt (ret) {
+                    _ {
+                        if (ret) {
+                            ret
+                        } else {
+                            ret
+                        }
+                    }
+                };
             } else if (ret) {
                 ret;
             }