Merge branch 'master' into recursive-elseif

Conflicts:

	src/comp/middle/typeck.rs
This commit is contained in:
Brian Anderson 2011-03-13 19:40:25 -04:00
commit bbb6836da0
44 changed files with 1856 additions and 961 deletions

View file

@ -34,6 +34,7 @@ DSYMUTIL := true
ifeq ($(CFG_OSTYPE), FreeBSD)
CFG_RUNTIME := librustrt.so
CFG_SUPPORT := librustllvm.so
CFG_STDLIB := libstd.so
CFG_GCC_CFLAGS += -fPIC -march=i686 -I/usr/local/include
CFG_GCC_LINK_FLAGS += -shared -fPIC -lpthread -lrt
@ -47,6 +48,7 @@ endif
ifeq ($(CFG_OSTYPE), Linux)
CFG_RUNTIME := librustrt.so
CFG_SUPPORT := librustllvm.so
CFG_STDLIB := libstd.so
CFG_GCC_CFLAGS += -fPIC -march=i686
CFG_GCC_LINK_FLAGS += -shared -fPIC -ldl -lpthread -lrt
@ -60,6 +62,7 @@ endif
ifeq ($(CFG_OSTYPE), Darwin)
CFG_RUNTIME := librustrt.dylib
CFG_SUPPORT := librustllvm.dylib
CFG_STDLIB := libstd.dylib
CFG_UNIXY := 1
CFG_GCC_LINK_FLAGS += -dynamiclib -lpthread
@ -85,8 +88,8 @@ ifdef CFG_WINDOWSY
CFG_NATIVE := 1
endif
CFG_RUNTIME := rustrt.dll
CFG_SUPPORT := rustllvm.dll
CFG_STDLIB := std.dll
CFG_OBJ_SUFFIX := .o
CFG_EXE_SUFFIX := .exe
CFG_BOOT := ./rustboot.exe
CFG_RUSTC := ./rustc.exe
@ -101,7 +104,6 @@ ifdef CFG_UNIXY
CFG_INFO := $(info cfg: unix-y environment)
CFG_BOOT := ./rustboot
CFG_RUSTC := ./rustc
CFG_OBJ_SUFFIX := .o
CFG_RUN_TARG = LD_LIBRARY_PATH=. $(CFG_VALGRIND) $(1)
CFG_GCC := 1
ifdef MINGW_CROSS
@ -109,12 +111,12 @@ ifdef CFG_UNIXY
CFG_GCC_CROSS := i586-mingw32msvc-
CFG_BOOT_FLAGS += -t win32-x86-pe
CFG_RUNTIME := rustrt.dll
CFG_SUPPORT := rustllvm.dll
CFG_STDLIB := std.dll
CFG_RUSTC := ./rustc.exe
ifdef CFG_VALGRIND
CFG_VALGRIND += wine
endif
CFG_OBJ_SUFFIX := .o
CFG_EXE_SUFFIX := .exe
CFG_GCC_CFLAGS := -march=i686
CFG_GCC_LINK_FLAGS := -shared
@ -182,7 +184,7 @@ endif
ifneq ($(CFG_LLVM_CONFIG),)
CFG_LLVM_VERSION := $(shell $(CFG_LLVM_CONFIG) --version)
$(info cfg: found llvm-config at $(CFG_LLVM_CONFIG))
CFG_LLVM_ALLOWED_VERSIONS := 2.8svn 2.8 2.9svn
CFG_LLVM_ALLOWED_VERSIONS := 2.8svn 2.8 2.9svn 3.0svn
ifneq ($(findstring $(CFG_LLVM_VERSION),$(CFG_LLVM_ALLOWED_VERSIONS)),)
$(info cfg: using LLVM version $(CFG_LLVM_VERSION))
else
@ -196,6 +198,10 @@ ifdef CFG_LLVM_CONFIG
LLC := "$(shell $(CFG_LLVM_CONFIG) --bindir)/llc"
CFG_LLC_CFLAGS := -march=x86
LLVM-DIS := "$(shell $(CFG_LLVM_CONFIG) --bindir)/llvm-dis"
CFG_LLVM_INCDIR := $(shell $(CFG_LLVM_CONFIG) --includedir)
CFG_LLVM_CXXFLAGS := $(shell $(CFG_LLVM_CONFIG) --cxxflags)
CFG_LLVM_LDFLAGS := $(shell $(CFG_LLVM_CONFIG) --ldflags)
CFG_LLVM_LIBS := $(shell $(CFG_LLVM_CONFIG) --libs)
endif
MKFILES := Makefile
@ -302,15 +308,22 @@ RUNTIME_HDR := rt/globals.h \
rt/test/rust_test_util.h
RUNTIME_INCS := -Irt/isaac -Irt/uthash
RUNTIME_OBJS := $(RUNTIME_CS:.cpp=$(CFG_OBJ_SUFFIX))
RUNTIME_LIBS := $(CFG_RUNTIME_LIBS)
RUNTIME_OBJS := $(RUNTIME_CS:.cpp=.o)
SUPPORT_CS := llvmext/Object.cpp
SUPPORT_HDR := llvmext/include/llvm-c/Object.h
SUPPORT_INCS := -iquote $(CFG_LLVM_INCDIR) -iquote llvmext/include
SUPPORT_OBJS := $(SUPPORT_CS:.cpp=.o)
SUPPORT_LIBS := $(CFG_LLVM_LDFLAGS) $(CFG_LLVM_LIBS)
STDLIB_CRATE := lib/std.rc
STDLIB_INPUTS := $(wildcard lib/*.rc lib/*.rs lib/*/*.rs)
COMPILER_CRATE := comp/rustc.rc
COMPILER_INPUTS := $(wildcard comp/*.rc comp/*.rs comp/*/*.rs)
COMPILER_INPUTS := $(wildcard comp/rustc.rc comp/*.rs comp/*/*.rs)
GENERATED := boot/fe/lexer.ml boot/util/version.ml
GENERATED := boot/fe/lexer.ml boot/util/version.ml glue.o
all: $(CFG_RUSTC) $(MKFILES) $(GENERATED)
@ -325,14 +338,24 @@ $(CFG_RUNTIME): $(RUNTIME_OBJS) $(MKFILES) $(RUNTIME_HDR)
@$(call CFG_ECHO, compile: $<)
$(CFG_QUIET)$(call CFG_LINK_C, $@) $(RUNTIME_OBJS)
$(CFG_SUPPORT): $(SUPPORT_OBJS) $(MKFILES) $(SUPPORT_HDR)
@$(call CFG_ECHO, compile: $<)
$(CFG_QUIET)$(call CFG_LINK_C, $@ $(CFG_LLVM_LDFLAGS) $(CFG_LLVM_LIBS)) \
$(SUPPORT_OBJS)
$(CFG_STDLIB): $(STDLIB_CRATE) $(CFG_BOOT) $(MKFILES)
@$(call CFG_ECHO, compile: $<)
$(BOOT) -shared -o $@ $(STDLIB_CRATE)
%$(CFG_OBJ_SUFFIX): %.cpp $(MKFILES)
rt/%.o: rt/%.cpp $(MKFILES)
@$(call CFG_ECHO, compile: $<)
$(CFG_QUIET)$(call CFG_COMPILE_C, $@, $(RUNTIME_INCS)) $<
llvmext/%.o: llvmext/%.cpp $(MKFILES)
@$(call CFG_ECHO, compile: $<)
$(CFG_QUIET)$(call CFG_COMPILE_C, $@, $(CFG_LLVM_CXXFLAGS) \
$(SUPPORT_INCS)) $<
ifdef CFG_NATIVE
$(CFG_BOOT): $(BOOT_CMXS) $(MKFILES)
@$(call CFG_ECHO, compile: $<)
@ -363,13 +386,18 @@ endif
# Main compiler targets and rules
######################################################################
$(CFG_RUSTC): $(COMPILER_INPUTS) $(CFG_BOOT) $(CFG_RUNTIME) $(CFG_STDLIB)
$(CFG_RUSTC): $(COMPILER_INPUTS) $(CFG_BOOT) $(CFG_RUNTIME) $(CFG_STDLIB) \
$(CFG_SUPPORT)
@$(call CFG_ECHO, compile: $<)
$(BOOT) -minimal -o $@ $<
$(CFG_QUIET)chmod 0755 $@
glue.bc: $(CFG_RUSTC) $(CFG_RUNTIME) $(CFG_STDLIB)
@$(call CFG_ECHO, generate: $@)
$(RUSTC) -o $@ -glue
self: $(CFG_RUSTC)
@$(call CFG_ECHO, compile: $<)
@$(call CFG_ECHO, compile: $(COMPILER_CRATE))
$(RUSTC) $(COMPILER_CRATE)
@ -402,6 +430,7 @@ TEST_XFAILS_BOOT := $(TASK_XFAILS) \
$(NOMINAL_TAG_XFAILS) \
$(CONST_TAG_XFAILS) \
test/run-pass/arith-unsigned.rs \
test/run-pass/box-compare.rs \
test/run-pass/child-outlives-parent.rs \
test/run-pass/clone-with-exterior.rs \
test/run-pass/constrained-type.rs \
@ -409,12 +438,15 @@ TEST_XFAILS_BOOT := $(TASK_XFAILS) \
test/run-pass/obj-as.rs \
test/run-pass/vec-slice.rs \
test/run-pass/fn-lval.rs \
test/run-pass/generic-bind-2.rs \
test/run-pass/generic-fn-box.rs \
test/run-pass/generic-tup.rs \
test/run-pass/iter-ret.rs \
test/run-pass/leak-tag-copy.rs \
test/run-pass/lib-io.rs \
test/run-pass/mlist-cycle.rs \
test/run-pass/obj-as.rs \
test/run-pass/seq-compare.rs \
test/run-pass/task-comm.rs \
test/run-pass/task-comm-3.rs \
test/run-pass/vec-slice.rs \
@ -439,24 +471,11 @@ TEST_XFAILS_RUSTC := $(addprefix test/run-pass/, \
basic-1.rs \
basic-2.rs \
basic.rs \
bind-obj-ctor.rs \
child-outlives-parent.rs \
clone-with-exterior.rs \
comm.rs \
constrained-type.rs \
destructor-ordering.rs \
drop-parametric-closure-with-bound-box.rs \
export-non-interference.rs \
foreach-nested-2.rs \
foreach-nested.rs \
foreach-put-structured.rs \
foreach-simple-outer-slot.rs \
generic-fn-twice.rs \
generic-iter-frame.rs \
generic-recursive-tag.rs \
generic-tag-alt.rs \
generic-tag-values.rs \
iter-range.rs \
iter-ret.rs \
lazychan.rs \
lib-bitv.rs \
@ -478,7 +497,6 @@ TEST_XFAILS_RUSTC := $(addprefix test/run-pass/, \
mutable-alias-vec.rs \
obj-as.rs \
obj-dtor.rs \
obj-return-polytypes.rs \
pred.rs \
preempt.rs \
rt-circular-buffer.rs \
@ -511,13 +529,11 @@ TEST_XFAILS_RUSTC := $(addprefix test/run-pass/, \
threads.rs \
type-sizes.rs \
typestate-cfg-nesting.rs \
use-import-export.rs \
user.rs \
utf8.rs \
vec-alloc-append.rs \
vec-append.rs \
vec-slice.rs \
while-prelude-drop.rs \
while-with-break.rs \
yield.rs \
yield2.rs \
@ -764,9 +780,9 @@ test/bench/shootout/%.boot$(CFG_EXE_SUFFIX): \
@$(call CFG_ECHO, assemble [llvm]: $<)
$(CFG_QUIET)gcc $(CFG_GCC_CFLAGS) -o $@ -c $<
%.rustc$(CFG_EXE_SUFFIX): %.o $(CFG_RUNTIME)
%.rustc$(CFG_EXE_SUFFIX): %.o $(CFG_RUNTIME) glue.o
@$(call CFG_ECHO, link [llvm]: $<)
$(CFG_QUIET)gcc $(CFG_GCC_CFLAGS) -o $@ $< -L. -lrustrt
$(CFG_QUIET)gcc $(CFG_GCC_CFLAGS) glue.o -o $@ $< -L. -lrustrt
@# dsymutil sometimes fails or prints a warning, but the
@# program still runs. Since it simplifies debugging other
@# programs, I\'ll live with the noise.
@ -803,7 +819,7 @@ C_DEPFILES := $(RUNTIME_CS:%.cpp=%.d)
%.d: %.cpp $(MKFILES)
@$(call CFG_ECHO, dep: $<)
$(CFG_QUIET)$(call CFG_DEPEND_C, $@ \
$(patsubst %.cpp, %$(CFG_OBJ_SUFFIX), $<), \
$(patsubst %.cpp, %.o, $<), \
$(RUNTIME_INCS)) $< $(CFG_PATH_MUNGE) >$@.tmp \
&& mv $@.tmp $@
@ -826,9 +842,15 @@ RUSTBOOT_PROBE := $(wildcard $(CFG_BOOT))
ifneq ($(RUSTBOOT_PROBE),)
CFG_INFO := $(info cfg: using built $(CFG_BOOT) for rust deps)
STDLIB_DEPFILE := $(CFG_STDLIB).d
RUSTC_DEPFILE := $(CFG_RUSTC).d
CRATE_DEPFILES := $(ALL_TEST_CRATES:%.rc=%.d) $(STDLIB_DEPFILE)
$(STDLIB_DEPFILE): $(STDLIB_CRATE) $(MKFILES) $(CFG_BOOT)
$(STDLIB_DEPFILE): $(STDLIB_CRATE) $(MKFILES) $(CFG_BOOT) $(STDLIB_INPUTS)
@$(call CFG_ECHO, dep: $<)
$(BOOT) -shared -rdeps $< $(CFG_PATH_MUNGE) >$@.tmp \
&& mv $@.tmp $@
$(RUSTC_DEPFILE): $(STDLIB_CRATE) $(MKFILES) $(CFG_BOOT) $(COMPILER_INPUTS)
@$(call CFG_ECHO, dep: $<)
$(BOOT) -shared -rdeps $< $(CFG_PATH_MUNGE) >$@.tmp \
&& mv $@.tmp $@
@ -920,12 +942,12 @@ clean:
$(CFG_QUIET)rm -f $(ML_DEPFILES:%.d=%.d.tmp)
$(CFG_QUIET)rm -f $(C_DEPFILES:%.d=%.d.tmp)
$(CFG_QUIET)rm -f $(CRATE_DEPFILES:%.d=%.d.tmp)
$(CFG_QUIET)rm -f $(GENERATED)
$(CFG_QUIET)rm -f $(GENERATED) glue.bc glue.s
$(CFG_QUIET)rm -f $(CFG_BOOT) $(CFG_RUNTIME) $(CFG_STDLIB)
$(CFG_QUIET)rm -Rf $(PKG_NAME)-*.tar.gz dist
$(CFG_QUIET)rm -f $(foreach ext,cmx cmi cmo cma o a d exe,\
$(CFG_QUIET)rm -f $(foreach ext,cmx cmi cmo cma bc o a d exe,\
$(wildcard boot/*/*.$(ext) boot/*/*/*.$(ext)))
$(CFG_QUIET)rm -Rf $(foreach ext,out llvm x86 boot rustc o s exe dSYM,\
$(CFG_QUIET)rm -Rf $(foreach ext,out llvm x86 boot rustc bc o s exe dSYM,\
$(wildcard test/*/*.$(ext)))

View file

@ -80,7 +80,7 @@ let general_code_alignment = 16;;
let tydesc_field_first_param = 0;;
let tydesc_field_size = 1;;
let tydesc_field_align = 2;;
let tydesc_field_copy_glue = 3;;
let tydesc_field_take_glue = 3;;
let tydesc_field_drop_glue = 4;;
let tydesc_field_free_glue = 5;;
let tydesc_field_sever_glue = 6;;

View file

@ -1,11 +1,6 @@
open Common;;
let _ =
Gc.set { (Gc.get()) with
Gc.space_overhead = 400; }
;;
let (targ:Common.target) =
match Sys.os_type with

View file

@ -20,7 +20,7 @@ type glue =
| GLUE_yield
| GLUE_exit_main_task
| GLUE_exit_task
| GLUE_copy of Ast.ty (* One-level copy. *)
| GLUE_take of Ast.ty (* One-level refcounts++. *)
| GLUE_drop of Ast.ty (* De-initialize local memory. *)
| GLUE_free of Ast.ty (* Drop body + free() box ptr. *)
| GLUE_sever of Ast.ty (* Null all box state slots. *)
@ -2776,7 +2776,7 @@ let glue_str (cx:ctxt) (g:glue) : string =
| GLUE_yield -> "glue$yield"
| GLUE_exit_main_task -> "glue$exit_main_task"
| GLUE_exit_task -> "glue$exit_task"
| GLUE_copy ty -> "glue$copy$" ^ (ty_str cx ty)
| GLUE_take ty -> "glue$take$" ^ (ty_str cx ty)
| GLUE_drop ty -> "glue$drop$" ^ (ty_str cx ty)
| GLUE_free ty -> "glue$free$" ^ (ty_str cx ty)
| GLUE_sever ty -> "glue$sever$" ^ (ty_str cx ty)

View file

@ -1355,7 +1355,7 @@ let trans_visitor
Asm.WORD (word_ty_mach, Asm.IMM 0L);
Asm.WORD (word_ty_mach, Asm.IMM sz);
Asm.WORD (word_ty_mach, Asm.IMM align);
fix (get_copy_glue t);
fix (get_take_glue t);
fix (get_drop_glue t);
begin
match ty_mem_ctrl cx t with
@ -2022,34 +2022,18 @@ let trans_visitor
get_typed_mem_glue g fty inner
and get_copy_glue
and get_take_glue
(ty:Ast.ty)
: fixup =
let ty = get_genericized_ty ty in
let arg_ty_params_alias = 0 in
let arg_src_alias = 1 in
let arg_initflag = 2 in
let g = GLUE_copy ty in
let inner (out_ptr:Il.cell) (args:Il.cell) =
let dst = deref out_ptr in
let g = GLUE_take ty in
let inner (_:Il.cell) (args:Il.cell) =
let ty_params = deref (get_element_ptr args arg_ty_params_alias) in
let src = deref (get_element_ptr args arg_src_alias) in
(* Translate copy code for the dst-initializing and
* dst-non-initializing cases and branch accordingly. *)
let initflag = get_element_ptr args arg_initflag in
let jmps = trans_compare_simple Il.JNE (Il.Cell initflag) one in
trans_copy_ty_full true ty_params true dst ty src ty;
let skip_noninit_jmp = mark() in
emit (Il.jmp Il.JMP Il.CodeNone);
List.iter patch jmps;
trans_copy_ty_full true ty_params false dst ty src ty;
patch skip_noninit_jmp;
trans_take_ty true ty_params src ty;
in
let ty_params_ptr = ty_params_covering ty in
let fty =
@ -2186,17 +2170,23 @@ let trans_visitor
get_tydesc_params ty_params_cell elt_td_ptr_cell
in
let initflag = Il.Reg (force_to_reg one) in
(* Take all *)
copy_loop dst_buf src_buf (Il.Cell fill) (Il.Cell elt_sz)
begin
fun dptr sptr ->
fun _ sptr ->
trans_call_dynamic_glue
elt_td_ptr_cell
Abi.tydesc_field_copy_glue
(Some (deref dptr))
[| ty_params_ptr; sptr; initflag |]
Abi.tydesc_field_take_glue
None
[| ty_params_ptr; sptr |]
None;
end;
(* Memcpy all *)
copy_loop dst_buf src_buf (Il.Cell fill) one
begin
fun dptr sptr ->
mov (deref dptr) (Il.Cell (deref sptr))
end;
(* Set the new vec's fill to the original vec's fill *)
@ -3734,17 +3724,58 @@ let trans_visitor
end
tys
and trans_copy_ty
(ty_params:Il.cell)
(initializing:bool)
(dst:Il.cell) (dst_ty:Ast.ty)
(src:Il.cell) (src_ty:Ast.ty)
: unit =
trans_copy_ty_full
false ty_params initializing dst dst_ty src src_ty
and trans_copy_ty_full
and trans_take_ty
(force_inline:bool)
(ty_params:Il.cell)
(v:Il.cell)
(ty:Ast.ty)
: unit =
let ty = strip_mutable_or_constrained_ty ty in
match ty_mem_ctrl cx ty with
MEM_rc_opaque | MEM_gc | MEM_rc_struct -> incr_refcount v
| _ ->
begin
match ty with
Ast.TY_fn _
| Ast.TY_obj _ ->
let binding =
get_element_ptr v Abi.binding_field_bound_data
in
let null_jmp = null_check binding in
incr_refcount binding;
patch null_jmp
| Ast.TY_param (i, _) ->
aliasing false v
begin
fun v ->
let td = get_ty_param ty_params i in
let ty_params_ptr = get_tydesc_params ty_params td in
trans_call_dynamic_glue
td Abi.tydesc_field_take_glue
None
[| ty_params_ptr; v; |]
None
end
| Ast.TY_rec _
| Ast.TY_tag _
| Ast.TY_tup _ ->
if force_inline
then
iter_ty_parts ty_params v ty
(trans_take_ty force_inline ty_params)
else
trans_call_static_glue
(code_fixup_to_ptr_operand (get_take_glue ty))
None
[| alias ty_params; alias v; |]
None
| _ -> ()
end
and trans_copy_ty
(ty_params:Il.cell)
(initializing:bool)
(dst:Il.cell) (dst_ty:Ast.ty)
@ -3789,7 +3820,7 @@ let trans_visitor
| _ ->
(* Heavyweight copy: duplicate 1 level of the referent. *)
anno "heavy";
trans_copy_ty_heavy force_inline ty_params initializing
trans_copy_ty_heavy ty_params initializing
dst dst_ty src src_ty
end
@ -3821,7 +3852,6 @@ let trans_visitor
*)
and trans_copy_ty_heavy
(force_inline:bool)
(ty_params:Il.cell)
(initializing:bool)
(dst:Il.cell) (dst_ty:Ast.ty)
@ -3863,68 +3893,14 @@ let trans_visitor
(ty_sz cx ty)));
mov dst (Il.Cell src)
| Ast.TY_param (i, _) ->
iflog
(fun _ -> annotate
(Printf.sprintf "copy_ty: parametric copy %#d" i));
let initflag = Il.Reg (force_to_reg one) in
aliasing false src
begin
fun src ->
let td = get_ty_param ty_params i in
let ty_params_ptr = get_tydesc_params ty_params td in
trans_call_dynamic_glue
td Abi.tydesc_field_copy_glue
(Some dst)
[| ty_params_ptr; src; initflag |]
None
end
| Ast.TY_fn _
| Ast.TY_obj _ ->
begin
let src_item =
get_element_ptr src Abi.binding_field_dispatch
in
let dst_item =
get_element_ptr dst Abi.binding_field_dispatch
in
let src_binding =
get_element_ptr src Abi.binding_field_bound_data
in
let dst_binding =
get_element_ptr dst Abi.binding_field_bound_data
in
mov dst_item (Il.Cell src_item);
mov dst_binding zero;
let null_jmp = null_check src_binding in
(* Copy if we have a src binding. *)
(* FIXME (issue #58): this is completely wrong, call
* through to the binding's self-copy fptr. For now
* this only works by accident.
*)
trans_copy_ty ty_params true
dst_binding (Ast.TY_box Ast.TY_int)
src_binding (Ast.TY_box Ast.TY_int);
patch null_jmp
end
| _ ->
if force_inline || should_inline_structure_helpers ty
then
iter_ty_parts_full ty_params dst src ty
(fun dst src ty ->
trans_copy_ty ty_params true
dst ty src ty)
else
let initflag = Il.Reg (force_to_reg one) in
trans_call_static_glue
(code_fixup_to_ptr_operand (get_copy_glue ty))
(Some dst)
[| alias ty_params;
alias src;
initflag |]
None
trans_take_ty false ty_params src ty;
if not initializing
then drop_ty ty_params dst ty;
let sz = ty_sz_with_ty_params ty_params ty in
copy_loop dst src sz (imm 1L)
(fun dptr sptr ->
mov (deref dptr) (Il.Cell (deref sptr)))
and trans_copy

View file

@ -25,22 +25,39 @@ fn restore_callee_saves() -> vec[str] {
"popl %ebp");
}
fn load_esp_from_rust_sp() -> vec[str] {
fn load_esp_from_rust_sp_first_arg() -> vec[str] {
ret vec("movl " + wstr(abi.task_field_rust_sp) + "(%ecx), %esp");
}
fn load_esp_from_runtime_sp() -> vec[str] {
fn load_esp_from_runtime_sp_first_arg() -> vec[str] {
ret vec("movl " + wstr(abi.task_field_runtime_sp) + "(%ecx), %esp");
}
fn store_esp_to_rust_sp() -> vec[str] {
fn store_esp_to_rust_sp_first_arg() -> vec[str] {
ret vec("movl %esp, " + wstr(abi.task_field_rust_sp) + "(%ecx)");
}
fn store_esp_to_runtime_sp() -> vec[str] {
fn store_esp_to_runtime_sp_first_arg() -> vec[str] {
ret vec("movl %esp, " + wstr(abi.task_field_runtime_sp) + "(%ecx)");
}
fn load_esp_from_rust_sp_second_arg() -> vec[str] {
ret vec("movl " + wstr(abi.task_field_rust_sp) + "(%edx), %esp");
}
fn load_esp_from_runtime_sp_second_arg() -> vec[str] {
ret vec("movl " + wstr(abi.task_field_runtime_sp) + "(%edx), %esp");
}
fn store_esp_to_rust_sp_second_arg() -> vec[str] {
ret vec("movl %esp, " + wstr(abi.task_field_rust_sp) + "(%edx)");
}
fn store_esp_to_runtime_sp_second_arg() -> vec[str] {
ret vec("movl %esp, " + wstr(abi.task_field_runtime_sp) + "(%edx)");
}
/*
* This is a bit of glue-code. It should be emitted once per
* compilation unit.
@ -61,8 +78,8 @@ fn store_esp_to_runtime_sp() -> vec[str] {
fn rust_activate_glue() -> vec[str] {
ret vec("movl 4(%esp), %ecx # ecx = rust_task")
+ save_callee_saves()
+ store_esp_to_runtime_sp()
+ load_esp_from_rust_sp()
+ store_esp_to_runtime_sp_first_arg()
+ load_esp_from_rust_sp_first_arg()
/*
* There are two paths we can arrive at this code from:
@ -154,10 +171,10 @@ fn rust_activate_glue() -> vec[str] {
fn rust_yield_glue() -> vec[str] {
ret vec("movl 0(%esp), %ecx # ecx = rust_task")
+ load_esp_from_rust_sp()
+ load_esp_from_rust_sp_first_arg()
+ save_callee_saves()
+ store_esp_to_rust_sp()
+ load_esp_from_runtime_sp()
+ store_esp_to_rust_sp_first_arg()
+ load_esp_from_runtime_sp_first_arg()
+ restore_callee_saves()
+ vec("ret");
}
@ -175,8 +192,11 @@ fn upcall_glue(int n_args) -> vec[str] {
*/
fn copy_arg(uint i) -> str {
auto src_off = wstr(5 + (i as int));
auto dst_off = wstr(1 + (i as int));
if (i == 0u) {
ret "movl %edx, (%esp)";
}
auto src_off = wstr(4 + (i as int));
auto dst_off = wstr(0 + (i as int));
auto m = vec("movl " + src_off + "(%ebp),%eax",
"movl %eax," + dst_off + "(%esp)");
ret _str.connect(m, "\n\t");
@ -189,20 +209,19 @@ fn upcall_glue(int n_args) -> vec[str] {
+ vec("movl %esp, %ebp # ebp = rust_sp")
+ store_esp_to_rust_sp()
+ load_esp_from_runtime_sp()
+ store_esp_to_rust_sp_second_arg()
+ load_esp_from_runtime_sp_second_arg()
+ vec("subl $" + wstr(n_args + 1) + ", %esp # esp -= args",
"andl $~0xf, %esp # align esp down",
"movl %ecx, (%esp) # arg[0] = rust_task ")
"andl $~0xf, %esp # align esp down")
+ _vec.init_fn[str](carg, n_args as uint)
+ _vec.init_fn[str](carg, (n_args + 1) as uint)
+ vec("movl %ecx, %edi # save task from ecx to edi",
"call *%edx # call *%edx",
"movl %edi, %ecx # restore edi-saved task to ecx")
+ vec("movl %edx, %edi # save task from edx to edi",
"call *%ecx # call *%ecx",
"movl %edi, %edx # restore edi-saved task to edx")
+ load_esp_from_rust_sp()
+ load_esp_from_rust_sp_second_arg()
+ restore_callee_saves()
+ vec("ret");
@ -254,6 +273,16 @@ fn get_module_asm() -> str {
ret _str.connect(glues, "\n\n");
}
fn get_meta_sect_name() -> str {
if (_str.eq(target_os(), "macos")) {
ret "__DATA,__note.rustc";
}
if (_str.eq(target_os(), "win32")) {
ret ".note.rustc";
}
ret ".note.rustc";
}
fn get_data_layout() -> str {
if (_str.eq(target_os(), "macos")) {
ret "e-p:32:32-f64:32:64-i64:32:64-f80:128:128-n8:16:32";

View file

@ -54,7 +54,8 @@ impure fn compile_input(session.session sess,
eval.env env,
str input, str output,
bool shared) {
auto p = parser.new_parser(sess, env, 0, input);
auto def = tup(0, 0);
auto p = parser.new_parser(sess, env, def, input);
auto crate = parse_input(sess, p, input);
crate = resolve.resolve_crate(sess, crate);
crate = typeck.check_crate(sess, crate);
@ -64,9 +65,10 @@ impure fn compile_input(session.session sess,
impure fn pretty_print_input(session.session sess,
eval.env env,
str input) {
auto p = front.parser.new_parser(sess, env, 0, input);
auto def = tup(0, 0);
auto p = front.parser.new_parser(sess, env, def, input);
auto crate = front.parser.parse_crate_from_source_file(p);
pretty.pprust.print_ast(crate.node.module);
pretty.pprust.print_ast(crate.node.module, std.io.stdout_writer());
}
fn warn_wrong_compiler() {
@ -82,6 +84,7 @@ fn usage(session.session sess, str argv0) {
log "";
log " -o <filename> write output to <filename>";
log " -nowarn suppress wrong-compiler warning";
log " -glue generate glue.bc file";
log " -shared compile a shared-library crate";
log " -pp pretty-print the input instead of compiling";
log " -h display this message";
@ -111,6 +114,7 @@ impure fn main(vec[str] args) {
let bool do_warn = true;
let bool shared = false;
let bool pretty = false;
let bool glue = false;
auto i = 1u;
auto len = _vec.len[str](args);
@ -121,6 +125,8 @@ impure fn main(vec[str] args) {
if (_str.byte_len(arg) > 0u && arg.(0) == '-' as u8) {
if (_str.eq(arg, "-nowarn")) {
do_warn = false;
} else if (_str.eq(arg, "-glue")) {
glue = true;
} else if (_str.eq(arg, "-shared")) {
shared = true;
} else if (_str.eq(arg, "-pp")) {
@ -157,6 +163,18 @@ impure fn main(vec[str] args) {
warn_wrong_compiler();
}
if (glue) {
alt (output_file) {
case (none[str]) {
middle.trans.make_common_glue("glue.bc");
}
case (some[str](?s)) {
middle.trans.make_common_glue(s);
}
}
ret;
}
alt (input_file) {
case (none[str]) {
usage(sess, args.(0));

View file

@ -21,7 +21,7 @@ type ty_param = rec(ident ident, def_id id);
// Annotations added during successive passes.
tag ann {
ann_none;
ann_type(@middle.ty.t);
ann_type(@middle.ty.t, option.t[vec[@middle.ty.t]] /* ty param substs */);
}
tag def {
@ -29,9 +29,11 @@ tag def {
def_obj(def_id);
def_obj_field(def_id);
def_mod(def_id);
def_native_mod(def_id);
def_const(def_id);
def_arg(def_id);
def_local(def_id);
def_upvar(def_id);
def_variant(def_id /* tag */, def_id /* variant */);
def_ty(def_id);
def_ty_arg(def_id);
@ -42,7 +44,8 @@ tag def {
}
type crate = spanned[crate_];
type crate_ = rec(_mod module);
type crate_ = rec(vec[@crate_directive] directives,
_mod module);
tag crate_directive_ {
cdir_expr(@expr);
@ -64,9 +67,15 @@ type meta_item = spanned[meta_item_];
type meta_item_ = rec(ident name, str value);
type block = spanned[block_];
type block_index = hashmap[ident, block_index_entry];
tag block_index_entry {
bie_item(@item);
bie_local(@local);
bie_tag_variant(@item /* tag item */, uint /* variant index */);
}
type block_ = rec(vec[@stmt] stmts,
option.t[@expr] expr,
hashmap[ident,uint] index);
hashmap[ident,block_index_entry] index);
type variant_def = tup(def_id /* tag */, def_id /* variant */);
@ -427,6 +436,44 @@ fn index_native_view_item(native_mod_index index, @view_item it) {
}
}
fn index_stmt(block_index index, @stmt s) {
alt (s.node) {
case (ast.stmt_decl(?d)) {
alt (d.node) {
case (ast.decl_local(?loc)) {
index.insert(loc.ident, ast.bie_local(loc));
}
case (ast.decl_item(?it)) {
alt (it.node) {
case (ast.item_fn(?i, _, _, _, _)) {
index.insert(i, ast.bie_item(it));
}
case (ast.item_mod(?i, _, _)) {
index.insert(i, ast.bie_item(it));
}
case (ast.item_ty(?i, _, _, _, _)) {
index.insert(i, ast.bie_item(it));
}
case (ast.item_tag(?i, ?variants, _, _)) {
index.insert(i, ast.bie_item(it));
let uint vid = 0u;
for (ast.variant v in variants) {
auto t = ast.bie_tag_variant(it, vid);
index.insert(v.name, t);
vid += 1u;
}
}
case (ast.item_obj(?i, _, _, _, _)) {
index.insert(i, ast.bie_item(it));
}
}
}
}
}
case (_) { /* fall through */ }
}
}
fn is_call_expr(@expr e) -> bool {
alt (e.node) {
case (expr_call(_, _, _)) {

View file

@ -42,7 +42,7 @@ fn val_is_bool(val v) -> bool {
fn val_is_int(val v) -> bool {
alt (v) {
case (val_bool(_)) { ret true; }
case (val_int(_)) { ret true; }
case (_) { }
}
ret false;
@ -386,9 +386,12 @@ impure fn eval_crate_directive(parser p,
auto full_path = prefix + std.os.path_sep() + file_path;
auto p0 = new_parser(p.get_session(), e, 0, full_path);
auto start_id = p.next_def_id();
auto p0 = new_parser(p.get_session(), e, start_id, full_path);
auto m0 = parse_mod_items(p0, token.EOF);
auto im = ast.item_mod(id, m0, p.next_def_id());
auto next_id = p0.next_def_id();
p.set_def(next_id._1);
auto im = ast.item_mod(id, m0, next_id);
auto i = @spanned(cdir.span, cdir.span, im);
ast.index_item(index, i);
append[@ast.item](items, i);

View file

@ -35,12 +35,13 @@ state type parser =
fn get_session() -> session.session;
fn get_span() -> common.span;
fn next_def_id() -> ast.def_id;
fn set_def(ast.def_num);
fn get_prec_table() -> vec[op_spec];
};
impure fn new_parser(session.session sess,
eval.env env,
ast.crate_num crate,
ast.def_id initial_def,
str path) -> parser {
state obj stdio_parser(session.session sess,
eval.env env,
@ -94,6 +95,10 @@ impure fn new_parser(session.session sess,
ret tup(crate, def);
}
fn set_def(ast.def_num d) {
def = d;
}
fn get_file_type() -> file_type {
ret ftype;
}
@ -114,8 +119,8 @@ impure fn new_parser(session.session sess,
auto rdr = lexer.new_reader(srdr, path);
auto npos = rdr.get_curr_pos();
ret stdio_parser(sess, env, ftype, lexer.next_token(rdr),
npos, npos, 0, UNRESTRICTED, crate, rdr,
prec_table());
npos, npos, initial_def._1, UNRESTRICTED, initial_def._0,
rdr, prec_table());
}
impure fn unexpected(parser p, token.token t) {
@ -1465,39 +1470,9 @@ impure fn parse_source_stmt(parser p) -> @ast.stmt {
}
fn index_block(vec[@ast.stmt] stmts, option.t[@ast.expr] expr) -> ast.block_ {
auto index = new_str_hash[uint]();
auto u = 0u;
auto index = new_str_hash[ast.block_index_entry]();
for (@ast.stmt s in stmts) {
alt (s.node) {
case (ast.stmt_decl(?d)) {
alt (d.node) {
case (ast.decl_local(?loc)) {
index.insert(loc.ident, u);
}
case (ast.decl_item(?it)) {
alt (it.node) {
case (ast.item_fn(?i, _, _, _, _)) {
index.insert(i, u);
}
case (ast.item_mod(?i, _, _)) {
index.insert(i, u);
}
case (ast.item_ty(?i, _, _, _, _)) {
index.insert(i, u);
}
case (ast.item_tag(?i, _, _, _)) {
index.insert(i, u);
}
case (ast.item_obj(?i, _, _, _, _)) {
index.insert(i, u);
}
}
}
}
}
case (_) { /* fall through */ }
}
u += 1u;
ast.index_stmt(index, s);
}
ret rec(stmts=stmts, expr=expr, index=index);
}
@ -2261,7 +2236,9 @@ impure fn parse_crate_from_source_file(parser p) -> @ast.crate {
auto lo = p.get_span();
auto hi = lo;
auto m = parse_mod_items(p, token.EOF);
ret @spanned(lo, hi, rec(module=m));
let vec[@ast.crate_directive] cdirs = vec();
ret @spanned(lo, hi, rec(directives=cdirs,
module=m));
}
// Logic for parsing crate files (.rc)
@ -2276,8 +2253,6 @@ impure fn parse_crate_directive(parser p) -> ast.crate_directive
auto hi = lo;
alt (p.peek()) {
case (token.AUTH) {
// FIXME: currently dropping auth clauses on the floor,
// as there is no effect-checking pass.
p.bump();
auto n = parse_path(p, GREEDY);
expect(p, token.EQ);
@ -2288,8 +2263,6 @@ impure fn parse_crate_directive(parser p) -> ast.crate_directive
}
case (token.META) {
// FIXME: currently dropping meta clauses on the floor,
// as there is no crate metadata system
p.bump();
auto mis = parse_meta(p);
hi = p.get_span();
@ -2398,7 +2371,8 @@ impure fn parse_crate_from_crate_file(parser p) -> @ast.crate {
cdirs, prefix);
hi = p.get_span();
expect(p, token.EOF);
ret @spanned(lo, hi, rec(module=m));
ret @spanned(lo, hi, rec(directives=cdirs,
module=m));
}

View file

@ -1,87 +0,0 @@
import std._int;
import std._str;
import std._uint;
import std._vec;
export print_expr;
// FIXME this is superseded by ../pretty/pprust.rs. can it be dropped?
fn unknown() -> str {
ret "<unknown ast node>";
}
fn print_expr(@ast.expr expr) -> str {
alt (expr.node) {
case (ast.expr_lit(?lit, _)) {
ret print_lit(lit);
}
case (ast.expr_binary(?op, ?lhs, ?rhs, _)) {
ret print_expr_binary(op, lhs, rhs);
}
case (ast.expr_call(?path, ?args, _)) {
ret print_expr_call(path, args);
}
case (ast.expr_path(?path, _, _)) {
ret print_path(path);
}
case (_) {
ret unknown();
}
}
}
fn print_lit(@ast.lit lit) -> str {
alt (lit.node) {
case (ast.lit_str(?s)) {
ret "\"" + s + "\"";
}
case (ast.lit_int(?i)) {
ret _int.to_str(i, 10u);
}
case (ast.lit_uint(?u)) {
ret _uint.to_str(u, 10u);
}
case (_) {
ret unknown();
}
}
}
fn print_expr_binary(ast.binop op, @ast.expr lhs, @ast.expr rhs) -> str {
alt (op) {
case (ast.add) {
auto l = print_expr(lhs);
auto r = print_expr(rhs);
ret l + " + " + r;
}
}
}
fn print_expr_call(@ast.expr path_expr, vec[@ast.expr] args) -> str {
auto s = print_expr(path_expr);
s += "(";
fn print_expr_ref(&@ast.expr e) -> str { ret print_expr(e); }
auto mapfn = print_expr_ref;
auto argstrs = _vec.map[@ast.expr, str](mapfn, args);
s += _str.connect(argstrs, ", ");
s += ")";
ret s;
}
fn print_path(ast.path path) -> str {
ret _str.connect(path.node.idents, ".");
}
//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C ../.. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
//

View file

@ -253,6 +253,8 @@ type ast_fold[ENV] =
(fn(&ENV e, &span sp, ident i, vec[ident] idents,
def_id id, option.t[def]) -> @view_item) fold_view_item_import,
(fn(&ENV e, &span sp, ident i) -> @view_item) fold_view_item_export,
// Additional nodes.
(fn(&ENV e, &span sp,
&ast.block_) -> block) fold_block,
@ -270,6 +272,7 @@ type ast_fold[ENV] =
(fn(&ENV e, &ast.native_mod m) -> ast.native_mod) fold_native_mod,
(fn(&ENV e, &span sp,
vec[@ast.crate_directive] cdirs,
&ast._mod m) -> @ast.crate) fold_crate,
(fn(&ENV e,
@ -451,11 +454,14 @@ fn fold_pat[ENV](&ENV env, ast_fold[ENV] fld, @ast.pat p) -> @ast.pat {
ret fld.fold_pat_bind(env_, p.span, id, did, t);
}
case (ast.pat_tag(?path, ?pats, ?d, ?t)) {
auto ppath = fold_path(env, fld, path);
let vec[@ast.pat] ppats = vec();
for (@ast.pat pat in pats) {
ppats += vec(fold_pat(env_, fld, pat));
}
ret fld.fold_pat_tag(env_, p.span, path, ppats, d, t);
ret fld.fold_pat_tag(env_, p.span, ppath, ppats, d, t);
}
}
}
@ -718,6 +724,7 @@ fn fold_stmt[ENV](&ENV env, ast_fold[ENV] fld, &@stmt s) -> @stmt {
fn fold_block[ENV](&ENV env, ast_fold[ENV] fld, &block blk) -> block {
auto index = new_str_hash[ast.block_index_entry]();
let ENV env_ = fld.update_env_for_block(env, blk);
if (!fld.keep_going(env_)) {
@ -726,7 +733,9 @@ fn fold_block[ENV](&ENV env, ast_fold[ENV] fld, &block blk) -> block {
let vec[@ast.stmt] stmts = vec();
for (@ast.stmt s in blk.node.stmts) {
append[@ast.stmt](stmts, fold_stmt[ENV](env_, fld, s));
auto new_stmt = fold_stmt[ENV](env_, fld, s);
append[@ast.stmt](stmts, new_stmt);
ast.index_stmt(index, new_stmt);
}
auto expr = none[@ast.expr];
@ -739,8 +748,7 @@ fn fold_block[ENV](&ENV env, ast_fold[ENV] fld, &block blk) -> block {
}
}
// FIXME: should we reindex?
ret respan(blk.span, rec(stmts=stmts, expr=expr, index=blk.node.index));
ret respan(blk.span, rec(stmts=stmts, expr=expr, index=index));
}
fn fold_arm[ENV](&ENV env, ast_fold[ENV] fld, &arm a) -> arm {
@ -838,6 +846,10 @@ fn fold_view_item[ENV](&ENV env, ast_fold[ENV] fld, @view_item vi)
ret fld.fold_view_item_import(env_, vi.span, def_ident, idents,
def_id, target_def);
}
case (ast.view_item_export(?def_ident)) {
ret fld.fold_view_item_export(env_, vi.span, def_ident);
}
}
fail;
@ -969,9 +981,12 @@ fn fold_native_mod[ENV](&ENV e, ast_fold[ENV] fld,
}
fn fold_crate[ENV](&ENV env, ast_fold[ENV] fld, @ast.crate c) -> @ast.crate {
// FIXME: possibly fold the directives so you process any expressions
// within them? Not clear. After front/eval.rs, nothing else should look
// at crate directives.
let ENV env_ = fld.update_env_for_crate(env, c);
let ast._mod m = fold_mod[ENV](env_, fld, c.node.module);
ret fld.fold_crate(env_, c.span, m);
ret fld.fold_crate(env_, c.span, c.node.directives, m);
}
//// Identity folds.
@ -1324,6 +1339,11 @@ fn identity_fold_view_item_import[ENV](&ENV e, &span sp, ident i,
ret @respan(sp, ast.view_item_import(i, is, id, target_def));
}
fn identity_fold_view_item_export[ENV](&ENV e, &span sp, ident i)
-> @view_item {
ret @respan(sp, ast.view_item_export(i));
}
// Additional identities.
fn identity_fold_block[ENV](&ENV e, &span sp, &ast.block_ blk) -> block {
@ -1353,8 +1373,10 @@ fn identity_fold_native_mod[ENV](&ENV e,
ret m;
}
fn identity_fold_crate[ENV](&ENV e, &span sp, &ast._mod m) -> @ast.crate {
ret @respan(sp, rec(module=m));
fn identity_fold_crate[ENV](&ENV e, &span sp,
vec[@ast.crate_directive] cdirs,
&ast._mod m) -> @ast.crate {
ret @respan(sp, rec(directives=cdirs, module=m));
}
fn identity_fold_obj[ENV](&ENV e,
@ -1501,13 +1523,15 @@ fn new_identity_fold[ENV]() -> ast_fold[ENV] {
bind identity_fold_view_item_use[ENV](_,_,_,_,_),
fold_view_item_import =
bind identity_fold_view_item_import[ENV](_,_,_,_,_,_),
fold_view_item_export =
bind identity_fold_view_item_export[ENV](_,_,_),
fold_block = bind identity_fold_block[ENV](_,_,_),
fold_fn = bind identity_fold_fn[ENV](_,_,_,_),
fold_fn_decl = bind identity_fold_fn_decl[ENV](_,_,_,_),
fold_mod = bind identity_fold_mod[ENV](_,_),
fold_native_mod = bind identity_fold_native_mod[ENV](_,_),
fold_crate = bind identity_fold_crate[ENV](_,_,_),
fold_crate = bind identity_fold_crate[ENV](_,_,_,_),
fold_obj = bind identity_fold_obj[ENV](_,_,_,_),
update_env_for_crate = bind identity_update_env_for_crate[ENV](_,_),

View file

@ -0,0 +1,29 @@
import std._str;
import front.ast;
import middle.trans;
import back.x86;
import lib.llvm.llvm;
import lib.llvm.llvm.ValueRef;
import lib.llvm.False;
// Returns a Plain Old LLVM String.
fn C_postr(str s) -> ValueRef {
ret llvm.LLVMConstString(_str.buf(s), _str.byte_len(s), False);
}
fn collect_meta_directives(@trans.crate_ctxt cx, @ast.crate crate)
-> ValueRef {
ret C_postr("Hello world!"); // TODO
}
fn write_metadata(@trans.crate_ctxt cx, @ast.crate crate) {
auto llmeta = collect_meta_directives(cx, crate);
auto llconst = trans.C_struct(vec(llmeta));
auto llglobal = llvm.LLVMAddGlobal(cx.llmod, trans.val_ty(llconst),
_str.buf("rust_metadata"));
llvm.LLVMSetInitializer(llglobal, llconst);
llvm.LLVMSetSection(llglobal, _str.buf(x86.get_meta_sect_name()));
}

View file

@ -71,6 +71,13 @@ fn unwrap_def(def_wrap d) -> def {
}
}
}
case (def_wrap_native_mod(?m)) {
alt (m.node) {
case (ast.item_native_mod(_, _, ?id)) {
ret ast.def_native_mod(id);
}
}
}
case (def_wrap_other(?d)) {
ret d;
}
@ -335,6 +342,40 @@ fn lookup_name_wrapped(&env e, ast.ident i) -> option.t[tup(@env, def_wrap)] {
ret none[def_wrap];
}
fn found_tag(@ast.item item, uint variant_idx) -> def_wrap {
alt (item.node) {
case (ast.item_tag(_, ?variants, _, ?tid)) {
auto vid = variants.(variant_idx).id;
auto t = ast.def_variant(tid, vid);
ret def_wrap_other(t);
}
case (_) {
log "tag item not actually a tag";
fail;
}
}
}
fn check_block(ast.ident i, &ast.block_ b) -> option.t[def_wrap] {
alt (b.index.find(i)) {
case (some[ast.block_index_entry](?ix)) {
alt(ix) {
case (ast.bie_item(?it)) {
ret some(found_def_item(it));
}
case (ast.bie_local(?l)) {
auto t = ast.def_local(l.id);
ret some(def_wrap_other(t));
}
case (ast.bie_tag_variant(?item, ?variant_idx)) {
ret some(found_tag(item, variant_idx));
}
}
}
case (_) { ret none[def_wrap]; }
}
}
fn in_scope(ast.ident i, &scope s) -> option.t[def_wrap] {
alt (s) {
@ -361,7 +402,7 @@ fn lookup_name_wrapped(&env e, ast.ident i) -> option.t[tup(@env, def_wrap)] {
}
}
}
case (ast.item_tag(_, _, ?ty_params, _)) {
case (ast.item_tag(_, ?variants, ?ty_params, ?tag_id)) {
for (ast.ty_param tp in ty_params) {
if (_str.eq(tp.ident, i)) {
auto t = ast.def_ty_arg(tp.id);
@ -407,13 +448,7 @@ fn lookup_name_wrapped(&env e, ast.ident i) -> option.t[tup(@env, def_wrap)] {
}
case (scope_block(?b)) {
alt (b.node.index.find(i)) {
case (some[uint](?ix)) {
auto x = found_decl_stmt(b.node.stmts.(ix));
ret some(x);
}
case (_) { /* fall through */ }
}
ret check_block(i, b.node);
}
case (scope_arm(?a)) {

File diff suppressed because it is too large Load diff

View file

@ -81,87 +81,10 @@ tag unify_result {
// Stringification
fn ast_ty_to_str(&@ast.ty ty) -> str {
fn ast_fn_input_to_str(&rec(ast.mode mode, @ast.ty ty) input) -> str {
auto s;
if (mode_is_alias(input.mode)) {
s = "&";
} else {
s = "";
}
ret s + ast_ty_to_str(input.ty);
}
fn ast_ty_field_to_str(&ast.ty_field f) -> str {
ret ast_ty_to_str(f.ty) + " " + f.ident;
}
auto s;
alt (ty.node) {
case (ast.ty_nil) { s = "()"; }
case (ast.ty_bool) { s = "bool"; }
case (ast.ty_int) { s = "int"; }
case (ast.ty_uint) { s = "uint"; }
case (ast.ty_machine(?tm)) { s = common.ty_mach_to_str(tm); }
case (ast.ty_char) { s = "char"; }
case (ast.ty_str) { s = "str"; }
case (ast.ty_box(?t)) { s = "@" + ast_ty_to_str(t); }
case (ast.ty_vec(?t)) { s = "vec[" + ast_ty_to_str(t) + "]"; }
case (ast.ty_type) { s = "type"; }
case (ast.ty_tup(?elts)) {
auto f = ast_ty_to_str;
s = "tup(";
s += _str.connect(_vec.map[@ast.ty,str](f, elts), ",");
s += ")";
}
case (ast.ty_rec(?fields)) {
auto f = ast_ty_field_to_str;
s = "rec(";
s += _str.connect(_vec.map[ast.ty_field,str](f, fields), ",");
s += ")";
}
case (ast.ty_fn(?proto, ?inputs, ?output)) {
auto f = ast_fn_input_to_str;
if (proto == ast.proto_fn) {
s = "fn(";
} else {
s = "iter(";
}
auto is = _vec.map[rec(ast.mode mode, @ast.ty ty),str](f, inputs);
s += _str.connect(is, ", ");
s += ")";
if (output.node != ast.ty_nil) {
s += " -> " + ast_ty_to_str(output);
}
}
case (ast.ty_path(?path, _)) {
s = path_to_str(path);
}
case (ast.ty_mutable(?t)) {
s = "mutable " + ast_ty_to_str(t);
}
case (_) {
fail; // FIXME: typestate bug
}
}
ret s;
}
fn path_to_str(&ast.path pth) -> str {
auto result = _str.connect(pth.node.idents, ".");
if (_vec.len[@ast.ty](pth.node.types) > 0u) {
auto f = ast_ty_to_str;
auto f = pretty.pprust.ty_to_str;
result += "[";
result += _str.connect(_vec.map[@ast.ty,str](f, pth.node.types), ",");
result += "]";
@ -169,8 +92,6 @@ fn path_to_str(&ast.path pth) -> str {
ret result;
}
// FIXME use the pretty-printer for this once it has a concept of an
// abstract stream
fn ty_to_str(&@t typ) -> str {
fn fn_input_to_str(&rec(ast.mode mode, @t ty) input) -> str {
@ -452,6 +373,14 @@ fn get_element_type(@t ty, uint i) -> @t {
fail;
}
fn type_is_box(@t ty) -> bool {
alt (ty.struct) {
case (ty_box(_)) { ret true; }
case (_) { ret false; }
}
fail;
}
fn type_is_boxed(@t ty) -> bool {
alt (ty.struct) {
case (ty_str) { ret true; }
@ -596,10 +525,10 @@ fn eq_ty(&@t a, &@t b) -> bool {
fn ann_to_type(&ast.ann ann) -> @t {
alt (ann) {
case (ast.ann_none) {
// shouldn't happen, but can until the typechecker is complete
ret plain_ty(ty_var(-1)); // FIXME: broken, broken, broken
log "ann_to_type() called on node with no type";
fail;
}
case (ast.ann_type(?ty)) {
case (ast.ann_type(?ty, _)) {
ret ty;
}
}

File diff suppressed because it is too large Load diff

View file

@ -17,17 +17,19 @@ type context = rec(contexttype tp, uint indent);
type ps = @rec(mutable vec[context] context,
uint width,
io.writer out,
mutable vec[token] buffered,
mutable uint scandepth,
mutable uint bufferedcol,
mutable uint col,
mutable bool start_of_line);
fn mkstate(uint width) -> ps {
fn mkstate(io.writer out, uint width) -> ps {
let vec[context] stack = vec(rec(tp=cx_v, indent=0u));
let vec[token] buff = vec();
ret @rec(mutable context=stack,
width=width,
out=out,
mutable buffered=buff,
mutable scandepth=0u,
mutable bufferedcol=0u,
@ -46,10 +48,22 @@ impure fn pop_context(ps p) {
}
impure fn add_token(ps p, token tok) {
if (p.scandepth == 0u) {do_token(p, tok);}
if (p.width == 0u) {direct_token(p, tok);}
else if (p.scandepth == 0u) {do_token(p, tok);}
else {buffer_token(p, tok);}
}
impure fn direct_token(ps p, token tok) {
alt (tok) {
case (brk(?sz)) {
while (sz > 0u) {p.out.write_str(" "); sz -= 1u;}
}
case (word(?w)) {p.out.write_str(w);}
case (cword(?w)) {p.out.write_str(w);}
case (_) {}
}
}
impure fn buffer_token(ps p, token tok) {
p.buffered += vec(tok);
p.bufferedcol += token_size(tok);
@ -101,14 +115,13 @@ impure fn finish_block_scan(ps p, contexttype tp) {
impure fn finish_break_scan(ps p) {
if (p.bufferedcol > p.width) {
write_str("\n");
p.col = 0u;
line_break(p);
}
else {
auto width;
alt (p.buffered.(0)) {case(brk(?w)) {width = w;}}
auto i = 0u;
while (i < width) {write_str(" "); i+=1u;}
while (i < width) {p.out.write_str(" "); i+=1u;}
p.col += width;
}
p.scandepth = 0u;
@ -142,20 +155,18 @@ impure fn do_token(ps p, token tok) {
start_scan(p, tok);
}
case (cx_v) {
write_str("\n");
p.col = 0u;
p.start_of_line = true;
line_break(p);
}
}
}
case (word(?w)) {
before_print(p, false);
write_str(w);
p.out.write_str(w);
p.col += _str.byte_len(w); // TODO char_len
}
case (cword(?w)) {
before_print(p, true);
write_str(w);
p.out.write_str(w);
p.col += _str.byte_len(w); // TODO char_len
}
case (open(?tp, ?indent)) {
@ -170,6 +181,12 @@ impure fn do_token(ps p, token tok) {
}
}
impure fn line_break(ps p) {
p.out.write_str("\n");
p.col = 0u;
p.start_of_line = true;
}
impure fn before_print(ps p, bool closing) {
if (p.start_of_line) {
p.start_of_line = false;
@ -177,14 +194,10 @@ impure fn before_print(ps p, bool closing) {
if (closing) {ind = base_indent(p);}
else {ind = cur_context(p).indent;}
p.col = ind;
while (ind > 0u) {write_str(" "); ind -= 1u;}
while (ind > 0u) {p.out.write_str(" "); ind -= 1u;}
}
}
fn write_str(str s) {
io.writefd(1, _str.bytes(s));
}
fn token_size(token tok) -> uint {
alt (tok) {
case (brk(?sz)) {ret sz;}

View file

@ -11,13 +11,19 @@ import foo = std.io;
const uint indent_unit = 2u;
const int as_prec = 5;
impure fn print_ast(ast._mod _mod) {
auto s = pp.mkstate(80u);
impure fn print_ast(ast._mod _mod, std.io.writer out) {
auto s = pp.mkstate(out, 80u);
for (@ast.view_item vitem in _mod.view_items) {print_view_item(s, vitem);}
line(s);
for (@ast.item item in _mod.items) {print_item(s, item);}
}
fn ty_to_str(&@ast.ty ty) -> str {
auto writer = std.io.string_writer();
print_type(pp.mkstate(writer.get_writer(), 0u), ty);
ret writer.get_str();
}
impure fn hbox(ps s) {
pp.hbox(s, indent_unit);
}
@ -85,24 +91,21 @@ impure fn print_type(ps s, @ast.ty ty) {
commasep[ast.ty_field](s, fields, f);
pclose(s);
}
case (ast.ty_fn(?proto,?inputs,?output)) {
if (proto == ast.proto_fn) {wrd(s, "fn");}
else {wrd(s, "iter");}
popen(s);
impure fn print_arg(ps s, ast.ty_arg input) {
if (middle.ty.mode_is_alias(input.mode)) {wrd(s, "&");}
print_type(s, input.ty);
}
auto f = print_arg;
commasep[ast.ty_arg](s, inputs, f);
pclose(s);
if (output.node != ast.ty_nil) {
space(s);
case (ast.ty_obj(?methods)) {
wrd1(s, "obj");
bopen(s);
for (ast.ty_method m in methods) {
hbox(s);
wrd1(s, "->");
print_type(s, output);
print_ty_fn(s, m.proto, option.some[str](m.ident),
m.inputs, m.output);
wrd(s, ";");
end(s);
line(s);
}
bclose(s);
}
case (ast.ty_fn(?proto,?inputs,?output)) {
print_ty_fn(s, proto, option.none[str], inputs, output);
}
case (ast.ty_path(?path,_)) {
print_path(s, path);
@ -376,6 +379,7 @@ impure fn print_expr(ps s, @ast.expr expr) {
wrd1(s, "else");
print_expr(s, _else);
}
case (_) { /* fall through */ }
}
}
case (ast.expr_while(?test,?block,_)) {
@ -503,8 +507,16 @@ impure fn print_expr(ps s, @ast.expr expr) {
wrd1(s, "check");
print_expr(s, expr);
}
case (_) {wrd(s, "X");}
// TODO expr_ext(path, vec[@expr], option.t[@expr], @expr, ann);
case (ast.expr_ext(?path, ?args, ?body, _, _)) {
wrd(s, "#");
print_path(s, path);
if (_vec.len[@ast.expr](args) > 0u) {
popen(s);
commasep[@ast.expr](s, args, pe);
pclose(s);
}
// TODO: extension 'body'
}
}
end(s);
}
@ -706,3 +718,28 @@ fn escape_str(str st, char to_escape) -> str {
impure fn print_string(ps s, str st) {
wrd(s, "\""); wrd(s, escape_str(st, '"')); wrd(s, "\"");
}
impure fn print_ty_fn(ps s, ast.proto proto, option.t[str] id,
vec[ast.ty_arg] inputs, @ast.ty output) {
if (proto == ast.proto_fn) {wrd(s, "fn");}
else {wrd(s, "iter");}
alt (id) {
case (option.some[str](?id)) {space(s); wrd(s, id);}
case (_) {}
}
popen(s);
impure fn print_arg(ps s, ast.ty_arg input) {
if (middle.ty.mode_is_alias(input.mode)) {wrd(s, "&");}
print_type(s, input.ty);
}
auto f = print_arg;
commasep[ast.ty_arg](s, inputs, f);
pclose(s);
if (output.node != ast.ty_nil) {
space(s);
hbox(s);
wrd1(s, "->");
print_type(s, output);
end(s);
}
}

View file

@ -8,13 +8,13 @@ mod front {
mod extfmt;
mod lexer;
mod parser;
mod pretty;
mod token;
mod eval;
}
mod middle {
mod fold;
mod metadata;
mod resolve;
mod trans;
mod ty;
@ -41,10 +41,12 @@ mod util {
}
auth driver.rustc.main = impure;
auth middle.metadata = unsafe;
auth middle.trans = unsafe;
auth middle.trans.copy_args_to_allocas = impure;
auth middle.trans.trans_block = impure;
auth lib.llvm = unsafe;
auth pretty.pprust = impure;
mod lib {
alt (target_os) {

View file

@ -46,6 +46,10 @@ fn new_str_hash[V]() -> std.map.hashmap[str,V] {
ret std.map.mk_hashmap[str,V](hasher, eqer);
}
fn def_eq(&ast.def_id a, &ast.def_id b) -> bool {
ret a._0 == b._0 && a._1 == b._1;
}
fn new_def_hash[V]() -> std.map.hashmap[ast.def_id,V] {
fn hash(&ast.def_id d) -> uint {
@ -55,12 +59,8 @@ fn new_def_hash[V]() -> std.map.hashmap[ast.def_id,V] {
ret u;
}
fn eq(&ast.def_id a, &ast.def_id b) -> bool {
ret a._0 == b._0 && a._1 == b._1;
}
let std.map.hashfn[ast.def_id] hasher = hash;
let std.map.eqfn[ast.def_id] eqer = eq;
let std.map.eqfn[ast.def_id] eqer = def_eq;
ret std.map.mk_hashmap[ast.def_id,V](hasher, eqer);
}

View file

@ -1,4 +1,3 @@
import std.sys;
fn add(int x, int y) -> int { ret x + y; }
fn sub(int x, int y) -> int { ret x - y; }

View file

@ -1,6 +1,6 @@
import rustrt.sbuf;
import std._vec.rustrt.vbuf;
import _vec.rustrt.vbuf;
native "rust" mod rustrt {
type sbuf;

View file

@ -1,4 +1,3 @@
import std.sys;
fn add(uint x, uint y) -> uint { ret x + y; }
fn sub(uint x, uint y) -> uint { ret x - y; }

View file

@ -1,5 +1,4 @@
import vbuf = rustrt.vbuf;
import std.option;
type operator2[T,U,V] = fn(&T, &U) -> V;

View file

@ -1,7 +1,3 @@
import std._uint;
import std._int;
import std._vec;
// FIXME: With recursive object types, we could implement binary methods like
// union, intersection, and difference. At that point, we could write
// an optimizing version of this module that produces a different obj

View file

@ -5,8 +5,6 @@
* logging.
*/
import std._vec;
// FIXME: handle 64-bit case.
const uint const_refcount = 0x7bad_face_u;

View file

@ -2,10 +2,6 @@
* A deque, for fun. Untested as of yet. Likely buggy.
*/
import std.option;
import std._vec;
import std._int;
type t[T] = obj {
fn size() -> uint;

View file

@ -1,7 +1,4 @@
import std.os.libc;
import std._str;
import std._vec;
import os.libc;
type stdio_reader = state obj {
fn getc() -> int;
@ -91,35 +88,29 @@ tag fileflag {
truncate;
}
fn writefd(int fd, vec[u8] v) {
auto len = _vec.len[u8](v);
auto count = 0u;
auto vbuf;
while (count < len) {
vbuf = _vec.buf_off[u8](v, count);
auto nout = os.libc.write(fd, vbuf, len);
if (nout < 0) {
log "error dumping buffer";
log sys.rustrt.last_os_error();
fail;
state obj fd_buf_writer(int fd, bool must_close) {
fn write(vec[u8] v) {
auto len = _vec.len[u8](v);
auto count = 0u;
auto vbuf;
while (count < len) {
vbuf = _vec.buf_off[u8](v, count);
auto nout = os.libc.write(fd, vbuf, len);
if (nout < 0) {
log "error dumping buffer";
log sys.rustrt.last_os_error();
fail;
}
count += nout as uint;
}
count += nout as uint;
}
drop {
if (must_close) {os.libc.close(fd);}
}
}
fn new_buf_writer(str path, vec[fileflag] flags) -> buf_writer {
state obj fd_buf_writer(int fd) {
fn write(vec[u8] v) {
writefd(fd, v);
}
drop {
os.libc.close(fd);
}
}
fn file_buf_writer(str path, vec[fileflag] flags) -> buf_writer {
let int fflags =
os.libc_constants.O_WRONLY() |
os.libc_constants.O_BINARY();
@ -142,26 +133,58 @@ fn new_buf_writer(str path, vec[fileflag] flags) -> buf_writer {
log sys.rustrt.last_os_error();
fail;
}
ret fd_buf_writer(fd);
ret fd_buf_writer(fd, true);
}
type writer =
state obj {
fn write_str(str s);
fn write_int(int n);
fn write_uint(uint n);
impure fn write_str(str s);
impure fn write_int(int n);
impure fn write_uint(uint n);
};
fn file_writer(str path,
vec[fileflag] flags)
-> writer
{
state obj fw(buf_writer out) {
fn write_str(str s) { out.write(_str.bytes(s)); }
fn write_int(int n) { out.write(_str.bytes(_int.to_str(n, 10u))); }
fn write_uint(uint n) { out.write(_str.bytes(_uint.to_str(n, 10u))); }
state obj new_writer(buf_writer out) {
impure fn write_str(str s) {
out.write(_str.bytes(s));
}
ret fw(new_buf_writer(path, flags));
impure fn write_int(int n) {
out.write(_str.bytes(_int.to_str(n, 10u)));
}
impure fn write_uint(uint n) {
out.write(_str.bytes(_uint.to_str(n, 10u)));
}
}
fn file_writer(str path, vec[fileflag] flags) -> writer {
ret new_writer(file_buf_writer(path, flags));
}
// FIXME it would be great if this could be a const named stdout
fn stdout_writer() -> writer {
ret new_writer(fd_buf_writer(1, false));
}
type str_writer =
state obj {
fn get_writer() -> writer;
fn get_str() -> str;
};
type str_buf = @rec(mutable str buf);
// TODO awkward! it's not possible to implement a writer with an extra method
fn string_writer() -> str_writer {
auto buf = @rec(mutable buf = "");
state obj str_writer_writer(str_buf buf) {
impure fn write_str(str s) { buf.buf += s; }
impure fn write_int(int n) { buf.buf += _int.to_str(n, 10u); }
impure fn write_uint(uint n) { buf.buf += _uint.to_str(n, 10u); }
}
state obj str_writer_wrap(writer wr, str_buf buf) {
fn get_writer() -> writer {ret wr;}
fn get_str() -> str {ret buf.buf;}
}
ret str_writer_wrap(str_writer_writer(buf), buf);
}
//

View file

@ -1,5 +1,3 @@
import std.option;
import option.some;
import option.none;

View file

@ -3,12 +3,6 @@
* use, but useful as a stress test for rustboot.
*/
import std._int;
import std.sys;
import std.option;
import std._vec;
type hashfn[K] = fn(&K) -> uint;
type eqfn[K] = fn(&K, &K) -> bool;

View file

@ -4,9 +4,6 @@
* point this will want to be rewritten.
*/
import std._vec;
import std._str;
export sha1;
export mk_sha1;

55
src/llvmext/Object.cpp Normal file
View file

@ -0,0 +1,55 @@
//===- Object.cpp - C bindings to the object file library--------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the C bindings to the file-format-independent object
// library.
//
//===----------------------------------------------------------------------===//
#include "llvm/Object/ObjectFile.h"
#include "llvm-c/Object.h"
using namespace llvm;
using namespace object;
LLVMObjectFileRef LLVMCreateObjectFile(const char *ObjectPath) {
StringRef SR(ObjectPath);
return wrap(ObjectFile::createObjectFile(SR));
}
void LLVMDisposeObjectFile(LLVMObjectFileRef ObjectFile) {
delete unwrap(ObjectFile);
}
LLVMSectionIteratorRef LLVMGetSections(LLVMObjectFileRef ObjectFile) {
ObjectFile::section_iterator SI = unwrap(ObjectFile)->begin_sections();
return wrap(new ObjectFile::section_iterator(SI));
}
void LLVMDisposeSectionIterator(LLVMSectionIteratorRef SI) {
delete unwrap(SI);
}
void LLVMMoveToNextSection(LLVMSectionIteratorRef SI) {
ObjectFile::section_iterator UnwrappedSI = *unwrap(SI);
++UnwrappedSI;
}
const char *LLVMGetSectionName(LLVMSectionIteratorRef SI) {
return (*unwrap(SI))->getName().data();
}
uint64_t LLVMGetSectionSize(LLVMSectionIteratorRef SI) {
return (*unwrap(SI))->getSize();
}
const char *LLVMGetSectionContents(LLVMSectionIteratorRef SI) {
return (*unwrap(SI))->getContents().data();
}

3
src/llvmext/README Normal file
View file

@ -0,0 +1,3 @@
This directory currently contains some LLVM support code. This will generally
be sent upstream to LLVM in time; for now it lives here.

View file

@ -0,0 +1,75 @@
/*===-- llvm-c/Object.h - Object Lib C Iface --------------------*- C++ -*-===*/
/* */
/* The LLVM Compiler Infrastructure */
/* */
/* This file is distributed under the University of Illinois Open Source */
/* License. See LICENSE.TXT for details. */
/* */
/*===----------------------------------------------------------------------===*/
/* */
/* This header declares the C interface to libLLVMObject.a, which */
/* implements object file reading and writing. */
/* */
/* Many exotic languages can interoperate with C code but have a harder time */
/* with C++ due to name mangling. So in addition to C, this interface enables */
/* tools written in such languages. */
/* */
/*===----------------------------------------------------------------------===*/
#ifndef LLVM_C_OBJECT_H
#define LLVM_C_OBJECT_H
#include "llvm-c/Core.h"
#include "llvm/Config/llvm-config.h"
#ifdef __cplusplus
#include "llvm/Object/ObjectFile.h"
extern "C" {
#endif
typedef struct LLVMOpaqueObjectFile *LLVMObjectFileRef;
typedef struct LLVMOpaqueSectionIterator *LLVMSectionIteratorRef;
LLVMObjectFileRef LLVMCreateObjectFile(const char *ObjectPath);
void LLVMDisposeObjectFile(LLVMObjectFileRef ObjectFile);
LLVMSectionIteratorRef LLVMGetSections(LLVMObjectFileRef ObjectFile);
void LLVMDisposeSectionIterator(LLVMSectionIteratorRef SI);
void LLVMMoveToNextSection(LLVMSectionIteratorRef SI);
const char *LLVMGetSectionName(LLVMSectionIteratorRef SI);
uint64_t LLVMGetSectionSize(LLVMSectionIteratorRef SI);
const char *LLVMGetSectionContents(LLVMSectionIteratorRef SI);
#ifdef __cplusplus
}
namespace llvm {
namespace object {
inline ObjectFile *unwrap(LLVMObjectFileRef OF) {
return reinterpret_cast<ObjectFile*>(OF);
}
inline LLVMObjectFileRef wrap(const ObjectFile *OF) {
return reinterpret_cast<LLVMObjectFileRef>(const_cast<ObjectFile*>(OF));
}
inline ObjectFile::section_iterator *unwrap(LLVMSectionIteratorRef SI) {
return reinterpret_cast<ObjectFile::section_iterator*>(SI);
}
inline LLVMSectionIteratorRef
wrap(const ObjectFile::section_iterator *SI) {
return reinterpret_cast<LLVMSectionIteratorRef>
(const_cast<ObjectFile::section_iterator*>(SI));
}
}
}
#endif /* defined(__cplusplus) */
#endif

View file

@ -0,0 +1,5 @@
fn main() {
check (@1 < @3);
check (@@"hello " > @@"hello");
check (@@@"hello" != @@@"there");
}

View file

@ -0,0 +1,10 @@
fn id[T](&T t) -> T {
ret t;
}
fn main() {
auto t = tup(1,2,3,4,5,6,7);
check (t._5 == 6);
auto f0 = bind id[tup(int,int,int,int,int,int,int)](t);
check (f0()._5 == 6);
}

View file

@ -3,6 +3,8 @@ fn id[T](&T t) -> T {
}
fn main() {
auto f = bind id[int](_);
check (f(10) == 10);
auto t = tup(1,2,3,4,5,6,7);
check (t._5 == 6);
auto f1 = bind id[tup(int,int,int,int,int,int,int)](_);
check (f1(t)._5 == 6);
}

View file

@ -2,7 +2,7 @@ tag foo[T] {
arm(T);
}
fn altfoo[T](foo[T] f) {
fn altfoo[T](&foo[T] f) {
auto hit = false;
alt (f) {
case (arm[T](?x)) {

View file

@ -0,0 +1,8 @@
tag clam[T] {
a(T);
}
fn main() {
auto c = a(3);
}

View file

@ -0,0 +1,9 @@
tag t {
a;
b(@int);
}
fn main() {
auto x = b(@10);
x = a;
}

View file

@ -0,0 +1,15 @@
fn main() {
check ("hello" < "hellr");
check ("hello " > "hello");
check ("hello" != "there");
check (vec(1,2,3,4) > vec(1,2,3));
check (vec(1,2,3) < vec(1,2,3,4));
check (vec(1,2,4,4) > vec(1,2,3,4));
check (vec(1,2,3,4) < vec(1,2,4,4));
check (vec(1,2,3) <= vec(1,2,3));
check (vec(1,2,3) <= vec(1,2,3,3));
check (vec(1,2,3,4) > vec(1,2,3));
check (vec(1,2,3) == vec(1,2,3));
check (vec(1,2,3) != vec(1,1,3));
}

View file

@ -0,0 +1,11 @@
tag clam[T] {
a(T);
}
fn main() {
auto c = a(2);
alt (c) {
case (a[int](_)) {}
}
}

View file

@ -0,0 +1,7 @@
tag clam[T] {
a(T);
}
fn main() {
}