[submodule "src/libuv"]
path = src/libuv
url = git://github.com/graydon/libuv.git
+[submodule "src/linenoise"]
+ path = src/linenoise
+ url = git://github.com/antirez/linenoise.git
Brendan Eich <brendan@mozilla.org>
Brian Anderson <banderson@mozilla.com>
Brian J. Burg <burg@cs.washington.edu>
+Brian Leibig <brian.leibig@gmail.com>
Chris Double <chris.double@double.co.nz>
Chris Peterson <cpeterson@mozilla.com>
Damian Gryski <damian@gryski.com>
CFG_RUSTC_FLAGS := $(RUSTFLAGS)
CFG_GCCISH_CFLAGS :=
+CFG_GCCISH_CXXFLAGS :=
CFG_GCCISH_LINK_FLAGS :=
ifdef CFG_DISABLE_OPTIMIZE
$(SREQ3_T_$(target)_H_$(CFG_HOST_TRIPLE)))
FUZZ := $(HBIN2_H_$(CFG_HOST_TRIPLE))/fuzzer$(X)
CARGO := $(HBIN2_H_$(CFG_HOST_TRIPLE))/cargo$(X)
+RUSTI := $(HBIN2_H_$(CFG_HOST_TRIPLE))/rusti$(X)
RUSTDOC := $(HBIN2_H_$(CFG_HOST_TRIPLE))/rustdoc$(X)
-all: rustc $(GENERATED) docs $(FUZZ) $(CARGO) $(RUSTDOC)
+all: rustc $(GENERATED) docs $(FUZZ) $(CARGO) $(RUSTDOC) $(RUSTI)
endif
make_dir rustllvm/$t
done
+make_dir linenoise
+for t in $CFG_TARGET_TRIPLES
+do
+ make_dir linenoise/$t
+done
+
make_dir rt
for t in $CFG_TARGET_TRIPLES
do
clean-misc:
@$(call E, cleaning)
- $(Q)find rustllvm rt $(CFG_HOST_TRIPLE)/test \
+ $(Q)find linenoise rustllvm rt $(CFG_HOST_TRIPLE)/test \
-name '*.[odasS]' -o \
-name '*.so' -o \
-name '*.dylib' -o \
-name '*.def' -o \
-name '*.bc' \
| xargs rm -f
- $(Q)find rustllvm rt $(CFG_HOST_TRIPLE)\
+ $(Q)find linenoise rustllvm rt $(CFG_HOST_TRIPLE)\
-name '*.dSYM' \
| xargs rm -Rf
$(Q)rm -f $(RUNTIME_OBJS) $(RUNTIME_DEF)
$(Q)rm -f $(RUSTLLVM_LIB_OBJS) $(RUSTLLVM_OBJS_OBJS) $(RUSTLLVM_DEF)
+ $(Q)rm -f $(LINENOISE_OBJS)
$(Q)rm -Rf $(DOCS)
$(Q)rm -Rf $(GENERATED)
$(Q)rm -f tmp/*.log tmp/*.rc tmp/*.rs
$(Q)rm -f $$(HBIN$(1)_H_$(2))/rustc$(X)
$(Q)rm -f $$(HBIN$(1)_H_$(2))/fuzzer$(X)
$(Q)rm -f $$(HBIN$(1)_H_$(2))/cargo$(X)
+ $(Q)rm -f $$(HBIN$(1)_H_$(2))/rusti$(X)
$(Q)rm -f $$(HBIN$(1)_H_$(2))/serializer$(X)
$(Q)rm -f $$(HBIN$(1)_H_$(2))/rustdoc$(X)
$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_RUNTIME)
$(Q)rm -f $$(TBIN$(1)_T_$(2)_H_$(3))/rustc$(X)
$(Q)rm -f $$(TBIN$(1)_T_$(2)_H_$(3))/fuzzer$(X)
$(Q)rm -f $$(TBIN$(1)_T_$(2)_H_$(3))/cargo$(X)
+ $(Q)rm -f $$(TBIN$(1)_T_$(2)_H_$(3))/rusti$(X)
$(Q)rm -f $$(TBIN$(1)_T_$(2)_H_$(3))/serializer$(X)
$(Q)rm -f $$(TBIN$(1)_T_$(2)_H_$(3))/rustdoc$(X)
$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_RUNTIME)
$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_RUSTLLVM)
$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/libstd.rlib
$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/libmorestack.a
+ $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/liblinenoise.a
endef
$(foreach host, $(CFG_TARGET_TRIPLES), \
$(addprefix $(S)src/, \
README.txt \
cargo \
+ rusti \
rustc \
compiletest \
etc \
libcore \
libsyntax \
libstd \
+ linenoise \
rt \
rustdoc \
rustllvm \
$(Q)mkdir -p $(PREFIX_ROOT)/share/man/man1
$(Q)$(call INSTALL,$(HB2),$(PHB),rustc$(X))
$(Q)$(call INSTALL,$(HB2),$(PHB),cargo$(X))
+ $(Q)$(call INSTALL,$(HB2),$(PHB),rusti$(X))
$(Q)$(call INSTALL,$(HB2),$(PHB),rustdoc$(X))
$(Q)$(call INSTALL,$(HL),$(PHL),$(CFG_RUNTIME))
$(Q)$(call INSTALL_LIB,$(HL),$(PHL),$(CORELIB_GLOB))
uninstall:
$(Q)rm -f $(PHB)/rustc$(X)
$(Q)rm -f $(PHB)/cargo$(X)
+ $(Q)rm -f $(PHB)/rusti$(X)
$(Q)rm -f $(PHB)/rustdoc$(X)
$(Q)rm -f $(PHL)/$(CFG_RUSTLLVM)
$(Q)rm -f $(PHL)/$(CFG_RUNTIME)
ifeq ($(origin CPP),default)
CPP=clang -E
endif
- CFG_GCCISH_CFLAGS += -Wall -Werror -fno-rtti -g
+ CFG_GCCISH_CFLAGS += -Wall -Werror -g
+ CFG_GCCISH_CXXFLAGS += -fno-rtti
CFG_GCCISH_LINK_FLAGS += -g
# These flags will cause the compiler to produce a .d file
# next to the .o file that lists header deps.
CFG_DEPEND_FLAGS = -MMD -MP -MT $(1) -MF $(1:%.o=%.d)
define CFG_MAKE_CC
- CFG_COMPILE_C_$(1) = $$(CFG_GCCISH_CROSS)$$(CXX) \
+ CFG_COMPILE_C_$(1) = $$(CFG_GCCISH_CROSS)$$(CC) \
+ $$(CFG_GCCISH_CFLAGS) $$(CFG_CLANG_CFLAGS) \
+ $$(CFG_GCCISH_CFLAGS_$$(HOST_$(1))) \
+ $$(CFG_CLANG_CFLAGS_$$(HOST_$(1))) \
+ $$(CFG_DEPEND_FLAGS) \
+ -c -o $$(1) $$(2)
+ CFG_LINK_C_$(1) = $$(CFG_GCCISH_CROSS)$$(CC) \
+ $$(CFG_GCCISH_LINK_FLAGS) -o $$(1) \
+ $$(CFG_GCCISH_LINK_FLAGS_$$(HOST_$(1))) \
+ $$(CFG_GCCISH_DEF_FLAG)$$(3) $$(2) \
+ $$(call CFG_INSTALL_NAME,$$(4))
+ CFG_COMPILE_CXX_$(1) = $$(CFG_GCCISH_CROSS)$$(CXX) \
$$(CFG_GCCISH_CFLAGS) $$(CFG_CLANG_CFLAGS) \
+ $$(CFG_GCCISH_CXXFLAGS) \
$$(CFG_GCCISH_CFLAGS_$$(HOST_$(1))) \
$$(CFG_CLANG_CFLAGS_$$(HOST_$(1))) \
$$(CFG_DEPEND_FLAGS) \
-c -o $$(1) $$(2)
- CFG_LINK_C_$(1) = $$(CFG_GCCISH_CROSS)$$(CXX) \
+ CFG_LINK_CXX_$(1) = $$(CFG_GCCISH_CROSS)$$(CXX) \
$$(CFG_GCCISH_LINK_FLAGS) -o $$(1) \
$$(CFG_GCCISH_LINK_FLAGS_$$(HOST_$(1))) \
$$(CFG_GCCISH_DEF_FLAG)$$(3) $$(2) \
ifeq ($(origin CPP),default)
CPP=gcc -E
endif
- CFG_GCCISH_CFLAGS += -Wall -Werror -fno-rtti -g
+ CFG_GCCISH_CFLAGS += -Wall -Werror -g
+ CFG_GCCISH_CXXFLAGS += -fno-rtti
CFG_GCCISH_LINK_FLAGS += -g
# These flags will cause the compiler to produce a .d file
# next to the .o file that lists header deps.
CFG_DEPEND_FLAGS = -MMD -MP -MT $(1) -MF $(1:%.o=%.d)
define CFG_MAKE_CC
- CFG_COMPILE_C_$(1) = $$(CFG_GCCISH_CROSS)$$(CXX) \
+ CFG_COMPILE_C_$(1) = $$(CFG_GCCISH_CROSS)$$(CC) \
+ $$(CFG_GCCISH_CFLAGS) \
+ $$(CFG_GCCISH_CFLAGS_$$(HOST_$(1))) \
+ $$(CFG_GCC_CFLAGS) \
+ $$(CFG_GCC_CFLAGS_$$(HOST_$(1))) \
+ $$(CFG_DEPEND_FLAGS) \
+ -c -o $$(1) $$(2)
+ CFG_LINK_C_$(1) = $$(CFG_GCCISH_CROSS)$$(CC) \
+ $$(CFG_GCCISH_LINK_FLAGS) -o $$(1) \
+ $$(CFG_GCCISH_LINK_FLAGS_$$(HOST_$(1))) \
+ $$(CFG_GCCISH_DEF_FLAG)$$(3) $$(2) \
+ $$(call CFG_INSTALL_NAME,$$(4))
+ CFG_COMPILE_CXX_$(1) = $$(CFG_GCCISH_CROSS)$$(CXX) \
$$(CFG_GCCISH_CFLAGS) \
+ $$(CFG_GCCISH_CXXFLAGS) \
$$(CFG_GCCISH_CFLAGS_$$(HOST_$(1))) \
$$(CFG_GCC_CFLAGS) \
$$(CFG_GCC_CFLAGS_$$(HOST_$(1))) \
$$(CFG_DEPEND_FLAGS) \
-c -o $$(1) $$(2)
- CFG_LINK_C_$(1) = $$(CFG_GCCISH_CROSS)$$(CXX) \
+ CFG_LINK_CXX_$(1) = $$(CFG_GCCISH_CROSS)$$(CXX) \
$$(CFG_GCCISH_LINK_FLAGS) -o $$(1) \
$$(CFG_GCCISH_LINK_FLAGS_$$(HOST_$(1))) \
$$(CFG_GCCISH_DEF_FLAG)$$(3) $$(2) \
$(S)src/test/*/*/*.rs) \
$(wildcard $(S)src/fuzzer/*.rs) \
$(wildcard $(S)src/cargo/*.rs)
+ $(wildcard $(S)src/rusti/*.rs)
PP_INPUTS_FILTERED = $(shell echo $(PP_INPUTS) | xargs grep -L \
"no-reformat\|xfail-pretty\|xfail-test")
rt/$(1)/%.o: rt/%.cpp $$(MKFILE_DEPS)
@$$(call E, compile: $$@)
- $$(Q)$$(call CFG_COMPILE_C_$(1), $$@, $$(RUNTIME_INCS_$(1)) \
+ $$(Q)$$(call CFG_COMPILE_CXX_$(1), $$@, $$(RUNTIME_INCS_$(1)) \
$$(SNAP_DEFINES)) $$<
rt/$(1)/%.o: rt/%.S $$(MKFILE_DEPS) \
$$(RUNTIME_DEF_$(1)) \
$$(RUNTIME_LIBS_$(1))
@$$(call E, link: $$@)
- $$(Q)$$(call CFG_LINK_C_$(1),$$@, $$(RUNTIME_OBJS_$(1)) \
+ $$(Q)$$(call CFG_LINK_CXX_$(1),$$@, $$(RUNTIME_OBJS_$(1)) \
$$(CFG_GCCISH_POST_LIB_FLAGS) $$(RUNTIME_LIBS_$(1)) \
$$(CFG_LIBUV_LINK_FLAGS),$$(RUNTIME_DEF_$(1)),$$(CFG_RUNTIME))
rustllvm/$(1)/$(CFG_RUSTLLVM): $$(RUSTLLVM_OBJS_OBJS_$(1)) \
$$(MKFILE_DEPS) $$(RUSTLLVM_DEF_$(1))
@$$(call E, link: $$@)
- $$(Q)$$(call CFG_LINK_C_$(1),$$@,$$(RUSTLLVM_OBJS_OBJS_$(1)) \
+ $$(Q)$$(call CFG_LINK_CXX_$(1),$$@,$$(RUSTLLVM_OBJS_OBJS_$(1)) \
$$(CFG_GCCISH_PRE_LIB_FLAGS) $$(LLVM_LIBS_$(1)) \
$$(CFG_GCCISH_POST_LIB_FLAGS) \
$$(LLVM_LDFLAGS_$(1)),$$(RUSTLLVM_DEF_$(1)),$$(CFG_RUSTLLVM))
rustllvm/$(1)/%.o: rustllvm/%.cpp $$(MKFILE_DEPS) $$(LLVM_CONFIG_$(1))
@$$(call E, compile: $$@)
- $$(Q)$$(call CFG_COMPILE_C_$(1), $$@, $$(LLVM_CXXFLAGS_$(1)) $$(RUSTLLVM_INCS_$(1))) $$<
+ $$(Q)$$(call CFG_COMPILE_CXX_$(1), $$@, $$(LLVM_CXXFLAGS_$(1)) $$(RUSTLLVM_INCS_$(1))) $$<
endef
# Instantiate template for all stages
USE_SNAPSHOT_CORELIB=0
USE_SNAPSHOT_STDLIB=0
+LINENOISE_OBJS_$(2) := linenoise/$(2)/linenoise.o
+ALL_OBJ_FILES += $$(LINENOISE_OBJS_$(2))
+
+linenoise/$(2)/linenoise.o: linenoise/linenoise.c $$(MKFILE_DEPS)
+ @$$(call E, compile: $$@)
+ $$(Q)$$(call CFG_COMPILE_C_$(2), $$@,) $$<
+
+linenoise/$(2)/liblinenoise.a: $$(LINENOISE_OBJS_$(2))
+ @$$(call E, link: $$@)
+ $$(Q)ar rcs $$@ $$<
+
define TARGET_STAGE_N
$$(TLIB$(1)_T_$(2)_H_$(3))/libmorestack.a: \
@$$(call E, cp: $$@)
$$(Q)cp $$< $$@
+$$(TLIB$(1)_T_$(2)_H_$(3))/liblinenoise.a: \
+ linenoise/$(2)/liblinenoise.a
+ @$$(call E, cp: $$@)
+ $$(Q)cp $$< $$@
+
$$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_RUSTLLVM): \
rustllvm/$(2)/$$(CFG_RUSTLLVM)
@$$(call E, cp: $$@)
check-stage$(1)-T-$(2)-H-$(3)-bench \
check-stage$(1)-T-$(2)-H-$(3)-pretty \
check-stage$(1)-T-$(2)-H-$(3)-rustdoc \
+ check-stage$(1)-T-$(2)-H-$(3)-rusti \
check-stage$(1)-T-$(2)-H-$(3)-cargo \
check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial \
check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial-ffi \
check-stage$(1)-T-$(2)-H-$(3)-rustdoc: \
check-stage$(1)-T-$(2)-H-$(3)-rustdoc-dummy
+check-stage$(1)-T-$(2)-H-$(3)-rusti: \
+ check-stage$(1)-T-$(2)-H-$(3)-rusti-dummy
+
check-stage$(1)-T-$(2)-H-$(3)-cargo: \
check-stage$(1)-T-$(2)-H-$(3)-cargo-dummy
$$(Q)$$(call CFG_RUN_TEST,$$<,$(2),$(3)) $$(TESTARGS) \
--logfile tmp/check-stage$(1)-T-$(2)-H-$(3)-rustdoc.log
+# Rules for the rusti test runner
+
+$(3)/test/rustitest.stage$(1)-$(2)$$(X): \
+ $$(RUSTI_CRATE) $$(RUSTI_INPUTS) \
+ $$(TSREQ$(1)_T_$(2)_H_$(3)) \
+ $$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_CORELIB) \
+ $$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_STDLIB) \
+ $$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_LIBRUSTC)
+ @$$(call E, compile_and_link: $$@)
+ $$(STAGE$(1)_T_$(2)_H_$(3)) -o $$@ $$< --test
+
+check-stage$(1)-T-$(2)-H-$(3)-rusti-dummy: \
+ $(3)/test/rustitest.stage$(1)-$(2)$$(X)
+ @$$(call E, run: $$<)
+ $$(Q)$$(call CFG_RUN_TEST,$$<,$(2),$(3)) $$(TESTARGS) \
+ --logfile tmp/check-stage$(1)-T-$(2)-H-$(3)-rusti.log
+
# Rules for the cargo test runner
$(3)/test/cargotest.stage$(1)-$(2)$$(X): \
check-stage$(1)-H-$(2)-rustdoc: \
$$(foreach target,$$(CFG_TARGET_TRIPLES), \
check-stage$(1)-T-$$(target)-H-$(2)-rustdoc)
+check-stage$(1)-H-$(2)-rusti: \
+ $$(foreach target,$$(CFG_TARGET_TRIPLES), \
+ check-stage$(1)-T-$$(target)-H-$(2)-rusti)
check-stage$(1)-H-$(2)-cargo: \
$$(foreach target,$$(CFG_TARGET_TRIPLES), \
check-stage$(1)-T-$$(target)-H-$(2)-cargo)
check-stage$(1)-H-all-rustdoc: \
$$(foreach target,$$(CFG_TARGET_TRIPLES), \
check-stage$(1)-H-$$(target)-rustdoc)
+check-stage$(1)-H-all-rusti: \
+ $$(foreach target,$$(CFG_TARGET_TRIPLES), \
+ check-stage$(1)-H-$$(target)-rusti)
check-stage$(1)-H-all-cargo: \
$$(foreach target,$$(CFG_TARGET_TRIPLES), \
check-stage$(1)-H-$$(target)-cargo)
check-stage$(1)-pretty-bench: check-stage$(1)-H-$$(CFG_HOST_TRIPLE)-pretty-bench
check-stage$(1)-pretty-pretty: check-stage$(1)-H-$$(CFG_HOST_TRIPLE)-pretty-pretty
check-stage$(1)-rustdoc: check-stage$(1)-H-$$(CFG_HOST_TRIPLE)-rustdoc
+check-stage$(1)-rusti: check-stage$(1)-H-$$(CFG_HOST_TRIPLE)-rusti
check-stage$(1)-cargo: check-stage$(1)-H-$$(CFG_HOST_TRIPLE)-cargo
check-stage$(1)-doc-tutorial: check-stage$(1)-H-$$(CFG_HOST_TRIPLE)-doc-tutorial
check-stage$(1)-doc-tutorial-ffi: check-stage$(1)-H-$$(CFG_HOST_TRIPLE)-doc-tutorial-ffi
CARGO_CRATE := $(S)src/cargo/cargo.rc
CARGO_INPUTS := $(wildcard $(S)src/cargo/*rs)
+# Rusti, the JIT REPL
+RUSTI_CRATE := $(S)src/rusti/rusti.rc
+RUSTI_INPUTS := $(wildcard $(S)src/rusti/*rs)
+
# Rustdoc, the documentation tool
RUSTDOC_CRATE := $(S)src/rustdoc/rustdoc.rc
RUSTDOC_INPUTS := $(wildcard $(S)src/rustdoc/*.rs)
@$$(call E, compile_and_link: $$@)
$$(STAGE$(1)_T_$(4)_H_$(3)) -o $$@ $$<
+$$(TBIN$(1)_T_$(4)_H_$(3))/rusti$$(X): \
+ $$(RUSTI_CRATE) $$(RUSTI_INPUTS) \
+ $$(TSREQ$(1)_T_$(4)_H_$(3)) \
+ $$(TLIB$(1)_T_$(4)_H_$(3))/$$(CFG_CORELIB) \
+ $$(TLIB$(1)_T_$(4)_H_$(3))/$$(CFG_STDLIB) \
+ $$(TLIB$(1)_T_$(4)_H_$(3))/$$(CFG_LIBRUSTC)
+ @$$(call E, compile_and_link: $$@)
+ $$(STAGE$(1)_T_$(4)_H_$(3)) -o $$@ $$<
+
$$(HBIN$(2)_H_$(4))/cargo$$(X): \
$$(TBIN$(1)_T_$(4)_H_$(3))/cargo$$(X) \
$$(HSREQ$(2)_H_$(4))
@$$(call E, cp: $$@)
$$(Q)cp $$< $$@
+$$(HBIN$(2)_H_$(4))/rusti$$(X): \
+ $$(TBIN$(1)_T_$(4)_H_$(3))/rusti$$(X) \
+ $$(HSREQ$(2)_H_$(4))
+ @$$(call E, cp: $$@)
+ $$(Q)cp $$< $$@
+
$$(TBIN$(1)_T_$(4)_H_$(3))/rustdoc$$(X): \
$$(RUSTDOC_CRATE) $$(RUSTDOC_INPUTS) \
$$(TSREQ$(1)_T_$(4)_H_$(3)) \
cargo/ The package manager
+rusti/ The JIT REPL
+
rustdoc/ The Rust API documentation tool
llvm/ The LLVM submodule
rustllvm/ LLVM support code
+linenoise\ Minimalistic libreadline alternative
+
fuzzer/ A collection of fuzz testers
etc/ Scripts, editor support, misc
pub mod inst;
}
pub mod result;
+pub mod rl;
pub mod to_str;
pub mod to_bytes;
pub mod from_str;
--- /dev/null
+use libc::{c_char, c_int};
+
+#[link_args = "-Llinenoise"]
+#[link_name = "linenoise"]
+#[abi = "cdecl"]
+extern mod linenoise {
+ #[legacy_exports];
+ fn linenoise(prompt: *c_char) -> *c_char;
+ fn linenoiseHistoryAdd(line: *c_char) -> c_int;
+ fn linenoiseHistorySetMaxLen(len: c_int) -> c_int;
+ fn linenoiseHistorySave(file: *c_char) -> c_int;
+ fn linenoiseHistoryLoad(file: *c_char) -> c_int;
+ fn linenoiseSetCompletionCallback(callback: *u8);
+ fn linenoiseAddCompletion(completions: *(), line: *c_char);
+ fn linenoiseClearScreen();
+}
+
+/// Add a line to history
+pub fn add_history(line: ~str) -> bool {
+ do str::as_c_str(line) |buf| {
+ linenoise::linenoiseHistoryAdd(buf) == 1 as c_int
+ }
+}
+
+/// Set the maximum amount of lines stored
+pub fn set_history_max_len(len: int) -> bool {
+ linenoise::linenoiseHistorySetMaxLen(len as c_int) == 1 as c_int
+}
+
+/// Save line history to a file
+pub fn save_history(file: ~str) -> bool {
+ do str::as_c_str(file) |buf| {
+ linenoise::linenoiseHistorySave(buf) == 1 as c_int
+ }
+}
+
+/// Load line history from a file
+pub fn load_history(file: ~str) -> bool {
+ do str::as_c_str(file) |buf| {
+ linenoise::linenoiseHistoryLoad(buf) == 1 as c_int
+ }
+}
+
+/// Print out a prompt and then wait for input and return it
+pub fn read(prompt: ~str) -> Option<~str> {
+ do str::as_c_str(prompt) |buf| unsafe {
+ let line = linenoise::linenoise(buf);
+
+ if line.is_null() { None }
+ else { Some(str::raw::from_c_str(line)) }
+ }
+}
+
+/// Clear the screen
+pub fn clear() {
+ linenoise::linenoiseClearScreen();
+}
+
+pub type CompletionCb = fn~(~str, fn(~str));
+
+fn complete_key(_v: @CompletionCb) {}
+
+/// Bind to the main completion callback
+pub fn complete(cb: CompletionCb) unsafe {
+ task::local_data::local_data_set(complete_key, @(move cb));
+
+ extern fn callback(line: *c_char, completions: *()) unsafe {
+ let cb: CompletionCb = copy *task::local_data::local_data_get(complete_key).get();
+
+ do cb(str::raw::from_c_str(line)) |suggestion| {
+ do str::as_c_str(suggestion) |buf| {
+ linenoise::linenoiseAddCompletion(completions, buf);
+ }
+ }
+ }
+
+ linenoise::linenoiseSetCompletionCallback(callback);
+}
--- /dev/null
+Subproject commit 8c9b481281ba401f6baf45bc9ca9fc940b59405f
--- /dev/null
+// rusti - REPL using the JIT backend
+
+#[link(name = "rusti",
+ vers = "0.4",
+ uuid = "7fb5bf52-7d45-4fee-8325-5ad3311149fc",
+ url = "https://github.com/mozilla/rust/tree/master/src/rusti")];
+
+#[crate_type = "bin"];
+
+#[no_core];
+
+#[allow(vecs_implicitly_copyable,
+ non_implicitly_copyable_typarams)];
+#[allow(non_camel_case_types)];
+#[allow(deprecated_mode)];
+#[allow(deprecated_pattern)];
+
+extern mod core(vers = "0.4");
+extern mod std(vers = "0.4");
+extern mod rustc(vers = "0.4");
+extern mod syntax(vers = "0.4");
+
+use core::*;
+use io::{ReaderUtil, WriterUtil};
+use std::c_vec;
+use rustc::back;
+use rustc::driver::{driver, session};
+use rustc::front;
+use rustc::lib::llvm::llvm;
+use rustc::metadata::{creader, filesearch};
+use rustc::middle::{freevars, kind, lint, trans, ty, typeck};
+use rustc::middle;
+use syntax::{ast, ast_util, codemap, diagnostic, fold, parse, print, visit};
+use syntax::ast_util::*;
+use parse::token;
+use print::{pp, pprust};
--- /dev/null
+/**
+ * A structure shared across REPL instances for storing history
+ * such as statements and view items. I wish the AST was sendable.
+ */
+struct Repl {
+ prompt: ~str,
+ binary: ~str,
+ running: bool,
+ view_items: ~str,
+ stmts: ~str
+}
+
+/// A utility function that hands off a pretty printer to a callback.
+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);
+ }
+}
+
+/**
+ * The AST (or the rest of rustc) are not sendable yet,
+ * so recorded things are printed to strings. A terrible hack that
+ * needs changes to rustc in order to be outed. This is unfortunately
+ * going to cause the REPL to regress in parser performance,
+ * because it has to parse the statements and view_items on each
+ * input.
+ */
+fn record(repl: Repl, blk: @ast::blk, intr: @token::ident_interner) -> Repl {
+ let view_items = if blk.node.view_items.len() > 0 {
+ let new_view_items = do with_pp(intr) |pp, writer| {
+ for blk.node.view_items.each |view_item| {
+ pprust::print_view_item(pp, *view_item);
+ writer.write_line(~"");
+ }
+ };
+
+ debug!("new view items %s", new_view_items);
+
+ repl.view_items + "\n" + new_view_items
+ } else { repl.view_items };
+ let stmts = if blk.node.stmts.len() > 0 {
+ let new_stmts = do with_pp(intr) |pp, writer| {
+ for blk.node.stmts.each |stmt| {
+ match stmt.node {
+ ast::stmt_decl(*) => {
+ pprust::print_stmt(pp, **stmt);
+ writer.write_line(~"");
+ }
+ ast::stmt_expr(expr, _) | ast::stmt_semi(expr, _) => {
+ match expr.node {
+ ast::expr_assign(*) |
+ ast::expr_assign_op(*) |
+ ast::expr_swap(*) => {
+ pprust::print_stmt(pp, **stmt);
+ writer.write_line(~"");
+ }
+ _ => {}
+ }
+ }
+ }
+ }
+ };
+
+ debug!("new stmts %s", new_stmts);
+
+ repl.stmts + "\n" + new_stmts
+ } else { repl.stmts };
+
+ Repl{
+ view_items: view_items,
+ stmts: stmts,
+ .. repl
+ }
+}
+
+/// Run an input string in a Repl, returning the new Repl.
+fn run(repl: Repl, input: ~str) -> Repl {
+ let options: @session::options = @{
+ crate_type: session::unknown_crate,
+ binary: repl.binary,
+ .. *session::basic_options()
+ };
+
+ debug!("building driver input");
+ let head = include_str!("wrapper.rs");
+ let foot = fmt!("%s\nfn main() {\n%s\n\nprint({\n%s\n})\n}",
+ repl.view_items, repl.stmts, input);
+ let wrapped = driver::str_input(head + foot);
+
+ debug!("inputting %s", head + foot);
+
+ debug!("building a driver session");
+ let sess = driver::build_session(options, diagnostic::emit);
+
+ debug!("building driver configuration");
+ let cfg = driver::build_configuration(sess,
+ repl.binary,
+ wrapped);
+
+ debug!("parsing");
+ let mut crate = driver::parse_input(sess, cfg, wrapped);
+ let mut opt = None;
+
+ for crate.node.module.items.each |item| {
+ match item.node {
+ ast::item_fn(_, _, _, blk) => {
+ if item.ident == sess.ident_of(~"main") {
+ opt = blk.node.expr;
+ }
+ }
+ _ => {}
+ }
+ }
+
+ let blk = match opt.get().node {
+ ast::expr_call(_, exprs, _) => {
+ match exprs[0].node {
+ ast::expr_block(blk) => @blk,
+ _ => fail
+ }
+ }
+ _ => fail
+ };
+
+ debug!("configuration");
+ crate = front::config::strip_unconfigured_items(crate);
+
+ debug!("maybe building test harness");
+ crate = front::test::modify_for_testing(sess, crate);
+
+ debug!("expansion");
+ crate = syntax::ext::expand::expand_crate(sess.parse_sess,
+ sess.opts.cfg,
+ crate);
+
+ debug!("intrinsic injection");
+ crate = front::intrinsic_inject::inject_intrinsic(sess, crate);
+
+ debug!("core injection");
+ crate = front::core_inject::maybe_inject_libcore_ref(sess, crate);
+
+ debug!("building lint settings table");
+ lint::build_settings_crate(sess, crate);
+
+ debug!("ast indexing");
+ let ast_map = syntax::ast_map::map_crate(sess.diagnostic(), *crate);
+
+ debug!("external crate/lib resolution");
+ creader::read_crates(sess.diagnostic(), *crate, sess.cstore,
+ sess.filesearch,
+ session::sess_os_to_meta_os(sess.targ_cfg.os),
+ sess.opts.static, sess.parse_sess.interner);
+
+ debug!("language item collection");
+ let lang_items = middle::lang_items::collect_language_items(crate, sess);
+
+ debug!("resolution");
+ let {def_map: def_map,
+ exp_map2: exp_map2,
+ trait_map: trait_map} = middle::resolve::resolve_crate(sess,
+ lang_items,
+ crate);
+
+ debug!("freevar finding");
+ let freevars = freevars::annotate_freevars(def_map, crate);
+
+ debug!("region_resolution");
+ let region_map = middle::region::resolve_crate(sess, def_map, crate);
+
+ debug!("region paramaterization inference");
+ let rp_set = middle::region::determine_rp_in_crate(sess, ast_map,
+ def_map, crate);
+
+ debug!("typechecking");
+ let ty_cx = ty::mk_ctxt(sess, def_map, ast_map, freevars,
+ region_map, rp_set, move lang_items, crate);
+ let (method_map, vtable_map) = typeck::check_crate(ty_cx, trait_map,
+ crate);
+
+ debug!("const marking");
+ middle::const_eval::process_crate(crate, def_map, ty_cx);
+
+ debug!("const checking");
+ middle::check_const::check_crate(sess, crate, ast_map, def_map,
+ method_map, ty_cx);
+
+ debug!("privacy checking");
+ middle::privacy::check_crate(ty_cx, &method_map, crate);
+
+ debug!("loop checking");
+ middle::check_loop::check_crate(ty_cx, crate);
+
+ debug!("alt checking");
+ middle::check_alt::check_crate(ty_cx, crate);
+
+ debug!("liveness checking");
+ let last_use_map = middle::liveness::check_crate(ty_cx,
+ method_map, crate);
+
+ debug!("borrow checking");
+ let (root_map, mutbl_map) = middle::borrowck::check_crate(ty_cx,
+ method_map,
+ last_use_map,
+ crate);
+
+ debug!("kind checking");
+ kind::check_crate(ty_cx, method_map, last_use_map, crate);
+
+ debug!("lint checking");
+ lint::check_crate(ty_cx, crate);
+
+ let maps = {mutbl_map: mutbl_map,
+ root_map: root_map,
+ last_use_map: last_use_map,
+ method_map: method_map,
+ vtable_map: vtable_map};
+
+ debug!("translation");
+ let (llmod, _) = trans::base::trans_crate(sess, crate, ty_cx,
+ ~path::from_str("<repl>"),
+ exp_map2, maps);
+ let pm = llvm::LLVMCreatePassManager();
+
+ debug!("executing jit");
+ back::link::jit::exec(sess, pm, llmod, 0, false);
+ llvm::LLVMDisposePassManager(pm);
+
+ debug!("recording input into repl history");
+ record(repl, blk, sess.parse_sess.interner)
+}
+
+/// Run a command, e.g. :clear, :exit, etc.
+fn run_cmd(repl: &mut Repl, _in: io::Reader, _out: io::Writer,
+ cmd: ~str, _args: ~[~str]) {
+ match cmd {
+ ~"exit" => repl.running = false,
+ ~"clear" => {
+ repl.view_items = ~"";
+ repl.stmts = ~"";
+
+ rl::clear();
+ }
+ ~"help" => {
+ io::println(~":clear - clear the screen\n" +
+ ~":exit - exit from the repl\n" +
+ ~":help - show this message");
+ }
+ _ => io::println(~"unknown cmd: " + cmd)
+ }
+}
+
+fn main() {
+ let args = os::args();
+ let in = io::stdin();
+ let out = io::stdout();
+ let mut repl = Repl {
+ prompt: ~"rusti> ",
+ binary: args[0],
+ running: true,
+ view_items: ~"",
+ stmts: ~""
+ };
+
+ do rl::complete |line, suggest| {
+ if line.starts_with(":") {
+ suggest(~":clear");
+ suggest(~":exit");
+ suggest(~":help");
+ }
+ }
+
+ while repl.running {
+ let result = rl::read(repl.prompt);
+
+ if result.is_none() {
+ break;
+ }
+
+ let line = result.get();
+
+ if line.is_empty() {
+ io::println(~"()");
+
+ loop;
+ }
+
+ rl::add_history(line);
+
+ if line.starts_with(~":") {
+ let full = line.substr(1, line.len() - 1);
+ let split = full.split_char(' ');
+ let len = split.len();
+
+ if len > 0 {
+ let cmd = split[0];
+
+ if !cmd.is_empty() {
+ let args = if len > 1 {
+ do vec::view(split, 1, len - 1).map |arg| {
+ *arg
+ }
+ } else { ~[] };
+
+ run_cmd(&mut repl, in, out, cmd, args);
+
+ loop;
+ }
+ }
+ }
+
+ let result = do task::try |copy repl| {
+ run(copy repl, line)
+ };
+
+ if result.is_ok() {
+ repl = result.get();
+ }
+ }
+}
--- /dev/null
+#[legacy_modes];
+#[legacy_exports];
+
+#[allow(ctypes)];
+#[allow(deprecated_mode)];
+#[allow(deprecated_pattern)];
+#[allow(heap_memory)];
+#[allow(implicit_copies)];
+#[allow(managed_heap_memory)];
+#[allow(non_camel_case_types)];
+#[allow(non_implicitly_copyable_typarams)];
+#[allow(owned_heap_memory)];
+#[allow(path_statement)];
+#[allow(structural_records)];
+#[allow(unrecognized_lint)];
+#[allow(unused_imports)];
+#[allow(vecs_implicitly_copyable)];
+#[allow(while_true)];
+
+extern mod std;
+
+fn print<T>(result: T) {
+ io::println(fmt!("%?", result));
+}