diff --git a/.gitmodules b/.gitmodules index d750f8eb5b78..f78aed6261a6 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [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 diff --git a/AUTHORS.txt b/AUTHORS.txt index 08a3ec77807c..cc9c1a460a2f 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -23,6 +23,7 @@ Benjamin Peterson Brendan Eich Brian Anderson Brian J. Burg +Brian Leibig Chris Double Chris Peterson Damian Gryski diff --git a/Makefile.in b/Makefile.in index a7594261c295..26365917a3d4 100644 --- a/Makefile.in +++ b/Makefile.in @@ -74,6 +74,7 @@ endif CFG_RUSTC_FLAGS := $(RUSTFLAGS) CFG_GCCISH_CFLAGS := +CFG_GCCISH_CXXFLAGS := CFG_GCCISH_LINK_FLAGS := ifdef CFG_DISABLE_OPTIMIZE @@ -449,9 +450,10 @@ TSREQS := \ $(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 diff --git a/configure b/configure index e67ea3af5f38..9c30bc2af14d 100755 --- a/configure +++ b/configure @@ -508,6 +508,12 @@ do 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 diff --git a/mk/clean.mk b/mk/clean.mk index d36cbaf7d0bf..9b606a845a58 100644 --- a/mk/clean.mk +++ b/mk/clean.mk @@ -23,7 +23,7 @@ clean: clean-misc $(CLEAN_STAGE_RULES) 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 \ @@ -31,11 +31,12 @@ clean-misc: -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 @@ -55,6 +56,7 @@ clean$(1)_H_$(2): $(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) @@ -81,6 +83,7 @@ clean$(1)_T_$(2)_H_$(3): $(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) @@ -95,6 +98,7 @@ clean$(1)_T_$(2)_H_$(3): $(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), \ diff --git a/mk/dist.mk b/mk/dist.mk index dd6a7aba4d6c..af4c6d8741bc 100644 --- a/mk/dist.mk +++ b/mk/dist.mk @@ -22,6 +22,7 @@ PKG_FILES := \ $(addprefix $(S)src/, \ README.txt \ cargo \ + rusti \ rustc \ compiletest \ etc \ @@ -29,6 +30,7 @@ PKG_FILES := \ libcore \ libsyntax \ libstd \ + linenoise \ rt \ rustdoc \ rustllvm \ diff --git a/mk/install.mk b/mk/install.mk index 3a2dbceaaad3..8bc691e813e0 100644 --- a/mk/install.mk +++ b/mk/install.mk @@ -72,6 +72,7 @@ install-host: $(SREQ$(ISTAGE)_T_$(CFG_HOST_TRIPLE)_H_$(CFG_HOST_TRIPLE)) $(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)) @@ -91,6 +92,7 @@ HOST_LIB_FROM_HL_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) diff --git a/mk/platform.mk b/mk/platform.mk index 67eaa1b878b3..010ddecb131c 100644 --- a/mk/platform.mk +++ b/mk/platform.mk @@ -212,20 +212,33 @@ ifeq ($(CFG_C_COMPILER),clang) 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) \ @@ -245,21 +258,35 @@ ifeq ($(CFG_C_COMPILER),gcc) 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) \ diff --git a/mk/pp.mk b/mk/pp.mk index dd956216bbe4..bf2a64f9b62a 100644 --- a/mk/pp.mk +++ b/mk/pp.mk @@ -9,6 +9,7 @@ else $(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") diff --git a/mk/rt.mk b/mk/rt.mk index 2304bcbf9d2f..573aad99cd08 100644 --- a/mk/rt.mk +++ b/mk/rt.mk @@ -117,7 +117,7 @@ RUNTIME_LIBS_$(1) := $$(LIBUV_LIB_$(1)) 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) \ @@ -133,7 +133,7 @@ rt/$(1)/$(CFG_RUNTIME): $$(RUNTIME_OBJS_$(1)) $$(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)) diff --git a/mk/rustllvm.mk b/mk/rustllvm.mk index 622f7d4fa090..c56220af05ee 100644 --- a/mk/rustllvm.mk +++ b/mk/rustllvm.mk @@ -25,14 +25,14 @@ ALL_OBJ_FILES += $$(RUSTLLVM_OBJS_OBJS_$(1)) 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 diff --git a/mk/target.mk b/mk/target.mk index 967191ab7450..51c89597ca69 100644 --- a/mk/target.mk +++ b/mk/target.mk @@ -12,6 +12,17 @@ USE_SNAPSHOT_RUNTIME=0 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: \ @@ -19,6 +30,11 @@ $$(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: $$@) diff --git a/mk/tests.mk b/mk/tests.mk index d8457a4f4974..7c6b9795c51b 100644 --- a/mk/tests.mk +++ b/mk/tests.mk @@ -229,6 +229,7 @@ check-stage$(1)-T-$(2)-H-$(3): \ 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 \ @@ -289,6 +290,9 @@ check-stage$(1)-T-$(2)-H-$(3)-pretty-pretty: \ 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 @@ -371,6 +375,23 @@ check-stage$(1)-T-$(2)-H-$(3)-rustdoc-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): \ @@ -756,6 +777,9 @@ check-stage$(1)-H-$(2)-pretty-pretty: \ 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) @@ -846,6 +870,9 @@ check-stage$(1)-H-all-pretty-pretty: \ 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) @@ -880,6 +907,7 @@ check-stage$(1)-pretty-rfail: check-stage$(1)-H-$$(CFG_HOST_TRIPLE)-pretty-rfail 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 diff --git a/mk/tools.mk b/mk/tools.mk index 6b7810de73b3..a17305081db6 100644 --- a/mk/tools.mk +++ b/mk/tools.mk @@ -12,6 +12,10 @@ COMPILETEST_INPUTS := $(wildcard $(S)src/compiletest/*rs) 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) @@ -62,12 +66,27 @@ $$(TBIN$(1)_T_$(4)_H_$(3))/cargo$$(X): \ @$$(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)) \ diff --git a/src/README.txt b/src/README.txt index 5e0d9bd0e841..e435d51463e8 100644 --- a/src/README.txt +++ b/src/README.txt @@ -30,6 +30,8 @@ compiletest/ The test runner cargo/ The package manager +rusti/ The JIT REPL + rustdoc/ The Rust API documentation tool llvm/ The LLVM submodule @@ -38,6 +40,8 @@ libuv/ The libuv submodule rustllvm/ LLVM support code +linenoise\ Minimalistic libreadline alternative + fuzzer/ A collection of fuzz testers etc/ Scripts, editor support, misc diff --git a/src/libcore/core.rc b/src/libcore/core.rc index 94e6decc4ca8..742385241b5a 100644 --- a/src/libcore/core.rc +++ b/src/libcore/core.rc @@ -152,6 +152,7 @@ pub mod option_iter { pub mod inst; } pub mod result; +pub mod rl; pub mod to_str; pub mod to_bytes; pub mod from_str; diff --git a/src/libcore/rl.rs b/src/libcore/rl.rs new file mode 100644 index 000000000000..5230b0596caf --- /dev/null +++ b/src/libcore/rl.rs @@ -0,0 +1,78 @@ +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); +} diff --git a/src/linenoise b/src/linenoise new file mode 160000 index 000000000000..8c9b481281ba --- /dev/null +++ b/src/linenoise @@ -0,0 +1 @@ +Subproject commit 8c9b481281ba401f6baf45bc9ca9fc940b59405f diff --git a/src/rusti/rusti.rc b/src/rusti/rusti.rc new file mode 100644 index 000000000000..612c57add812 --- /dev/null +++ b/src/rusti/rusti.rc @@ -0,0 +1,36 @@ +// 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}; diff --git a/src/rusti/rusti.rs b/src/rusti/rusti.rs new file mode 100644 index 000000000000..d12172ac69d1 --- /dev/null +++ b/src/rusti/rusti.rs @@ -0,0 +1,323 @@ +/** + * 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(""), + 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(); + } + } +} diff --git a/src/rusti/wrapper.rs b/src/rusti/wrapper.rs new file mode 100644 index 000000000000..0e6510c88df3 --- /dev/null +++ b/src/rusti/wrapper.rs @@ -0,0 +1,24 @@ +#[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(result: T) { + io::println(fmt!("%?", result)); +}