diff --git a/Makefile.in b/Makefile.in index 3ad038e8358..7e77f6fd678 100644 --- a/Makefile.in +++ b/Makefile.in @@ -221,7 +221,6 @@ CFG_LIBRUSTC_$(1) :=$(call CFG_LIB_NAME_$(1),rustc) CFG_LIBSYNTAX_$(1) :=$(call CFG_LIB_NAME_$(1),syntax) CFG_LIBRUSTPKG_$(1) :=$(call CFG_LIB_NAME_$(1),rustpkg) CFG_LIBRUSTDOC_$(1) :=$(call CFG_LIB_NAME_$(1),rustdoc) -CFG_LIBRUSTI_$(1) :=$(call CFG_LIB_NAME_$(1),rusti) EXTRALIB_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),extra) STDLIB_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),std) @@ -229,14 +228,12 @@ LIBRUSTC_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),rustc) LIBSYNTAX_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),syntax) LIBRUSTPKG_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),rustpkg) LIBRUSTDOC_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),rustdoc) -LIBRUSTI_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),rusti) EXTRALIB_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),extra) STDLIB_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),std) LIBRUSTC_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),rustc) LIBSYNTAX_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),syntax) LIBRUSTPKG_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),rustpkg) LIBRUSTDOC_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),rustdoc) -LIBRUSTI_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),rusti) endef @@ -446,14 +443,12 @@ CSREQ$(1)_T_$(2)_H_$(3) = \ $$(HBIN$(1)_H_$(3))/rusti$$(X_$(3)) \ $$(HLIB$(1)_H_$(3))/$(CFG_LIBRUSTPKG_$(3)) \ $$(HLIB$(1)_H_$(3))/$(CFG_LIBRUSTDOC_$(3)) \ - $$(HLIB$(1)_H_$(3))/$(CFG_LIBRUSTI_$(3)) \ $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_STDLIB_$(2)) \ $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_EXTRALIB_$(2)) \ $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBSYNTAX_$(2)) \ $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTC_$(2)) \ $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTPKG_$(2)) \ - $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTDOC_$(2)) \ - $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTI_$(2)) \ + $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTDOC_$(2)) ifeq ($(1),0) # Don't run the the stage0 compiler under valgrind - that ship has sailed diff --git a/RELEASES.txt b/RELEASES.txt index 9aea24dd22d..e2dfa320327 100644 --- a/RELEASES.txt +++ b/RELEASES.txt @@ -1,3 +1,11 @@ +Version 0.9 (XXX 2013) +-------------------------- + + * ~XXX changes, numerous bugfixes + + * Tooling + * The `rust` and `rusti` commands have been removed, due to lack of maintenance. + Version 0.8 (September 2013) -------------------------- diff --git a/doc/tutorial.md b/doc/tutorial.md index 3723d12262b..241e0367fef 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -113,9 +113,7 @@ for more information on them. When complete, `make install` will place several programs into `/usr/local/bin`: `rustc`, the Rust compiler; `rustdoc`, the -API-documentation tool; `rustpkg`, the Rust package manager; -`rusti`, the Rust REPL; and `rust`, a tool which acts both as a unified -interface for them, and for a few common command line scenarios. +API-documentation tool; and `rustpkg`, the Rust package manager. [tarball]: http://static.rust-lang.org/dist/rust-0.8.tar.gz [win-exe]: http://static.rust-lang.org/dist/rust-0.8-install.exe diff --git a/man/rustc.1 b/man/rustc.1 index 2298d5e5455..e4cfab7747f 100644 --- a/man/rustc.1 +++ b/man/rustc.1 @@ -130,7 +130,7 @@ To build an executable with debug info (experimental): .SH "SEE ALSO" -rust, rustdoc, rustpkg, rusti +rustdoc, rustpkg .SH "BUGS" See <\fBhttps://github.com/mozilla/rust/issues\fR> for issues. diff --git a/man/rustdoc.1 b/man/rustdoc.1 index c7cdb832887..78340984f96 100644 --- a/man/rustdoc.1 +++ b/man/rustdoc.1 @@ -84,7 +84,7 @@ The generated HTML can be viewed with any standard web browser. .SH "SEE ALSO" -rust, rustc, rustpkg, rusti +rustc, rustpkg .SH "BUGS" See <\fBhttps://github.com/mozilla/rust/issues\fR> for issues. diff --git a/man/rusti.1 b/man/rusti.1 deleted file mode 100644 index 9f7d1733c65..00000000000 --- a/man/rusti.1 +++ /dev/null @@ -1,82 +0,0 @@ -.TH RUSTI "1" "July 2013" "rusti 0.7" "User Commands" -\" Macros -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.SH NAME -rusti \- Rust interactive shell - -.SH SYNOPSIS -.B rusti - -.SH DESCRIPTION - -This program is a REPL (Read-Eval-Print Loop) for the Rust language, available -at <\fBhttps://www.rust-lang.org\fR>. It provides an interactive shell to -evaluate Rust expressions, functions and code snippets, and to experiment with -Rust code. - -.B WARNING: -The Rust REPL is experimental and may be unstable. If you encounter problems, -please use the compiler instead. - -.SH OPTIONS - -Currently none. - -.SH SPECIAL COMMANDS - -The interactive shell evaluates all input as a sequence of Rust expressions, -except for a set of special commands prefixed by a colon ':'. These special -commands are described below: - -.TP -\fB:help\fR -Display a summary of available commands. -.TP -\fB:{\\n ..lines.. \\n:}\\n\fR -execute multiline command -.TP -\fB:load ...\fR -loads given crates as dynamic libraries -.TP -\fB:clear\fR -clear the bindings -.TP -\fB:exit\fR -exit from the repl - -.SH "EXAMPLES" - -A simple example session, declaring a variable, defining a function, -evaluating an expression and printing the result: - -.PP -.Vb -\& \fBrusti>\fR let x = 42; -\& \fBrusti>\fR fn square(n: int) -> int { n*n } -\& \fBrusti>\fR println(fmt!("%d squared is %d", x, square(x))); -\& 42 squared is 1764 -.Ve - -.SH "SEE ALSO" - -rust, rustc, rustdoc, rustpkg - -.SH "BUGS" -See <\fBhttps://github.com/mozilla/rust/issues\fR> for issues. - -.SH "AUTHOR" -See \fBAUTHORS.txt\fR in the rust source distribution. Graydon Hoare -<\fIgraydon@mozilla.com\fR> is the project leader. - -.SH "COPYRIGHT" -This work is dual-licensed under Apache 2.0 and MIT terms. See \fBCOPYRIGHT\fR -file in the rust source distribution. diff --git a/man/rustpkg.1 b/man/rustpkg.1 index d23a1f4368e..856f9022813 100644 --- a/man/rustpkg.1 +++ b/man/rustpkg.1 @@ -181,7 +181,7 @@ custom build logic. .SH "SEE ALSO" -rust, rustc, rustdoc, rusti +rustc, rustdoc .SH "BUGS" See <\fBhttps://github.com/mozilla/rust/issues\fR> for issues. diff --git a/mk/clean.mk b/mk/clean.mk index d1e3afe98a0..09a80c5507b 100644 --- a/mk/clean.mk +++ b/mk/clean.mk @@ -67,7 +67,6 @@ clean$(1)_H_$(2): $(Q)rm -f $$(HBIN$(1)_H_$(2))/rustpkg$(X_$(2)) $(Q)rm -f $$(HBIN$(1)_H_$(2))/serializer$(X_$(2)) $(Q)rm -f $$(HBIN$(1)_H_$(2))/rustdoc$(X_$(2)) - $(Q)rm -f $$(HBIN$(1)_H_$(2))/rusti$(X_$(2)) $(Q)rm -f $$(HBIN$(1)_H_$(2))/rust$(X_$(2)) $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_LIBRUSTPKG_$(2)) $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_LIBRUSTDOC_$(2)) @@ -76,14 +75,12 @@ clean$(1)_H_$(2): $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_EXTRALIB_$(2)) $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_LIBRUSTC_$(2)) $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_LIBSYNTAX_$(2)) - $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_LIBRUSTI_$(2)) $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(STDLIB_GLOB_$(2)) $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(EXTRALIB_GLOB_$(2)) $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(LIBRUSTC_GLOB_$(2)) $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(LIBSYNTAX_GLOB_$(2)) $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(LIBRUSTPKG_GLOB_$(2)) $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(LIBRUSTDOC_GLOB_$(2)) - $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(LIBRUSTI_GLOB_$(2)) $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_RUSTLLVM_$(2)) $(Q)rm -f $$(HLIB$(1)_H_$(2))/libstd.rlib @@ -100,7 +97,6 @@ clean$(1)_T_$(2)_H_$(3): $(Q)rm -f $$(TBIN$(1)_T_$(2)_H_$(3))/rustpkg$(X_$(2)) $(Q)rm -f $$(TBIN$(1)_T_$(2)_H_$(3))/serializer$(X_$(2)) $(Q)rm -f $$(TBIN$(1)_T_$(2)_H_$(3))/rustdoc$(X_$(2)) - $(Q)rm -f $$(TBIN$(1)_T_$(2)_H_$(3))/rusti$(X_$(2)) $(Q)rm -f $$(TBIN$(1)_T_$(2)_H_$(3))/rust$(X_$(2)) $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTPKG_$(2)) $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTDOC_$(2)) @@ -109,14 +105,12 @@ clean$(1)_T_$(2)_H_$(3): $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_EXTRALIB_$(2)) $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTC_$(2)) $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBSYNTAX_$(2)) - $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTI_$(2)) $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(STDLIB_GLOB_$(2)) $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(EXTRALIB_GLOB_$(2)) $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(LIBRUSTC_GLOB_$(2)) $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(LIBSYNTAX_GLOB_$(2)) $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(LIBRUSTPKG_GLOB_$(2)) $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(LIBRUSTDOC_GLOB_$(2)) - $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(LIBRUSTI_GLOB_$(2)) $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_RUSTLLVM_$(2)) $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/libstd.rlib $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/libmorestack.a diff --git a/mk/dist.mk b/mk/dist.mk index ccb20a164d9..13b9509e667 100644 --- a/mk/dist.mk +++ b/mk/dist.mk @@ -29,7 +29,6 @@ PKG_FILES := \ README.txt \ driver \ librustpkg \ - librusti \ librustc \ compiletest \ etc \ diff --git a/mk/install.mk b/mk/install.mk index 90cdb3939fc..94260056386 100644 --- a/mk/install.mk +++ b/mk/install.mk @@ -104,7 +104,6 @@ install-target-$(1)-host-$(2): $$(CSREQ$$(ISTAGE)_T_$(1)_H_$(2)) $$(Q)$$(call INSTALL_LIB,$$(LIBSYNTAX_GLOB_$(1))) $$(Q)$$(call INSTALL_LIB,$$(LIBRUSTPKG_GLOB_$(1))) $$(Q)$$(call INSTALL_LIB,$$(LIBRUSTDOC_GLOB_$(1))) - $$(Q)$$(call INSTALL_LIB,$$(LIBRUSTI_GLOB_$(1))) $$(Q)$$(call INSTALL_LIB,libmorestack.a) endef @@ -138,19 +137,16 @@ install-host: $(CSREQ$(ISTAGE)_T_$(CFG_BUILD_TRIPLE)_H_$(CFG_BUILD_TRIPLE)) $(Q)$(call INSTALL,$(HB2),$(PHB),rustc$(X_$(CFG_BUILD_TRIPLE))) $(Q)$(call INSTALL,$(HB2),$(PHB),rustpkg$(X_$(CFG_BUILD_TRIPLE))) $(Q)$(call INSTALL,$(HB2),$(PHB),rustdoc$(X_$(CFG_BUILD_TRIPLE))) - $(Q)$(call INSTALL,$(HB2),$(PHB),rusti$(X_$(CFG_BUILD_TRIPLE))) $(Q)$(call INSTALL_LIB,$(STDLIB_GLOB_$(CFG_BUILD_TRIPLE))) $(Q)$(call INSTALL_LIB,$(EXTRALIB_GLOB_$(CFG_BUILD_TRIPLE))) $(Q)$(call INSTALL_LIB,$(LIBRUSTC_GLOB_$(CFG_BUILD_TRIPLE))) $(Q)$(call INSTALL_LIB,$(LIBSYNTAX_GLOB_$(CFG_BUILD_TRIPLE))) - $(Q)$(call INSTALL_LIB,$(LIBRUSTI_GLOB_$(CFG_BUILD_TRIPLE))) $(Q)$(call INSTALL_LIB,$(LIBRUSTPKG_GLOB_$(CFG_BUILD_TRIPLE))) $(Q)$(call INSTALL_LIB,$(LIBRUSTDOC_GLOB_$(CFG_BUILD_TRIPLE))) $(Q)$(call INSTALL,$(HL),$(PHL),$(CFG_RUNTIME_$(CFG_BUILD_TRIPLE))) $(Q)$(call INSTALL,$(HL),$(PHL),$(CFG_RUSTLLVM_$(CFG_BUILD_TRIPLE))) $(Q)$(call INSTALL,$(S)/man, $(PREFIX_ROOT)/share/man/man1,rustc.1) $(Q)$(call INSTALL,$(S)/man, $(PREFIX_ROOT)/share/man/man1,rustdoc.1) - $(Q)$(call INSTALL,$(S)/man, $(PREFIX_ROOT)/share/man/man1,rusti.1) $(Q)$(call INSTALL,$(S)/man, $(PREFIX_ROOT)/share/man/man1,rustpkg.1) install-targets: $(INSTALL_TARGET_RULES) @@ -162,7 +158,6 @@ HOST_LIB_FROM_HL_GLOB = \ uninstall: $(Q)rm -f $(PHB)/rustc$(X_$(CFG_BUILD_TRIPLE)) $(Q)rm -f $(PHB)/rustpkg$(X_$(CFG_BUILD_TRIPLE)) - $(Q)rm -f $(PHB)/rusti$(X_$(CFG_BUILD_TRIPLE)) $(Q)rm -f $(PHB)/rustdoc$(X_$(CFG_BUILD_TRIPLE)) $(Q)rm -f $(PHL)/$(CFG_RUSTLLVM_$(CFG_BUILD_TRIPLE)) $(Q)rm -f $(PHL)/$(CFG_RUNTIME_$(CFG_BUILD_TRIPLE)) @@ -173,14 +168,12 @@ uninstall: $(call HOST_LIB_FROM_HL_GLOB,$(LIBSYNTAX_GLOB_$(CFG_BUILD_TRIPLE))) \ $(call HOST_LIB_FROM_HL_GLOB,$(LIBRUSTPKG_GLOB_$(CFG_BUILD_TRIPLE))) \ $(call HOST_LIB_FROM_HL_GLOB,$(LIBRUSTDOC_GLOB_$(CFG_BUILD_TRIPLE))) \ - $(call HOST_LIB_FROM_HL_GLOB,$(LIBRUSTI_GLOB_$(CFG_BUILD_TRIPLE))) \ ; \ do rm -f $$i ; \ done $(Q)rm -Rf $(PHL)/rustc $(Q)rm -f $(PREFIX_ROOT)/share/man/man1/rustc.1 $(Q)rm -f $(PREFIX_ROOT)/share/man/man1/rustdoc.1 - $(Q)rm -f $(PREFIX_ROOT)/share/man/man1/rusti.1 $(Q)rm -f $(PREFIX_ROOT)/share/man/man1/rustpkg.1 # target platform specific variables diff --git a/mk/tests.mk b/mk/tests.mk index c4e3dbbf603..fb5bd094404 100644 --- a/mk/tests.mk +++ b/mk/tests.mk @@ -15,7 +15,7 @@ # The names of crates that must be tested TEST_TARGET_CRATES = std extra -TEST_HOST_CRATES = rusti rustpkg rustc rustdoc syntax +TEST_HOST_CRATES = rustpkg rustc rustdoc syntax TEST_CRATES = $(TEST_TARGET_CRATES) $(TEST_HOST_CRATES) # Markdown files under doc/ that should have their code extracted and run @@ -189,7 +189,7 @@ check-test: cleantestlibs cleantmptestlogs all check-stage2-rfail check-lite: cleantestlibs cleantmptestlogs \ check-stage2-std check-stage2-extra check-stage2-rpass \ - check-stage2-rustpkg check-stage2-rusti \ + check-stage2-rustpkg \ check-stage2-rfail check-stage2-cfail $(Q)$(CFG_PYTHON) $(S)src/etc/check-summary.py tmp/*.log @@ -379,14 +379,6 @@ $(3)/stage$(1)/test/rustpkgtest-$(2)$$(X_$(2)): \ @$$(call E, compile_and_link: $$@) $$(STAGE$(1)_T_$(2)_H_$(3)) -o $$@ $$< --test -$(3)/stage$(1)/test/rustitest-$(2)$$(X_$(2)): \ - $$(RUSTI_LIB) $$(RUSTI_INPUTS) \ - $$(SREQ$(1)_T_$(2)_H_$(3)) \ - $$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_LIBSYNTAX_$(2)) \ - $$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_LIBRUSTC_$(2)) - @$$(call E, compile_and_link: $$@) - $$(STAGE$(1)_T_$(2)_H_$(3)) -o $$@ $$< --test - $(3)/stage$(1)/test/rustdoctest-$(2)$$(X_$(2)): \ $$(RUSTDOC_LIB) $$(RUSTDOC_INPUTS) \ $$(SREQ$(1)_T_$(2)_H_$(3)) \ diff --git a/mk/tools.mk b/mk/tools.mk index fa85e9e725a..a9ea12b5b24 100644 --- a/mk/tools.mk +++ b/mk/tools.mk @@ -24,10 +24,6 @@ RUSTDOC_LIB := $(S)src/librustdoc/rustdoc.rs RUSTDOC_INPUTS := $(wildcard $(addprefix $(S)src/librustdoc/, \ *.rs */*.rs */*/*.rs)) -# Rusti, the JIT REPL -RUSTI_LIB := $(S)src/librusti/rusti.rs -RUSTI_INPUTS := $(wildcard $(S)src/librusti/*.rs) - # FIXME: These are only built for the host arch. Eventually we'll # have tools that need to built for other targets. define TOOLS_STAGE_N_TARGET @@ -75,24 +71,6 @@ $$(TBIN$(1)_T_$(4)_H_$(3))/rustdoc$$(X_$(4)): \ @$$(call E, compile_and_link: $$@) $$(STAGE$(1)_T_$(4)_H_$(3)) --cfg rustdoc -o $$@ $$< -$$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_LIBRUSTI_$(4)): \ - $$(RUSTI_LIB) $$(RUSTI_INPUTS) \ - $$(SREQ$(1)_T_$(4)_H_$(3)) \ - $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_LIBRUSTC_$(4)) \ - | $$(TLIB$(1)_T_$(4)_H_$(3))/ - @$$(call E, compile_and_link: $$@) - $$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUSTI_GLOB_$(4)),$$(notdir $$@)) - $$(STAGE$(1)_T_$(4)_H_$(3)) $$(WFLAGS_ST$(1)) --out-dir $$(@D) $$< && touch $$@ - $$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUSTI_GLOB_$(4)),$$(notdir $$@)) - -$$(TBIN$(1)_T_$(4)_H_$(3))/rusti$$(X_$(4)): \ - $$(DRIVER_CRATE) \ - $$(TSREQ$(1)_T_$(4)_H_$(3)) \ - $$(TLIB$(1)_T_$(4)_H_$(4))/$(CFG_LIBRUSTI_$(4)) \ - | $$(TBIN$(1)_T_$(4)_H_$(3))/ - @$$(call E, compile_and_link: $$@) - $$(STAGE$(1)_T_$(4)_H_$(3)) --cfg rusti -o $$@ $$< - endef define TOOLS_STAGE_N_HOST @@ -147,27 +125,6 @@ $$(HBIN$(2)_H_$(4))/rustdoc$$(X_$(4)): \ @$$(call E, cp: $$@) $$(Q)cp $$< $$@ -$$(HLIB$(2)_H_$(4))/$(CFG_LIBRUSTI_$(4)): \ - $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_LIBRUSTI_$(4)) \ - $$(HLIB$(2)_H_$(4))/$(CFG_LIBRUSTC_$(4)) \ - $$(HSREQ$(2)_H_$(4)) \ - | $$(HLIB$(2)_H_$(4))/ - @$$(call E, cp: $$@) - $$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUSTI_GLOB_$(4)),$$(notdir $$@)) - $$(Q)cp $$< $$@ - $$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUSTI_GLOB_$(4)),$$(notdir $$@)) - $$(Q)cp -R $$(TLIB$(1)_T_$(4)_H_$(3))/$(LIBRUSTI_GLOB_$(4)) \ - $$(wildcard $$(TLIB$(1)_T_$(4)_H_$(3))/$(LIBRUSTI_DSYM_GLOB_$(4))) \ - $$(HLIB$(2)_H_$(4)) - -$$(HBIN$(2)_H_$(4))/rusti$$(X_$(4)): \ - $$(TBIN$(1)_T_$(4)_H_$(3))/rusti$$(X_$(4)) \ - $$(HLIB$(2)_H_$(4))/$(CFG_LIBRUSTI_$(4)) \ - $$(HSREQ$(2)_H_$(4)) \ - | $$(HBIN$(2)_H_$(4))/ - @$$(call E, cp: $$@) - $$(Q)cp $$< $$@ - endef $(foreach host,$(CFG_HOST_TRIPLES), \ diff --git a/src/README.txt b/src/README.txt index f229068731f..7cf523e1017 100644 --- a/src/README.txt +++ b/src/README.txt @@ -31,8 +31,6 @@ compiletest/ The test runner librustpkg/ The package manager and build system -librusti/ The JIT REPL - librustdoc/ The Rust API documentation tool llvm/ The LLVM submodule diff --git a/src/librusti/program.rs b/src/librusti/program.rs deleted file mode 100644 index 4ab9ac4aef5..00000000000 --- a/src/librusti/program.rs +++ /dev/null @@ -1,416 +0,0 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::cast; -use std::util; -use std::hashmap::HashMap; -use std::local_data; - -use syntax::ast; -use syntax::parse::token; -use syntax::print::pprust; -use rustc::middle::ty; -use rustc::util::ppaux; - -use utils::*; - -/// This structure keeps track of the state of the world for the code being -/// executed in rusti. -#[deriving(Clone)] -pub struct Program { - /// All known local variables - local_vars: HashMap<~str, LocalVariable>, - /// New variables which will be present (learned from typechecking) - newvars: HashMap<~str, LocalVariable>, - /// All known view items (use statements), distinct because these must - /// follow extern mods - view_items: ~str, - /// All known 'extern mod' statements (must always come first) - externs: ~str, - /// All known structs defined. These need to have - /// #[deriving(Encodable,Decodable)] to be at all useful in rusti - structs: HashMap<~str, ~str>, - /// All other items, can all be intermingled. Duplicate definitions of the - /// same name have the previous one overwritten. - items: HashMap<~str, ~str>, -} - -/// Represents a local variable that the program is currently using. -#[deriving(Clone)] -struct LocalVariable { - /// Should this variable be locally declared as mutable? - mutable: bool, - /// This is the type of the serialized data below - ty: ~str, - /// This is the serialized version of the variable - data: ~[u8], - /// When taking borrowed pointers or slices, care must be taken to ensure - /// that the deserialization produces what we'd expect. If some magic is in - /// order, the first element of this pair is the actual type of the local - /// variable (which can be different from the deserialized type), and the - /// second element are the '&'s which need to be prepended. - alterations: Option<(~str, ~str)>, -} - -type LocalCache = @mut HashMap<~str, @~[u8]>; -local_data_key!(tls_key: LocalCache) - -impl Program { - pub fn new() -> Program { - Program { - local_vars: HashMap::new(), - newvars: HashMap::new(), - view_items: ~"", - externs: ~"", - structs: HashMap::new(), - items: HashMap::new(), - } - } - - /// Clears all local bindings about variables, items, externs, etc. - pub fn clear(&mut self) { - *self = Program::new(); - } - - /// Creates a block of code to be fed to rustc. This code is not meant to - /// run, but rather it is meant to learn about the input given. This will - /// assert that the types of all bound local variables are encodable, - /// along with checking syntax and other rust-related things. The reason - /// that we only check for encodability is that some super-common types - /// (like &'static str) are not decodable, but are encodable. By doing some - /// mild approximation when decoding, we can emulate at least &str and &[T]. - /// - /// Once this code has been fed to rustc, it is intended that the code() - /// function is used to actually generate code to fully compile and run. - pub fn test_code(&self, user_input: &str, to_print: &Option<~str>, - new_locals: &[(~str, bool)]) -> ~str { - let mut code = self.program_header(); - code.push_str(" - fn assert_encodable>(t: &T) {} - "); - - code.push_str("fn main() {\n"); - // It's easy to initialize things if we don't run things... - for (name, var) in self.local_vars.iter() { - let mt = var.mt(); - code.push_str(format!("let{} {}: {} = fail!();\n", mt, *name, var.ty)); - var.alter(*name, &mut code); - } - code.push_str("{\n"); - code.push_str(user_input); - code.push_char('\n'); - match *to_print { - Some(ref s) => { - code.push_str(*s); - code.push_str(";\n"); - } - None => {} - } - - for p in new_locals.iter() { - code.push_str(format!("assert_encodable(&{});\n", *p.first_ref())); - } - code.push_str("};}"); - return code; - } - - /// Creates a program to be fed into rustc. This program is structured to - /// deserialize all bindings into local variables, run the code input, and - /// then reserialize all the variables back out. - /// - /// This program (unlike test_code) is meant to run to actually execute the - /// user's input - pub fn code(&mut self, user_input: &str, to_print: &Option<~str>) -> ~str { - let mut code = self.program_header(); - code.push_str(" - fn main() { - "); - - let key: uint= unsafe { cast::transmute(tls_key) }; - // First, get a handle to the tls map which stores all the local - // variables. This works by totally legitimately using the 'code' - // pointer of the 'tls_key' function as a uint, and then casting it back - // up to a function - code.push_str(format!(" - let __tls_map: @mut ::std::hashmap::HashMap<~str, @~[u8]> = unsafe \\{ - let key = ::std::cast::transmute({}); - ::std::local_data::get(key, |k| k.map(|&x| *x)).unwrap() - \\};\n", key)); - - // Using this __tls_map handle, deserialize each variable binding that - // we know about - for (name, var) in self.local_vars.iter() { - let mt = var.mt(); - code.push_str(format!("let{} {}: {} = \\{ - let data = __tls_map.get_copy(&~\"{}\"); - let doc = ::extra::ebml::reader::Doc(data); - let mut decoder = ::extra::ebml::reader::Decoder(doc); - ::extra::serialize::Decodable::decode(&mut decoder) - \\};\n", mt, *name, var.ty, *name)); - var.alter(*name, &mut code); - } - - // After all that, actually run the user's code. - code.push_str(user_input); - code.push_char('\n'); - - match *to_print { - Some(ref s) => { code.push_str(format!("pp(\\{\n{}\n\\});", *s)); } - None => {} - } - - let newvars = util::replace(&mut self.newvars, HashMap::new()); - for (name, var) in newvars.move_iter() { - self.local_vars.insert(name, var); - } - - // After the input code is run, we can re-serialize everything back out - // into tls map (to be read later on by this task) - for (name, var) in self.local_vars.iter() { - code.push_str(format!("\\{ - let local: {} = {}; - let bytes = do ::std::io::with_bytes_writer |io| \\{ - let mut enc = ::extra::ebml::writer::Encoder(io); - local.encode(&mut enc); - \\}; - __tls_map.insert(~\"{}\", @bytes); - \\}\n", var.real_ty(), *name, *name)); - } - - // Close things up, and we're done. - code.push_str("}"); - return code; - } - - /// Creates the header of the programs which are generated to send to rustc - fn program_header(&self) -> ~str { - // up front, disable lots of annoying lints, then include all global - // state such as items, view items, and extern mods. - let mut code = format!(" - \\#[allow(warnings)]; - - extern mod extra; - {} // extern mods - - use extra::serialize::*; - {} // view items - ", self.externs, self.view_items); - for (_, s) in self.structs.iter() { - // The structs aren't really useful unless they're encodable - code.push_str("#[deriving(Encodable, Decodable)]"); - code.push_str(*s); - code.push_str("\n"); - } - for (_, s) in self.items.iter() { - code.push_str(*s); - code.push_str("\n"); - } - code.push_str("fn pp(t: T) { println(fmt!(\"%?\", t)); }\n"); - return code; - } - - /// Initializes the task-local cache of all local variables known to the - /// program. This will be used to read local variables out of once the - /// program starts - pub fn set_cache(&self) { - let map = @mut HashMap::new(); - for (name, value) in self.local_vars.iter() { - map.insert((*name).clone(), @(value.data).clone()); - } - local_data::set(tls_key, map); - } - - /// Once the program has finished running, this function will consume the - /// task-local cache of local variables. After the program finishes running, - /// it updates this cache with the new values of each local variable. - pub fn consume_cache(&mut self) { - let map = local_data::pop(tls_key).expect("tls is empty"); - let cons_map = util::replace(map, HashMap::new()); - for (name, value) in cons_map.move_iter() { - match self.local_vars.find_mut(&name) { - Some(v) => { v.data = (*value).clone(); } - None => { fail2!("unknown variable {}", name) } - } - } - } - - // Simple functions to record various global things (as strings) - - pub fn record_view_item(&mut self, vi: &str) { - self.view_items.push_str(vi); - self.view_items.push_char('\n'); - } - - pub fn record_struct(&mut self, name: &str, s: ~str) { - let name = name.to_owned(); - self.items.remove(&name); - self.structs.insert(name, s); - } - - pub fn record_item(&mut self, name: &str, it: ~str) { - let name = name.to_owned(); - self.structs.remove(&name); - self.items.insert(name, it); - } - - pub fn record_extern(&mut self, name: &str) { - self.externs.push_str(name); - self.externs.push_char('\n'); - } - - /// This monster function is responsible for reading the main function - /// generated by test_code() to determine the type of each local binding - /// created by the user's input. - /// - /// Once the types are known, they are inserted into the local_vars map in - /// this Program (to be deserialized later on - pub fn register_new_vars(&mut self, blk: &ast::Block, tcx: ty::ctxt) { - debug2!("looking for new variables"); - let newvars = @mut HashMap::new(); - do each_user_local(blk) |local| { - let mutable = local.is_mutbl; - do each_binding(local) |path, id| { - let name = do with_pp(token::get_ident_interner()) |pp, _| { - pprust::print_path(pp, path, false); - }; - let mut t = ty::node_id_to_type(tcx, id); - let mut tystr = ~""; - let mut lvar = LocalVariable { - ty: ~"", - data: ~[], - mutable: mutable, - alterations: None, - }; - // This loop is responsible for figuring out what "alterations" - // are necessary for this local variable. - loop { - match ty::get(t).sty { - // &T encoded will decode to T, so we need to be sure to - // re-take a loan after decoding - ty::ty_rptr(_, mt) => { - if mt.mutbl == ast::MutMutable { - tystr.push_str("&mut "); - } else { - tystr.push_str("&"); - } - t = mt.ty; - } - // Literals like [1, 2, 3] and (~[0]).slice() will both - // be serialized to ~[T], whereas it's requested to be a - // &[T] instead. - ty::ty_evec(mt, ty::vstore_slice(*)) | - ty::ty_evec(mt, ty::vstore_fixed(*)) => { - let vty = ppaux::ty_to_str(tcx, mt.ty); - let derefs = tystr.clone(); - lvar.ty = tystr + "~[" + vty + "]"; - lvar.alterations = Some((tystr + "&[" + vty + "]", - derefs)); - break; - } - // Similar to vectors, &str serializes to ~str, so a - // borrow must be taken - ty::ty_estr(ty::vstore_slice(*)) => { - let derefs = tystr.clone(); - lvar.ty = tystr + "~str"; - lvar.alterations = Some((tystr + "&str", derefs)); - break; - } - // Don't generate extra stuff if there's no borrowing - // going on here - _ if "" == tystr => { - lvar.ty = ppaux::ty_to_str(tcx, t); - break; - } - // If we're just borrowing (no vectors or strings), then - // we just need to record how many borrows there were. - _ => { - let derefs = tystr.clone(); - let tmptystr = ppaux::ty_to_str(tcx, t); - lvar.alterations = Some((tystr + tmptystr, derefs)); - lvar.ty = tmptystr; - break; - } - } - } - newvars.insert(name, lvar); - } - } - - // I'm not an @ pointer, so this has to be done outside. - let cons_newvars = util::replace(newvars, HashMap::new()); - for (k, v) in cons_newvars.move_iter() { - self.newvars.insert(k, v); - } - - // helper functions to perform ast iteration - fn each_user_local(blk: &ast::Block, f: &fn(@ast::Local)) { - do find_user_block(blk) |blk| { - for stmt in blk.stmts.iter() { - match stmt.node { - ast::StmtDecl(d, _) => { - match d.node { - ast::DeclLocal(l) => { f(l); } - _ => {} - } - } - _ => {} - } - } - } - } - - fn find_user_block(blk: &ast::Block, f: &fn(&ast::Block)) { - for stmt in blk.stmts.iter() { - match stmt.node { - ast::StmtSemi(e, _) => { - match e.node { - ast::ExprBlock(ref blk) => { return f(blk); } - _ => {} - } - } - _ => {} - } - } - fail2!("couldn't find user block"); - } - } -} - -impl LocalVariable { - /// Performs alterations to the code provided, given the name of this - /// variable. - fn alter(&self, name: &str, code: &mut ~str) { - match self.alterations { - Some((ref real_ty, ref prefix)) => { - code.push_str(format!("let{} {}: {} = {}{};\n", - self.mt(), name, - *real_ty, *prefix, name)); - } - None => {} - } - } - - fn real_ty<'a>(&'a self) -> &'a str { - match self.alterations { - Some((ref real_ty, _)) => { - let ret: &'a str = *real_ty; - return ret; - } - None => { - let ret: &'a str = self.ty; - return ret; - } - } - } - - fn mt(&self) -> &'static str { - if self.mutable {" mut"} else {""} - } -} diff --git a/src/librusti/rusti.rs b/src/librusti/rusti.rs deleted file mode 100644 index c025d9b10dd..00000000000 --- a/src/librusti/rusti.rs +++ /dev/null @@ -1,786 +0,0 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/*! - * rusti - A REPL using the JIT backend - * - * Rusti works by serializing state between lines of input. This means that each - * line can be run in a separate task, and the only limiting factor is that all - * local bound variables are encodable. - * - * This is accomplished by feeding in generated input to rustc for execution in - * the JIT compiler. Currently input actually gets fed in three times to get - * information about the program. - * - * - Pass #1 - * In this pass, the input is simply thrown at the parser and the input comes - * back. This validates the structure of the program, and at this stage the - * global items (fns, structs, impls, traits, etc.) are filtered from the - * input into the "global namespace". These declarations shadow all previous - * declarations of an item by the same name. - * - * - Pass #2 - * After items have been stripped, the remaining input is passed to rustc - * along with all local variables declared (initialized to nothing). This pass - * runs up to typechecking. From this, we can learn about the types of each - * bound variable, what variables are bound, and also ensure that all the - * types are encodable (the input can actually be run). - * - * - Pass #3 - * Finally, a program is generated to deserialize the local variable state, - * run the code input, and then reserialize all bindings back into a local - * hash map. This code is then run in the JIT engine provided by the rust - * compiler. - * - * - Pass #4 - * Once this code runs, the input has fully been run and the hash map of local - * variables from TLS is read back into the local store of variables. This is - * then used later to pass back along to the parent rusti task and then begin - * waiting for input again. - * - * - Pass #5 - * When running rusti code, it's important to consume ownership of the LLVM - * jit contextual information to prevent code from being deallocated too soon - * (before drop glue runs, see #7732). For this reason, the jit context is - * consumed and also passed along to the parent task. The parent task then - * keeps around all contexts while rusti is running. This must be done because - * tasks could in theory be spawned off and running in the background (still - * using the code). - * - * Encoding/decoding is done with EBML, and there is simply a map of ~str -> - * ~[u8] maintaining the values of each local binding (by name). - */ - -#[link(name = "rusti", - vers = "0.9-pre", - uuid = "7fb5bf52-7d45-4fee-8325-5ad3311149fc", - url = "https://github.com/mozilla/rust/tree/master/src/rusti")]; - -#[license = "MIT/ASL2"]; -#[crate_type = "lib"]; - -#[feature(globs)]; - -extern mod extra; -extern mod rustc; -extern mod syntax; - -use std::{libc, io, os, task}; -use std::cell::Cell; -use extra::rl::CompletionCb; -use extra::rl; - -use rustc::driver::{driver, session}; -use rustc::back::link::jit; -use syntax::{ast, codemap, diagnostic}; -use syntax::ast_util::*; -use syntax::diagnostic::Emitter; -use syntax::parse::token; -use syntax::print::pprust; - -use program::Program; -use utils::*; - -mod program; -pub mod utils; - -/** - * A structure shared across REPL instances for storing history - * such as statements and view items. I wish the AST was sendable. - */ -pub struct Repl { - prompt: ~str, - binary: ~str, - running: bool, - lib_search_paths: ~[~str], - engines: ~[~jit::Engine], - - program: ~Program, -} - -// Action to do after reading a :command -enum CmdAction { - action_none, - action_run_line(~str), -} - -struct EncodableWarningEmitter; - -impl diagnostic::Emitter for EncodableWarningEmitter { - fn emit(&self, - cm: Option<(@codemap::CodeMap, codemap::Span)>, - msg: &str, - lvl: diagnostic::level) { - diagnostic::DefaultEmitter.emit(cm, msg, lvl); - if msg.contains("failed to find an implementation of trait") && - msg.contains("extra::serialize::Encodable") { - diagnostic::DefaultEmitter.emit(cm, - "Currrently rusti serializes \ - bound locals between different \ - lines of input. This means that \ - all values of local variables \ - need to be encodable, and this \ - type isn't encodable", - diagnostic::note); - } - } -} - -/// Run an input string in a Repl, returning the new Repl. -fn run(mut program: ~Program, binary: ~str, lib_search_paths: ~[~str], - input: ~str) -> (~Program, Option<~jit::Engine>) -{ - // Build some necessary rustc boilerplate for compiling things - let binary = binary.to_managed(); - let options = @session::options { - crate_type: session::unknown_crate, - binary: binary, - addl_lib_search_paths: @mut lib_search_paths.map(|p| Path::new(p.as_slice())), - jit: true, - .. (*session::basic_options()).clone() - }; - // Because we assume that everything is encodable (and assert so), add some - // extra helpful information if the error crops up. Otherwise people are - // bound to be very confused when they find out code is running that they - // never typed in... - let sess = driver::build_session(options, - @EncodableWarningEmitter as - @diagnostic::Emitter); - let intr = token::get_ident_interner(); - - // - // Stage 1: parse the input and filter it into the program (as necessary) - // - debug2!("parsing: {}", input); - let crate = parse_input(sess, input); - let mut to_run = ~[]; // statements to run (emitted back into code) - let new_locals = @mut ~[]; // new locals being defined - let mut result = None; // resultant expression (to print via pp) - do find_main(&crate, sess) |blk| { - // Fish out all the view items, be sure to record 'extern mod' items - // differently beause they must appear before all 'use' statements - for vi in blk.view_items.iter() { - let s = do with_pp(intr) |pp, _| { - pprust::print_view_item(pp, vi); - }; - match vi.node { - ast::view_item_extern_mod(*) => { - program.record_extern(s); - } - ast::view_item_use(*) => { program.record_view_item(s); } - } - } - - // Iterate through all of the block's statements, inserting them into - // the correct portions of the program - for stmt in blk.stmts.iter() { - let s = do with_pp(intr) |pp, _| { pprust::print_stmt(pp, *stmt); }; - match stmt.node { - ast::StmtDecl(d, _) => { - match d.node { - ast::DeclItem(it) => { - let name = sess.str_of(it.ident); - match it.node { - // Structs are treated specially because to make - // them at all usable they need to be decorated - // with #[deriving(Encoable, Decodable)] - ast::item_struct(*) => { - program.record_struct(name, s); - } - // Item declarations are hoisted out of main() - _ => { program.record_item(name, s); } - } - } - - // Local declarations must be specially dealt with, - // record all local declarations for use later on - ast::DeclLocal(l) => { - let mutbl = l.is_mutbl; - do each_binding(l) |path, _| { - let s = do with_pp(intr) |pp, _| { - pprust::print_path(pp, path, false); - }; - new_locals.push((s, mutbl)); - } - to_run.push(s); - } - } - } - - // run statements with expressions (they have effects) - ast::StmtMac(*) | ast::StmtSemi(*) | ast::StmtExpr(*) => { - to_run.push(s); - } - } - } - result = do blk.expr.map |e| { - do with_pp(intr) |pp, _| { pprust::print_expr(pp, e); } - }; - } - // return fast for empty inputs - if to_run.len() == 0 && result.is_none() { - return (program, None); - } - - // - // Stage 2: run everything up to typeck to learn the types of the new - // variables introduced into the program - // - info2!("Learning about the new types in the program"); - program.set_cache(); // before register_new_vars (which changes them) - let input = to_run.connect("\n"); - let test = program.test_code(input, &result, *new_locals); - debug2!("testing with ^^^^^^ {:?}", (||{ println(test) })()); - let dinput = driver::str_input(test.to_managed()); - let cfg = driver::build_configuration(sess); - - let crate = driver::phase_1_parse_input(sess, cfg.clone(), &dinput); - let expanded_crate = driver::phase_2_configure_and_expand(sess, cfg, crate); - let analysis = driver::phase_3_run_analysis_passes(sess, &expanded_crate); - - // Once we're typechecked, record the types of all local variables defined - // in this input - do find_main(&expanded_crate, sess) |blk| { - program.register_new_vars(blk, analysis.ty_cx); - } - - // - // Stage 3: Actually run the code in the JIT - // - info2!("actually running code"); - let code = program.code(input, &result); - debug2!("actually running ^^^^^^ {:?}", (||{ println(code) })()); - let input = driver::str_input(code.to_managed()); - let cfg = driver::build_configuration(sess); - let outputs = driver::build_output_filenames(&input, &None, &None, [], sess); - let sess = driver::build_session(options, - @diagnostic::DefaultEmitter as - @diagnostic::Emitter); - - let crate = driver::phase_1_parse_input(sess, cfg.clone(), &input); - let expanded_crate = driver::phase_2_configure_and_expand(sess, cfg, crate); - let analysis = driver::phase_3_run_analysis_passes(sess, &expanded_crate); - let trans = driver::phase_4_translate_to_llvm(sess, expanded_crate, &analysis, outputs); - driver::phase_5_run_llvm_passes(sess, &trans, outputs); - - // - // Stage 4: Inform the program that computation is done so it can update all - // local variable bindings. - // - info2!("cleaning up after code"); - program.consume_cache(); - - // - // Stage 5: Extract the LLVM execution engine to take ownership of the - // generated JIT code. This means that rusti can spawn parallel - // tasks and we won't deallocate the code emitted until rusti - // itself is destroyed. - // - return (program, jit::consume_engine()); - - fn parse_input(sess: session::Session, input: &str) -> ast::Crate { - let code = format!("fn main() \\{\n {} \n\\}", input); - let input = driver::str_input(code.to_managed()); - let cfg = driver::build_configuration(sess); - driver::phase_1_parse_input(sess, cfg.clone(), &input) - } - - fn find_main(crate: &ast::Crate, sess: session::Session, - f: &fn(&ast::Block)) { - for item in crate.module.items.iter() { - match item.node { - ast::item_fn(_, _, _, _, ref blk) => { - if item.ident == sess.ident_of("main") { - return f(blk); - } - } - _ => {} - } - } - fail2!("main function was expected somewhere..."); - } -} - -// Compiles a crate given by the filename as a library if the compiled -// version doesn't exist or is older than the source file. Binary is -// the name of the compiling executable. Returns Some(true) if it -// successfully compiled, Some(false) if the crate wasn't compiled -// because it already exists and is newer than the source file, or -// None if there were compile errors. -fn compile_crate(src_filename: ~str, binary: ~str) -> Option { - fn has_prefix(v: &[u8], pref: &[u8]) -> bool { - v.len() >= pref.len() && v.slice_to(pref.len()) == pref - } - fn has_extension(v: &[u8], ext: Option<&[u8]>) -> bool { - match ext { - None => true, - Some(ext) => { - v.len() > ext.len() && v[v.len()-ext.len()-1] == '.' as u8 && - v.slice_from(v.len()-ext.len()) == ext - } - } - } - match do task::try { - let src_path = Path::new(src_filename.as_slice()); - let binary = binary.to_managed(); - let options = @session::options { - binary: binary, - addl_lib_search_paths: @mut ~[os::getcwd()], - .. (*session::basic_options()).clone() - }; - let input = driver::file_input(src_path.clone()); - let sess = driver::build_session(options, - @diagnostic::DefaultEmitter as - @diagnostic::Emitter); - *sess.building_library = true; - let cfg = driver::build_configuration(sess); - let outputs = driver::build_output_filenames( - &input, &None, &None, [], sess); - // If the library already exists and is newer than the source - // file, skip compilation and return None. - let mut should_compile = true; - let dir = os::list_dir_path(&outputs.out_filename.dir_path()); - let maybe_lib_path = do dir.iter().find |file| { - // The actual file's name has a hash value and version - // number in it which is unknown at this time, so looking - // for a file that matches out_filename won't work, - // instead we guess which file is the library by matching - // the prefix and suffix of out_filename to files in the - // directory. - let file_vec = file.filename().unwrap(); - has_prefix(file_vec, outputs.out_filename.filestem().unwrap()) && - has_extension(file_vec, outputs.out_filename.extension()) - }; - match maybe_lib_path { - Some(lib_path) => { - let (src_mtime, _) = src_path.get_mtime().unwrap(); - let (lib_mtime, _) = lib_path.get_mtime().unwrap(); - if lib_mtime >= src_mtime { - should_compile = false; - } - }, - None => { }, - } - if (should_compile) { - println(format!("compiling {}...", src_filename)); - let crate = driver::phase_1_parse_input(sess, cfg.clone(), &input); - let expanded_crate = driver::phase_2_configure_and_expand(sess, cfg, crate); - let analysis = driver::phase_3_run_analysis_passes(sess, &expanded_crate); - let trans = driver::phase_4_translate_to_llvm(sess, expanded_crate, &analysis, outputs); - driver::phase_5_run_llvm_passes(sess, &trans, outputs); - true - } else { false } - } { - Ok(true) => Some(true), - Ok(false) => Some(false), - Err(_) => None, - } -} - -/// Tries to get a line from rl after outputting a prompt. Returns -/// None if no input was read (e.g. EOF was reached). -fn get_line(use_rl: bool, prompt: &str) -> Option<~str> { - if use_rl { - let result = rl::read(prompt); - - match result { - None => None, - Some(line) => { - rl::add_history(line); - Some(line) - } - } - } else { - if io::stdin().eof() { - None - } else { - Some(io::stdin().read_line()) - } - } -} - -/// Run a command, e.g. :clear, :exit, etc. -fn run_cmd(repl: &mut Repl, _in: @io::Reader, _out: @io::Writer, - cmd: ~str, args: ~[~str], use_rl: bool) -> CmdAction { - let mut action = action_none; - match cmd { - ~"exit" => repl.running = false, - ~"clear" => { - repl.program.clear(); - - // XXX: Win32 version of linenoise can't do this - //rl::clear(); - } - ~"help" => { - println( - ":{\\n ..lines.. \\n:}\\n - execute multiline command\n\ - :load ... - loads given crates as dynamic libraries\n\ - :clear - clear the bindings\n\ - :exit - exit from the repl\n\ - :help - show this message"); - } - ~"load" => { - let mut loaded_crates: ~[~str] = ~[]; - for arg in args.iter() { - let (crate, filename) = - if arg.ends_with(".rs") || arg.ends_with(".rc") { - (arg.slice_to(arg.len() - 3).to_owned(), (*arg).clone()) - } else { - ((*arg).clone(), *arg + ".rs") - }; - match compile_crate(filename, repl.binary.clone()) { - Some(_) => loaded_crates.push(crate), - None => { } - } - } - for crate in loaded_crates.iter() { - let crate_path = Path::new(crate.as_slice()); - // FIXME (#9639): This needs to handle non-utf8 paths - let crate_dir = crate_path.dirname_str().unwrap(); - repl.program.record_extern(format!("extern mod {};", *crate)); - if !repl.lib_search_paths.iter().any(|x| crate_dir == *x) { - repl.lib_search_paths.push(crate_dir.to_owned()); - } - } - if loaded_crates.is_empty() { - println("no crates loaded"); - } else { - println!("crates loaded: {}", loaded_crates.connect(", ")); - } - } - ~"{" => { - let mut multiline_cmd = ~""; - let mut end_multiline = false; - while (!end_multiline) { - match get_line(use_rl, "rusti| ") { - None => fail2!("unterminated multiline command :\\{ .. :\\}"), - Some(line) => { - if line.trim() == ":}" { - end_multiline = true; - } else { - multiline_cmd.push_str(line); - multiline_cmd.push_char('\n'); - } - } - } - } - action = action_run_line(multiline_cmd); - } - _ => println(~"unknown cmd: " + cmd) - } - return action; -} - -/// Executes a line of input, which may either be rust code or a -/// :command. Returns a new Repl if it has changed. -pub fn run_line(repl: &mut Repl, input: @io::Reader, out: @io::Writer, line: ~str, - use_rl: bool) -> bool -{ - if line.starts_with(":") { - // drop the : and the \n (one byte each) - let full = line.slice(1, line.len()); - let split: ~[~str] = full.word_iter().map(|s| s.to_owned()).collect(); - let len = split.len(); - - if len > 0 { - let cmd = split[0].clone(); - - if !cmd.is_empty() { - let args = if len > 1 { - split.slice(1, len).to_owned() - } else { ~[] }; - - match run_cmd(repl, input, out, cmd, args, use_rl) { - action_none => { } - action_run_line(multiline_cmd) => { - if !multiline_cmd.is_empty() { - return run_line(repl, input, out, multiline_cmd, use_rl); - } - } - } - return true; - } - } - } - - let line = Cell::new(line); - let program = Cell::new(repl.program.clone()); - let lib_search_paths = Cell::new(repl.lib_search_paths.clone()); - let binary = Cell::new(repl.binary.clone()); - let result = do task::try { - run(program.take(), binary.take(), lib_search_paths.take(), line.take()) - }; - - match result { - Ok((program, engine)) => { - repl.program = program; - match engine { - Some(e) => { repl.engines.push(e); } - None => {} - } - return true; - } - Err(*) => { return false; } - } -} - -pub fn main() { - os::set_exit_status(main_args(os::args())); -} - -struct Completer; - -impl CompletionCb for Completer { - fn complete(&self, line: ~str, suggest: &fn(~str)) { - if line.starts_with(":") { - suggest(~":clear"); - suggest(~":exit"); - suggest(~":help"); - suggest(~":load"); - } - } -} - -pub fn main_args(args: &[~str]) -> int { - #[fixed_stack_segment]; #[inline(never)]; - - let input = io::stdin(); - let out = io::stdout(); - let mut repl = Repl { - prompt: ~"rusti> ", - binary: args[0].clone(), - running: true, - lib_search_paths: ~[], - engines: ~[], - - program: ~Program::new(), - }; - - let istty = unsafe { libc::isatty(libc::STDIN_FILENO as i32) } != 0; - - // only print this stuff if the user is actually typing into rusti - if istty { - println("WARNING: The Rust REPL is experimental and may be"); - println("unstable. If you encounter problems, please use the"); - println("compiler instead. Type :help for help."); - - unsafe { - rl::complete(@Completer as @CompletionCb) - } - } - - while repl.running { - match get_line(istty, repl.prompt) { - None => break, - Some(line) => { - if line.is_empty() { - if istty { - println("()"); - } - continue; - } - run_line(&mut repl, input, out, line, istty); - } - } - } - - return 0; -} - -#[cfg(test)] -mod tests { - use std::io; - use program::Program; - use super::*; - - fn repl() -> Repl { - Repl { - prompt: ~"rusti> ", - binary: ~"rusti", - running: true, - lib_search_paths: ~[], - engines: ~[], - program: ~Program::new(), - } - } - - // FIXME: #7220 rusti on 32bit mac doesn't work. - // FIXME: #7641 rusti on 32bit linux cross compile doesn't work - // FIXME: #7115 re-enable once LLVM has been upgraded - #[cfg(thiswillneverbeacfgflag)] - fn run_program(prog: &str) { - let mut r = repl(); - for cmd in prog.split_iter('\n') { - assert!(run_line(&mut r, io::stdin(), io::stdout(), - cmd.to_owned(), false), - "the command '%s' failed", cmd); - } - } - fn run_program(_: &str) {} - - #[ignore] - #[test] - fn super_basic() { - run_program(""); - } - - #[ignore] - #[test] - fn regression_5937() { - run_program("use std::hashmap;"); - } - - #[ignore] - #[test] - fn regression_5784() { - run_program("let a = 3;"); - } - - #[test] #[ignore] - fn new_tasks() { - // XXX: can't spawn new tasks because the JIT code is cleaned up - // after the main function is done. - run_program(" - spawn( || println(\"Please don't segfault\") ); - do spawn { println(\"Please?\"); } - "); - } - - #[ignore] - #[test] - fn inferred_integers_usable() { - run_program("let a = 2;\n()\n"); - run_program(" - let a = 3; - let b = 4u; - assert!((a as uint) + b == 7) - "); - } - - #[ignore] - #[test] - fn local_variables_allow_shadowing() { - run_program(" - let a = 3; - let a = 5; - assert!(a == 5) - "); - } - - #[ignore] - #[test] - fn string_usable() { - run_program(" - let a = ~\"\"; - let b = \"\"; - let c = @\"\"; - let d = a + b + c; - assert!(d.len() == 0); - "); - } - - #[ignore] - #[test] - fn vectors_usable() { - run_program(" - let a = ~[1, 2, 3]; - let b = &[1, 2, 3]; - let c = @[1, 2, 3]; - let d = a + b + c; - assert!(d.len() == 9); - let e: &[int] = []; - "); - } - - #[ignore] - #[test] - fn structs_usable() { - run_program(" - struct A{ a: int } - let b = A{ a: 3 }; - assert!(b.a == 3) - "); - } - - #[ignore] - #[test] - fn mutable_variables_work() { - run_program(" - let mut a = 3; - a = 5; - let mut b = std::hashmap::HashSet::new::(); - b.insert(a); - assert!(b.contains(&5)) - assert!(b.len() == 1) - "); - } - - #[ignore] - #[test] - fn functions_saved() { - run_program(" - fn fib(x: int) -> int { if x < 2 {x} else { fib(x - 1) + fib(x - 2) } } - let a = fib(3); - let a = a + fib(4); - assert!(a == 5) - "); - } - - #[ignore] - #[test] - fn modules_saved() { - run_program(" - mod b { pub fn foo() -> uint { 3 } } - assert!(b::foo() == 3) - "); - } - - #[ignore] - #[test] - fn multiple_functions() { - run_program(" - fn f() {} - fn f() {} - f() - "); - } - - #[ignore] - #[test] - fn multiple_items_same_name() { - run_program(" - fn f() {} - mod f {} - struct f; - enum f {} - fn f() {} - f() - "); - } - - #[ignore] - #[test] - fn simultaneous_definition_and_expression() { - run_program(" - let a = 3; a as u8 - "); - } - - #[ignore] - #[test] - fn exit_quits() { - let mut r = repl(); - assert!(r.running); - let result = run_line(&mut r, io::stdin(), io::stdout(), - ~":exit", false); - assert!(result); - assert!(!r.running); - } -} diff --git a/src/librusti/utils.rs b/src/librusti/utils.rs deleted file mode 100644 index 904594fdfb8..00000000000 --- a/src/librusti/utils.rs +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::io; -use syntax::ast; -use syntax::print::pp; -use syntax::print::pprust; -use syntax::parse::token; -use syntax::visit; - -struct EachBindingVisitor<'self> { - f: &'self fn(&ast::Path, ast::NodeId) -} - -impl<'self> visit::Visitor<()> for EachBindingVisitor<'self> { - fn visit_pat(&mut self, pat:@ast::Pat, _:()) { - match pat.node { - ast::PatIdent(_, ref path, _) => { - (self.f)(path, pat.id); - } - _ => {} - } - - visit::walk_pat(self, pat, ()); - } -} - -pub fn each_binding(l: @ast::Local, f: &fn(&ast::Path, ast::NodeId)) { - use syntax::visit::Visitor; - - let mut vt = EachBindingVisitor{ f: f }; - - vt.visit_pat(l.pat, ()); -} - -/// A utility function that hands off a pretty printer to a callback. -pub fn with_pp(intr: @token::ident_interner, - cb: &fn(@pprust::ps, @io::Writer)) -> ~str { - do io::with_str_writer |writer| { - let pp = pprust::rust_printer(writer, intr); - - cb(pp, writer); - pp::eof(pp.s); - } -}