Reformat source tree (minus a couple tests that are still grumpy).

This commit is contained in:
Graydon Hoare 2011-06-15 11:19:50 -07:00
parent 8d381823e2
commit ce72993488
379 changed files with 13643 additions and 18907 deletions

View File

@ -1,101 +1,136 @@
// FIXME: Most of these should be uints.
// FIXME: Most of these should be uints.
const int rc_base_field_refcnt = 0;
// FIXME: import from std::dbg when imported consts work.
const uint const_refcount = 0x7bad_face_u;
const int task_field_refcnt = 0;
const int task_field_stk = 2;
const int task_field_runtime_sp = 3;
const int task_field_rust_sp = 4;
const int task_field_gc_alloc_chain = 5;
const int task_field_dom = 6;
const int n_visible_task_fields = 7;
const int dom_field_interrupt_flag = 1;
const int frame_glue_fns_field_mark = 0;
const int frame_glue_fns_field_drop = 1;
const int frame_glue_fns_field_reloc = 2;
const int box_rc_field_refcnt = 0;
const int box_rc_field_body = 1;
const int general_code_alignment = 16;
const int vec_elt_rc = 0;
const int vec_elt_alloc = 1;
const int vec_elt_fill = 2;
const int vec_elt_pad = 3;
const int vec_elt_data = 4;
const int tydesc_field_first_param = 0;
const int tydesc_field_size = 1;
const int tydesc_field_align = 2;
const int tydesc_field_take_glue = 3;
const int tydesc_field_drop_glue = 4;
const int tydesc_field_free_glue = 5;
const int tydesc_field_sever_glue = 6;
const int tydesc_field_mark_glue = 7;
// FIXME no longer used in rustc, drop when rustboot is gone
const int tydesc_field_obj_drop_glue = 8;
const int tydesc_field_is_stateful = 9;
const int tydesc_field_cmp_glue = 10;
const int n_tydesc_fields = 11;
const uint cmp_glue_op_eq = 0u;
const uint cmp_glue_op_lt = 1u;
const uint cmp_glue_op_le = 2u;
const int obj_field_vtbl = 0;
const int obj_field_box = 1;
const int obj_body_elt_tydesc = 0;
const int obj_body_elt_typarams = 1;
const int obj_body_elt_fields = 2;
const int obj_body_elt_with_obj = 3; /* The base object to which an anonymous
* object is attached */
const int fn_field_code = 0;
const int obj_body_elt_typarams = 1;
const int obj_body_elt_fields = 2;
const int obj_body_elt_with_obj = 3;
/* The base object to which an anonymous
* object is attached */
const int fn_field_code = 0;
const int fn_field_box = 1;
const int closure_elt_tydesc = 0;
const int closure_elt_target = 1;
const int closure_elt_bindings = 2;
const int closure_elt_ty_params = 3;
const uint ivec_default_length = 8u;
const uint ivec_elt_len = 0u;
const uint ivec_elt_alen = 1u;
const uint ivec_elt_elems = 2u;
const uint ivec_heap_stub_elt_zero = 0u;
const uint ivec_heap_stub_elt_alen = 1u;
const uint ivec_heap_stub_elt_ptr = 2u;
const uint ivec_heap_elt_len = 0u;
const uint ivec_heap_elt_elems = 1u;
const uint ivec_elt_alen = 1u;
const uint ivec_elt_elems = 2u;
const uint ivec_heap_stub_elt_zero = 0u;
const uint ivec_heap_stub_elt_alen = 1u;
const uint ivec_heap_stub_elt_ptr = 2u;
const uint ivec_heap_elt_len = 0u;
const uint ivec_heap_elt_elems = 1u;
const int worst_case_glue_call_args = 7;
fn memcpy_glue_name() -> str {
ret "rust_memcpy_glue";
}
fn memcpy_glue_name() -> str { ret "rust_memcpy_glue"; }
fn bzero_glue_name() -> str {
ret "rust_bzero_glue";
}
fn bzero_glue_name() -> str { ret "rust_bzero_glue"; }
fn yield_glue_name() -> str {
ret "rust_yield_glue";
}
fn no_op_type_glue_name() -> str {
ret "rust_no_op_type_glue";
}
fn yield_glue_name() -> str { ret "rust_yield_glue"; }
fn no_op_type_glue_name() -> str { ret "rust_no_op_type_glue"; }
//
// Local Variables:
// mode: rust

View File

@ -1,3 +1,4 @@
import driver::session;
import lib::llvm::llvm;
import middle::trans;
@ -13,7 +14,6 @@ import std::sha1::sha1;
import std::sort;
import trans::crate_ctxt;
import front::ast;
import lib::llvm::llvm::ModuleRef;
import lib::llvm::llvm::ValueRef;
import lib::llvm::mk_pass_manager;
@ -32,11 +32,9 @@ tag output_type {
fn llvm_err(session::session sess, str msg) {
auto buf = llvm::LLVMRustGetLastError();
if ((buf as uint) == 0u) {
if (buf as uint == 0u) {
sess.err(msg);
} else {
sess.err(msg + ": " + str::str_from_cstr(buf));
}
} else { sess.err(msg + ": " + str::str_from_cstr(buf)); }
fail;
}
@ -44,22 +42,18 @@ fn link_intrinsics(session::session sess, ModuleRef llmod) {
auto path = fs::connect(sess.get_opts().sysroot, "intrinsics.bc");
auto membuf =
llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(str::buf(path));
if ((membuf as uint) == 0u) {
if (membuf as uint == 0u) {
llvm_err(sess, "installation problem: couldn't open " + path);
fail;
}
auto llintrinsicsmod = llvm::LLVMRustParseBitcode(membuf);
llvm::LLVMDisposeMemoryBuffer(membuf);
if ((llintrinsicsmod as uint) == 0u) {
if (llintrinsicsmod as uint == 0u) {
llvm_err(sess, "installation problem: couldn't parse intrinsics.bc");
fail;
}
auto linkres = llvm::LLVMLinkModules(llmod, llintrinsicsmod);
llvm::LLVMDisposeModule(llintrinsicsmod);
if (linkres == False) {
llvm_err(sess, "couldn't link the module with the intrinsics");
fail;
@ -68,9 +62,8 @@ fn link_intrinsics(session::session sess, ModuleRef llmod) {
mod write {
fn is_object_or_assembly_or_exe(output_type ot) -> bool {
if ( (ot == output_type_assembly) ||
(ot == output_type_object) ||
(ot == output_type_exe) ) {
if (ot == output_type_assembly || ot == output_type_object ||
ot == output_type_exe) {
ret true;
}
ret false;
@ -83,39 +76,30 @@ mod write {
auto stem;
if (dot_pos < 0) {
stem = output_path;
} else {
stem = str::substr(output_path, 0u, dot_pos as uint);
}
} else { stem = str::substr(output_path, 0u, dot_pos as uint); }
ret stem + "." + extension;
}
fn run_passes(session::session sess, ModuleRef llmod, str output) {
auto opts = sess.get_opts();
if (opts.time_llvm_passes) {
llvm::LLVMRustEnableTimePasses();
}
if (opts.time_llvm_passes) { llvm::LLVMRustEnableTimePasses(); }
link_intrinsics(sess, llmod);
auto pm = mk_pass_manager();
auto td = mk_target_data(x86::get_data_layout());
llvm::LLVMAddTargetData(td.lltd, pm.llpm);
// TODO: run the linter here also, once there are llvm-c bindings for
// it.
// Generate a pre-optimization intermediate file if -save-temps was
// specified.
if (opts.save_temps) {
alt (opts.output_type) {
case (output_type_bitcode) {
if (opts.optimize != 0u) {
auto filename = mk_intermediate_name(output,
"no-opt.bc");
auto filename =
mk_intermediate_name(output, "no-opt.bc");
llvm::LLVMWriteBitcodeToFile(llmod,
str::buf(filename));
str::buf(filename));
}
}
case (_) {
@ -124,109 +108,95 @@ mod write {
}
}
}
if (opts.verify) {
llvm::LLVMAddVerifierPass(pm.llpm);
}
if (opts.verify) { llvm::LLVMAddVerifierPass(pm.llpm); }
// FIXME: This is mostly a copy of the bits of opt's -O2 that are
// available in the C api.
// FIXME2: We might want to add optimization levels like -O1, -O2,
// -Os, etc
// FIXME3: Should we expose and use the pass lists used by the opt
// tool?
if (opts.optimize != 0u) {
auto fpm = mk_pass_manager();
llvm::LLVMAddTargetData(td.lltd, fpm.llpm);
llvm::LLVMAddStandardFunctionPasses(fpm.llpm, 2u);
llvm::LLVMRunPassManager(fpm.llpm, llmod);
let uint threshold = 225u;
if (opts.optimize == 3u) {
threshold = 275u;
}
if (opts.optimize == 3u) { threshold = 275u; }
llvm::LLVMAddStandardModulePasses(pm.llpm,
// optimization level
opts.optimize,
False, // optimize for size
True, // unit-at-a-time
True, // unroll loops
True, // simplify lib calls
threshold); // inline threshold
}
True, // unit-at-a-time
True, // unroll loops
True, // simplify lib calls
threshold); // inline threshold
if (opts.verify) {
llvm::LLVMAddVerifierPass(pm.llpm);
}
if (opts.verify) { llvm::LLVMAddVerifierPass(pm.llpm); }
if (is_object_or_assembly_or_exe(opts.output_type)) {
let int LLVMAssemblyFile = 0;
let int LLVMObjectFile = 1;
let int LLVMNullFile = 2;
auto FileType;
if ((opts.output_type == output_type_object) ||
(opts.output_type == output_type_exe)) {
if (opts.output_type == output_type_object ||
opts.output_type == output_type_exe) {
FileType = LLVMObjectFile;
} else {
FileType = LLVMAssemblyFile;
}
} else { FileType = LLVMAssemblyFile; }
// Write optimized bitcode if --save-temps was on.
if (opts.save_temps) {
if (opts.save_temps) {
// Always output the bitcode file with --save-temps
auto filename = mk_intermediate_name(output, "opt.bc");
llvm::LLVMRunPassManager(pm.llpm, llmod);
llvm::LLVMWriteBitcodeToFile(llmod, str::buf(filename));
pm = mk_pass_manager();
// Save the assembly file if -S is used
if (opts.output_type == output_type_assembly) {
llvm::LLVMRustWriteOutputFile(pm.llpm, llmod,
str::buf(x86::get_target_triple()),
str::buf(output), LLVMAssemblyFile);
auto triple = x86::get_target_triple();
llvm::LLVMRustWriteOutputFile(pm.llpm, llmod,
str::buf(triple),
str::buf(output),
LLVMAssemblyFile);
}
// Save the object file for -c or --save-temps alone
// This .o is needed when an exe is built
if ((opts.output_type == output_type_object) ||
(opts.output_type == output_type_exe)) {
llvm::LLVMRustWriteOutputFile(pm.llpm, llmod,
str::buf(x86::get_target_triple()),
str::buf(output), LLVMObjectFile);
}
if (opts.output_type == output_type_object ||
opts.output_type == output_type_exe) {
auto triple = x86::get_target_triple();
llvm::LLVMRustWriteOutputFile(pm.llpm, llmod,
str::buf(triple),
str::buf(output),
LLVMObjectFile);
}
} else {
// If we aren't saving temps then just output the file
// type corresponding to the '-c' or '-S' flag used
auto triple = x86::get_target_triple();
llvm::LLVMRustWriteOutputFile(pm.llpm, llmod,
str::buf(x86::get_target_triple()),
str::buf(output),
FileType);
str::buf(triple),
str::buf(output), FileType);
}
// Clean up and return
llvm::LLVMDisposeModule(llmod);
if (opts.time_llvm_passes) {
llvm::LLVMRustPrintPassTimings();
}
if (opts.time_llvm_passes) { llvm::LLVMRustPrintPassTimings(); }
ret;
}
// If only a bitcode file is asked for by using the '--emit-llvm'
// flag, then output it here
llvm::LLVMRunPassManager(pm.llpm, llmod);
llvm::LLVMRunPassManager(pm.llpm, llmod);
llvm::LLVMWriteBitcodeToFile(llmod, str::buf(output));
llvm::LLVMDisposeModule(llmod);
if (opts.time_llvm_passes) {
llvm::LLVMRustPrintPassTimings();
}
if (opts.time_llvm_passes) { llvm::LLVMRustPrintPassTimings(); }
}
}
/*
* Name mangling and its relationship to metadata. This is complex. Read
* carefully.
@ -277,81 +247,63 @@ mod write {
* system linkers understand.
*
*/
iter crate_export_metas(&ast::crate c) -> @ast::meta_item {
for (@ast::crate_directive cdir in c.node.directives) {
alt (cdir.node) {
case (ast::cdir_meta(?v, ?mis)) {
if (v == ast::export_meta) {
for (@ast::meta_item mi in mis) {
put mi;
}
for (@ast::meta_item mi in mis) { put mi; }
}
}
case (_) {}
case (_) { }
}
}
}
iter crate_local_metas(&ast::crate c) -> @ast::meta_item {
for (@ast::crate_directive cdir in c.node.directives) {
alt (cdir.node) {
case (ast::cdir_meta(?v, ?mis)) {
if (v == ast::local_meta) {
for (@ast::meta_item mi in mis) {
put mi;
}
for (@ast::meta_item mi in mis) { put mi; }
}
}
case (_) {}
case (_) { }
}
}
}
fn get_crate_meta_export(&session::session sess,
&ast::crate c, str k, str default,
bool warn_default) -> str {
fn get_crate_meta_export(&session::session sess, &ast::crate c, str k,
str default, bool warn_default) -> str {
let vec[@ast::meta_item] v = [];
for each (@ast::meta_item mi in crate_export_metas(c)) {
if (mi.node.key == k) {
v += [mi];
}
if (mi.node.key == k) { v += [mi]; }
}
alt (vec::len(v)) {
case (0u) {
if (warn_default) {
sess.warn(#fmt("missing meta '%s', using '%s' as default",
k, default));
sess.warn(#fmt("missing meta '%s', using '%s' as default", k,
default));
}
ret default;
}
case (1u) {
ret v.(0).node.value;
}
case (1u) { ret v.(0).node.value; }
case (_) {
sess.span_err(v.(1).span, #fmt("duplicate meta '%s'", k));
}
}
}
// This calculates CMH as defined above
fn crate_meta_extras_hash(sha1 sha, &ast::crate crate) -> str {
fn lteq(&@ast::meta_item ma,
&@ast::meta_item mb) -> bool {
fn lteq(&@ast::meta_item ma, &@ast::meta_item mb) -> bool {
ret ma.node.key <= mb.node.key;
}
fn len_and_str(&str s) -> str {
ret #fmt("%u_%s", str::byte_len(s), s);
}
let vec[mutable @ast::meta_item] v = [mutable];
fn len_and_str(&str s) -> str { ret #fmt("%u_%s", str::byte_len(s), s); }
let vec[mutable @ast::meta_item] v = [mutable ];
for each (@ast::meta_item mi in crate_export_metas(crate)) {
if (mi.node.key != "name" &&
mi.node.key != "vers") {
if (mi.node.key != "name" && mi.node.key != "vers") {
v += [mutable mi];
}
}
@ -365,10 +317,10 @@ fn crate_meta_extras_hash(sha1 sha, &ast::crate crate) -> str {
ret truncated_sha1_result(sha);
}
fn crate_meta_name(&session::session sess, &ast::crate crate,
&str output) -> str {
fn crate_meta_name(&session::session sess, &ast::crate crate, &str output) ->
str {
auto os = str::split(fs::basename(output), '.' as u8);
assert vec::len(os) >= 2u;
assert (vec::len(os) >= 2u);
vec::pop(os);
ret get_crate_meta_export(sess, crate, "name", str::connect(os, "."),
sess.get_opts().shared);
@ -384,15 +336,16 @@ fn truncated_sha1_result(sha1 sha) -> str {
}
// This calculates STH for a symbol, as defined above
fn symbol_hash(ty::ctxt tcx, sha1 sha, &ty::t t,
str crate_meta_name,
fn symbol_hash(ty::ctxt tcx, sha1 sha, &ty::t t, str crate_meta_name,
str crate_meta_extras_hash) -> str {
// NB: do *not* use abbrevs here as we want the symbol names
// to be independent of one another in the crate.
auto cx = @rec(ds=metadata::def_to_str, tcx=tcx,
abbrevs=metadata::ac_no_abbrevs);
auto cx =
@rec(ds=metadata::def_to_str,
tcx=tcx,
abbrevs=metadata::ac_no_abbrevs);
sha.reset();
sha.input_str(crate_meta_name);
sha.input_str("-");
@ -401,6 +354,7 @@ fn symbol_hash(ty::ctxt tcx, sha1 sha, &ty::t t,
sha.input_str(metadata::Encode::ty_str(cx, t));
auto hash = truncated_sha1_result(sha);
// Prefix with _ so that it never blends into adjacent digits
ret "_" + hash;
}
@ -409,54 +363,49 @@ fn get_symbol_hash(&@crate_ctxt ccx, &ty::t t) -> str {
alt (ccx.type_sha1s.find(t)) {
case (some(?h)) { hash = h; }
case (none) {
hash = symbol_hash(ccx.tcx, ccx.sha, t,
ccx.crate_meta_name,
ccx.crate_meta_extras_hash);
hash =
symbol_hash(ccx.tcx, ccx.sha, t, ccx.crate_meta_name,
ccx.crate_meta_extras_hash);
ccx.type_sha1s.insert(t, hash);
}
}
ret hash;
}
fn mangle(&vec[str] ss) -> str {
// Follow C++ namespace-mangling style
auto n = "_ZN"; // Begin name-sequence.
for (str s in ss) {
n += #fmt("%u%s", str::byte_len(s), s);
}
for (str s in ss) { n += #fmt("%u%s", str::byte_len(s), s); }
n += "E"; // End name-sequence.
ret n;
}
fn exported_name(&vec[str] path, &str hash, &str vers) -> str {
// FIXME: versioning isn't working yet
ret mangle(path + [hash]); // + "@" + vers;
}
fn mangle_exported_name(&@crate_ctxt ccx, &vec[str] path,
&ty::t t) -> str {
fn mangle_exported_name(&@crate_ctxt ccx, &vec[str] path, &ty::t t) -> str {
auto hash = get_symbol_hash(ccx, t);
ret exported_name(path, hash, ccx.crate_meta_vers);
}
fn mangle_internal_name_by_type_only(&@crate_ctxt ccx, &ty::t t,
&str name) -> str {
fn mangle_internal_name_by_type_only(&@crate_ctxt ccx, &ty::t t, &str name) ->
str {
auto f = metadata::def_to_str;
auto cx = @rec(ds=f, tcx=ccx.tcx, abbrevs=metadata::ac_no_abbrevs);
auto s = pretty::ppaux::ty_to_short_str(ccx.tcx, t);
auto hash = get_symbol_hash(ccx, t);
ret mangle([name, s, hash]);
}
fn mangle_internal_name_by_path_and_seq(&@crate_ctxt ccx, &vec[str] path,
&str flav) -> str {
&str flav) -> str {
ret mangle(path + [ccx.names.next(flav)]);
}
@ -467,7 +416,6 @@ fn mangle_internal_name_by_path(&@crate_ctxt ccx, &vec[str] path) -> str {
fn mangle_internal_name_by_seq(&@crate_ctxt ccx, &str flav) -> str {
ret ccx.names.next(flav);
}
//
// Local Variables:
// mode: rust

View File

@ -1,7 +1,6 @@
import middle::trans;
import trans::decl_cdecl_fn;
import trans::T_f32;
import trans::T_f64;
import trans::T_fn;
@ -20,49 +19,47 @@ import trans::T_str;
import trans::T_taskptr;
import trans::T_tydesc;
import trans::T_void;
import lib::llvm::type_names;
import lib::llvm::llvm::ModuleRef;
import lib::llvm::llvm::ValueRef;
import lib::llvm::llvm::TypeRef;
type upcalls = rec(
ValueRef grow_task,
ValueRef log_int,
ValueRef log_float,
ValueRef log_double,
ValueRef log_str,
ValueRef trace_word,
ValueRef trace_str,
ValueRef new_port,
ValueRef del_port,
ValueRef new_chan,
ValueRef flush_chan,
ValueRef del_chan,
ValueRef clone_chan,
ValueRef _yield,
ValueRef sleep,
ValueRef _join,
ValueRef send,
ValueRef recv,
ValueRef _fail,
ValueRef kill,
ValueRef exit,
ValueRef malloc,
ValueRef free,
ValueRef mark,
ValueRef new_str,
ValueRef new_vec,
ValueRef vec_grow,
ValueRef vec_append,
ValueRef get_type_desc,
ValueRef new_task,
ValueRef start_task,
ValueRef new_thread,
ValueRef start_thread,
ValueRef ivec_resize,
ValueRef ivec_spill
);
type upcalls =
rec(ValueRef grow_task,
ValueRef log_int,
ValueRef log_float,
ValueRef log_double,
ValueRef log_str,
ValueRef trace_word,
ValueRef trace_str,
ValueRef new_port,
ValueRef del_port,
ValueRef new_chan,
ValueRef flush_chan,
ValueRef del_chan,
ValueRef clone_chan,
ValueRef _yield,
ValueRef sleep,
ValueRef _join,
ValueRef send,
ValueRef recv,
ValueRef _fail,
ValueRef kill,
ValueRef exit,
ValueRef malloc,
ValueRef free,
ValueRef mark,
ValueRef new_str,
ValueRef new_vec,
ValueRef vec_grow,
ValueRef vec_append,
ValueRef get_type_desc,
ValueRef new_task,
ValueRef start_task,
ValueRef new_thread,
ValueRef start_thread,
ValueRef ivec_resize,
ValueRef ivec_spill);
fn declare_upcalls(type_names tn, ModuleRef llmod) -> @upcalls {
fn decl(type_names tn, ModuleRef llmod, str name, vec[TypeRef] tys,
@ -72,69 +69,67 @@ fn declare_upcalls(type_names tn, ModuleRef llmod) -> @upcalls {
auto fn_ty = T_fn(arg_tys, rv);
ret trans::decl_cdecl_fn(llmod, "upcall_" + name, fn_ty);
}
auto dv = bind decl(tn, llmod, _, _, T_void());
auto d = bind decl(tn, llmod, _, _, _);
// FIXME: Sigh:.. remove this when I fix the typechecker pushdown.
// --pcwalton
let vec[TypeRef] empty_vec = [];
ret @rec(
grow_task=dv("grow_task", [T_size_t()]),
log_int=dv("log_int", [T_i32(), T_i32()]),
log_float=dv("log_float", [T_i32(), T_f32()]),
log_double=dv("log_double", [T_i32(), T_ptr(T_f64())]),
log_str=dv("log_str", [T_i32(), T_ptr(T_str())]),
trace_word=dv("trace_word", [T_int()]),
trace_str=dv("trace_str", [T_ptr(T_i8())]),
new_port=d("new_port", [T_size_t()], T_opaque_port_ptr()),
del_port=dv("del_port", [T_opaque_port_ptr()]),
new_chan=d("new_chan", [T_opaque_port_ptr()], T_opaque_chan_ptr()),
flush_chan=dv("flush_chan", [T_opaque_chan_ptr()]),
del_chan=dv("del_chan", [T_opaque_chan_ptr()]),
clone_chan=d("clone_chan", [T_taskptr(tn), T_opaque_chan_ptr()],
T_opaque_chan_ptr()),
_yield=dv("yield", empty_vec),
sleep=dv("sleep", [T_size_t()]),
_join=dv("join", [T_taskptr(tn)]),
send=dv("send", [T_opaque_chan_ptr(), T_ptr(T_i8())]),
recv=dv("recv", [T_ptr(T_ptr(T_i8())), T_opaque_port_ptr()]),
_fail=dv("fail", [T_ptr(T_i8()), T_ptr(T_i8()), T_size_t()]),
kill=dv("kill", [T_taskptr(tn)]),
exit=dv("exit", empty_vec),
malloc=d("malloc", [T_size_t(), T_ptr(T_tydesc(tn))],
T_ptr(T_i8())),
free=dv("free", [T_ptr(T_i8()), T_int()]),
mark=d("mark", [T_ptr(T_i8())], T_int()),
new_str=d("new_str", [T_ptr(T_i8()), T_size_t()], T_ptr(T_str())),
new_vec=d("new_vec", [T_size_t(), T_ptr(T_tydesc(tn))],
T_opaque_vec_ptr()),
vec_grow=d("vec_grow", [T_opaque_vec_ptr(), T_size_t(),
T_ptr(T_int()), T_ptr(T_tydesc(tn))],
T_opaque_vec_ptr()),
vec_append=d("vec_append", [T_ptr(T_tydesc(tn)), T_ptr(T_tydesc(tn)),
T_ptr(T_opaque_vec_ptr()),
T_opaque_vec_ptr(), T_bool()], T_void()),
get_type_desc=d("get_type_desc",
[T_ptr(T_nil()), T_size_t(), T_size_t(),
T_size_t(), T_ptr(T_ptr(T_tydesc(tn)))],
T_ptr(T_tydesc(tn))),
new_task=d("new_task", [T_ptr(T_str())], T_taskptr(tn)),
start_task=d("start_task", [T_taskptr(tn),
T_int(), T_int(), T_size_t()],
T_taskptr(tn)),
new_thread=d("new_thread", [T_ptr(T_i8())], T_taskptr(tn)),
start_thread=d("start_thread", [T_taskptr(tn), T_int(), T_int(),
T_int(), T_size_t()],
T_taskptr(tn)),
ivec_resize=d("ivec_resize", [T_ptr(T_opaque_ivec()), T_int()],
T_void()),
ivec_spill=d("ivec_spill", [T_ptr(T_opaque_ivec()), T_int()],
T_void())
);
ret @rec(grow_task=dv("grow_task", [T_size_t()]),
log_int=dv("log_int", [T_i32(), T_i32()]),
log_float=dv("log_float", [T_i32(), T_f32()]),
log_double=dv("log_double", [T_i32(), T_ptr(T_f64())]),
log_str=dv("log_str", [T_i32(), T_ptr(T_str())]),
trace_word=dv("trace_word", [T_int()]),
trace_str=dv("trace_str", [T_ptr(T_i8())]),
new_port=d("new_port", [T_size_t()], T_opaque_port_ptr()),
del_port=dv("del_port", [T_opaque_port_ptr()]),
new_chan=d("new_chan", [T_opaque_port_ptr()],
T_opaque_chan_ptr()),
flush_chan=dv("flush_chan", [T_opaque_chan_ptr()]),
del_chan=dv("del_chan", [T_opaque_chan_ptr()]),
clone_chan=d("clone_chan", [T_taskptr(tn), T_opaque_chan_ptr()],
T_opaque_chan_ptr()),
_yield=dv("yield", empty_vec),
sleep=dv("sleep", [T_size_t()]),
_join=dv("join", [T_taskptr(tn)]),
send=dv("send", [T_opaque_chan_ptr(), T_ptr(T_i8())]),
recv=dv("recv", [T_ptr(T_ptr(T_i8())), T_opaque_port_ptr()]),
_fail=dv("fail", [T_ptr(T_i8()), T_ptr(T_i8()), T_size_t()]),
kill=dv("kill", [T_taskptr(tn)]),
exit=dv("exit", empty_vec),
malloc=d("malloc", [T_size_t(), T_ptr(T_tydesc(tn))],
T_ptr(T_i8())),
free=dv("free", [T_ptr(T_i8()), T_int()]),
mark=d("mark", [T_ptr(T_i8())], T_int()),
new_str=d("new_str", [T_ptr(T_i8()), T_size_t()],
T_ptr(T_str())),
new_vec=d("new_vec", [T_size_t(), T_ptr(T_tydesc(tn))],
T_opaque_vec_ptr()),
vec_grow=d("vec_grow",
[T_opaque_vec_ptr(), T_size_t(), T_ptr(T_int()),
T_ptr(T_tydesc(tn))], T_opaque_vec_ptr()),
vec_append=d("vec_append",
[T_ptr(T_tydesc(tn)), T_ptr(T_tydesc(tn)),
T_ptr(T_opaque_vec_ptr()), T_opaque_vec_ptr(),
T_bool()], T_void()),
get_type_desc=d("get_type_desc",
[T_ptr(T_nil()), T_size_t(), T_size_t(),
T_size_t(), T_ptr(T_ptr(T_tydesc(tn)))],
T_ptr(T_tydesc(tn))),
new_task=d("new_task", [T_ptr(T_str())], T_taskptr(tn)),
start_task=d("start_task",
[T_taskptr(tn), T_int(), T_int(), T_size_t()],
T_taskptr(tn)),
new_thread=d("new_thread", [T_ptr(T_i8())], T_taskptr(tn)),
start_thread=d("start_thread",
[T_taskptr(tn), T_int(), T_int(), T_int(),
T_size_t()], T_taskptr(tn)),
ivec_resize=d("ivec_resize", [T_ptr(T_opaque_ivec()), T_int()],
T_void()),
ivec_spill=d("ivec_spill", [T_ptr(T_opaque_ivec()), T_int()],
T_void()));
}
//
// Local Variables:
// mode: rust

View File

@ -1,3 +1,4 @@
import lib::llvm::llvm;
import lib::llvm::llvm::ModuleRef;
import std::str;
@ -5,43 +6,33 @@ import std::vec;
import std::os::target_os;
import util::common::istr;
fn get_module_asm() -> str {
ret "";
}
fn get_module_asm() -> str { ret ""; }
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";
}
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:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64" +
"-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" +
"-n8:16:32";
ret "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16"
+ "-i32:32:32-i64:32:64"
+ "-f32:32:32-f64:32:64-v64:64:64"
+ "-v128:128:128-a0:0:64-f80:128:128"
+ "-n8:16:32";
}
if (str::eq(target_os(), "win32")) {
ret "e-p:32:32-f64:64:64-i64:64:64-f80:32:32-n8:16:32";
ret "e-p:32:32-f64:64:64-i64:64:64-f80:32:32-n8:16:32";
}
ret "e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32";
}
fn get_target_triple() -> str {
if (str::eq(target_os(), "macos")) {
ret "i686-apple-darwin";
}
if (str::eq(target_os(), "win32")) {
ret "i686-pc-mingw32";
}
if (str::eq(target_os(), "macos")) { ret "i686-apple-darwin"; }
if (str::eq(target_os(), "win32")) { ret "i686-pc-mingw32"; }
ret "i686-unknown-linux-gnu";
}
//
// Local Variables:
// mode: rust

View File

@ -1,5 +1,6 @@
// -*- rust -*-
// -*- rust -*-
import front::creader;
import front::parser;
import front::token;
@ -15,7 +16,6 @@ import pretty::ppaux;
import back::link;
import lib::llvm;
import util::common;
import std::fs;
import std::map::mk_hashmap;
import std::option;
@ -25,99 +25,78 @@ import std::str;
import std::vec;
import std::io;
import std::run;
import std::getopts;
import std::getopts::optopt;
import std::getopts::optmulti;
import std::getopts::optflag;
import std::getopts::optflagopt;
import std::getopts::opt_present;
import back::link::output_type;
tag pp_mode {
ppm_normal;
ppm_typed;
ppm_identified;
}
tag pp_mode { ppm_normal; ppm_typed; ppm_identified; }
fn default_environment(session::session sess,
str argv0,
str input) -> eval::env {
auto libc = alt (sess.get_targ_cfg().os) {
case (session::os_win32) { "msvcrt.dll" }
case (session::os_macos) { "libc.dylib" }
case (session::os_linux) { "libc.so.6" }
case (_) { "libc.so" }
};
ret [// Target bindings.
fn default_environment(session::session sess, str argv0, str input) ->
eval::env {
auto libc =
alt (sess.get_targ_cfg().os) {
case (session::os_win32) { "msvcrt.dll" }
case (session::os_macos) { "libc.dylib" }
case (session::os_linux) { "libc.so.6" }
case (_) { "libc.so" }
};
ret [ // Target bindings.
tup("target_os", eval::val_str(std::os::target_os())),
tup("target_arch", eval::val_str("x86")),
tup("target_libc", eval::val_str(libc)),
// Build bindings.
tup("build_compiler", eval::val_str(argv0)),
tup("build_input", eval::val_str(input))
];
tup("build_input", eval::val_str(input))];
}
fn parse_input(session::session sess,
parser::parser p,
str input) -> @ast::crate {
fn parse_input(session::session sess, parser::parser p, str input) ->
@ast::crate {
ret if (str::ends_with(input, ".rc")) {
parser::parse_crate_from_crate_file(p)
} else if (str::ends_with(input, ".rs")) {
parser::parse_crate_from_source_file(p)
} else {
sess.err("unknown input file type: " + input);
fail
};
parser::parse_crate_from_crate_file(p)
} else if (str::ends_with(input, ".rs")) {
parser::parse_crate_from_source_file(p)
} else { sess.err("unknown input file type: " + input); fail };
}
fn time[T](bool do_it, str what, fn()->T thunk) -> T {
fn time[T](bool do_it, str what, fn() -> T thunk) -> T {
if (!do_it) { ret thunk(); }
auto start = std::time::get_time();
auto rv = thunk();
auto end = std::time::get_time();
// FIXME: Actually do timeval math.
log_err #fmt("time: %s took %u s", what, (end.sec - start.sec) as uint);
log_err #fmt("time: %s took %u s", what, end.sec - start.sec as uint);
ret rv;
}
fn compile_input(session::session sess,
eval::env env,
str input, str output) {
fn compile_input(session::session sess, eval::env env, str input,
str output) {
auto time_passes = sess.get_opts().time_passes;
auto def = tup(ast::local_crate, 0);
auto p = parser::new_parser(sess, env, def, input, 0u, 0u);
auto crate = time(time_passes, "parsing",
bind parse_input(sess, p, input));
if (sess.get_opts().output_type == link::output_type_none) {ret;}
auto def_map = time(time_passes, "resolution",
bind resolve::resolve_crate(sess, crate));
auto crate =
time(time_passes, "parsing", bind parse_input(sess, p, input));
if (sess.get_opts().output_type == link::output_type_none) { ret; }
auto def_map =
time(time_passes, "resolution",
bind resolve::resolve_crate(sess, crate));
auto ty_cx = ty::mk_ctxt(sess, def_map);
time[()](time_passes, "typechecking",
bind typeck::check_crate(ty_cx, crate));
if (sess.get_opts().run_typestate) {
time(time_passes, "typestate checking",
bind middle::tstate::ck::check_crate(ty_cx, crate));
}
time(time_passes, "alias checking",
bind middle::alias::check_crate(@ty_cx, def_map, crate));
auto llmod =
time[llvm::llvm::ModuleRef](time_passes, "translation",
bind trans::trans_crate(sess, crate,
ty_cx, output));
time[()](time_passes, "LLVM passes",
bind link::write::run_passes(sess, llmod, output));
}
@ -127,7 +106,6 @@ fn pretty_print_input(session::session sess, eval::env env, str input,
auto def = tup(ast::local_crate, 0);
auto p = front::parser::new_parser(sess, env, def, input, 0u, 0u);
auto crate = parse_input(sess, p, input);
auto mode;
alt (ppm) {
case (ppm_typed) {
@ -139,7 +117,6 @@ fn pretty_print_input(session::session sess, eval::env env, str input,
case (ppm_normal) { mode = ppaux::mo_untyped; }
case (ppm_identified) { mode = ppaux::mo_identified; }
}
pprust::print_file(sess, crate.node.module, input, std::io::stdout(),
mode);
}
@ -147,14 +124,13 @@ fn pretty_print_input(session::session sess, eval::env env, str input,
fn version(str argv0) {
auto vers = "unknown version";
auto env_vers = #env("CFG_VERSION");
if (str::byte_len(env_vers) != 0u) {
vers = env_vers;
}
if (str::byte_len(env_vers) != 0u) { vers = env_vers; }
io::stdout().write_str(#fmt("%s %s\n", argv0, vers));
}
fn usage(str argv0) {
io::stdout().write_str(#fmt("usage: %s [options] <input>\n", argv0) + "
io::stdout().write_str(#fmt("usage: %s [options] <input>\n", argv0) +
"
options:
-h --help display this message
@ -185,35 +161,27 @@ options:
fn get_os(str triple) -> session::os {
ret if (str::find(triple, "win32") >= 0 ||
str::find(triple, "mingw32") >= 0 ) {
session::os_win32
} else if (str::find(triple, "darwin") >= 0) {
session::os_macos
} else if (str::find(triple, "linux") >= 0) {
session::os_linux
} else {
log_err "Unknown operating system!";
fail
};
str::find(triple, "mingw32") >= 0) {
session::os_win32
} else if (str::find(triple, "darwin") >= 0) {
session::os_macos
} else if (str::find(triple, "linux") >= 0) {
session::os_linux
} else { log_err "Unknown operating system!"; fail };
}
fn get_arch(str triple) -> session::arch {
ret if (str::find(triple, "i386") >= 0 ||
str::find(triple, "i486") >= 0 ||
str::find(triple, "i586") >= 0 ||
str::find(triple, "i686") >= 0 ||
str::find(triple, "i786") >= 0 ) {
session::arch_x86
} else if (str::find(triple, "x86_64") >= 0) {
session::arch_x64
} else if (str::find(triple, "arm") >= 0 ||
str::find(triple, "xscale") >= 0 ) {
session::arch_arm
}
else {
log_err ("Unknown architecture! " + triple);
fail
};
ret if (str::find(triple, "i386") >= 0 || str::find(triple, "i486") >= 0
|| str::find(triple, "i586") >= 0 ||
str::find(triple, "i686") >= 0 ||
str::find(triple, "i786") >= 0) {
session::arch_x86
} else if (str::find(triple, "x86_64") >= 0) {
session::arch_x64
} else if (str::find(triple, "arm") >= 0 ||
str::find(triple, "xscale") >= 0) {
session::arch_arm
} else { log_err "Unknown architecture! " + triple; fail };
}
fn get_default_sysroot(str binary) -> str {
@ -225,34 +193,29 @@ fn get_default_sysroot(str binary) -> str {
fn build_target_config() -> @session::config {
let str triple =
std::str::rustrt::str_from_cstr(llvm::llvm::LLVMRustGetHostTriple());
let @session::config target_cfg =
@rec(os = get_os(triple),
arch = get_arch(triple),
int_type = common::ty_i32,
uint_type = common::ty_u32,
float_type = common::ty_f64);
@rec(os=get_os(triple),
arch=get_arch(triple),
int_type=common::ty_i32,
uint_type=common::ty_u32,
float_type=common::ty_f64);
ret target_cfg;
}
fn build_session_options(str binary, getopts::match match)
-> @session::options {
fn build_session_options(str binary, getopts::match match) ->
@session::options {
auto shared = opt_present(match, "shared");
auto library_search_paths = getopts::opt_strs(match, "L");
auto output_type = if (opt_present(match, "parse-only")) {
link::output_type_none
} else if (opt_present(match, "S")) {
link::output_type_assembly
} else if (opt_present(match, "c")) {
link::output_type_object
} else if (opt_present(match, "emit-llvm")) {
link::output_type_bitcode
} else {
link::output_type_exe
};
auto output_type =
if (opt_present(match, "parse-only")) {
link::output_type_none
} else if (opt_present(match, "S")) {
link::output_type_assembly
} else if (opt_present(match, "c")) {
link::output_type_object
} else if (opt_present(match, "emit-llvm")) {
link::output_type_bitcode
} else { link::output_type_exe };
auto verify = !opt_present(match, "noverify");
auto save_temps = opt_present(match, "save-temps");
auto debuginfo = opt_present(match, "g");
@ -261,47 +224,44 @@ fn build_session_options(str binary, getopts::match match)
auto time_llvm_passes = opt_present(match, "time-llvm-passes");
auto run_typestate = !opt_present(match, "no-typestate");
auto sysroot_opt = getopts::opt_maybe_str(match, "sysroot");
let uint opt_level = if (opt_present(match, "O")) {
if (opt_present(match, "OptLevel")) {
log_err "error: -O and --OptLevel both provided";
fail;
}
2u
} else if (opt_present(match, "OptLevel")) {
alt (getopts::opt_str(match, "OptLevel")) {
case ("0") { 0u }
case ("1") { 1u }
case ("2") { 2u }
case ("3") { 3u }
case (_) {
log_err "error: optimization level needs to be between 0-3";
fail
let uint opt_level =
if (opt_present(match, "O")) {
if (opt_present(match, "OptLevel")) {
log_err "error: -O and --OptLevel both provided";
fail;
}
}
} else {
0u
};
auto sysroot = alt (sysroot_opt) {
case (none) { get_default_sysroot(binary) }
case (some(?s)) { s }
};
2u
} else if (opt_present(match, "OptLevel")) {
alt (getopts::opt_str(match, "OptLevel")) {
case ("0") { 0u }
case ("1") { 1u }
case ("2") { 2u }
case ("3") { 3u }
case (_) {
log_err "error: optimization level needs " +
"to be between 0-3";
fail
}
}
} else { 0u };
auto sysroot =
alt (sysroot_opt) {
case (none) { get_default_sysroot(binary) }
case (some(?s)) { s }
};
let @session::options sopts =
@rec(shared = shared,
optimize = opt_level,
debuginfo = debuginfo,
verify = verify,
run_typestate = run_typestate,
save_temps = save_temps,
stats = stats,
time_passes = time_passes,
time_llvm_passes = time_llvm_passes,
output_type = output_type,
library_search_paths = library_search_paths,
sysroot = sysroot);
@rec(shared=shared,
optimize=opt_level,
debuginfo=debuginfo,
verify=verify,
run_typestate=run_typestate,
save_temps=save_temps,
stats=stats,
time_passes=time_passes,
time_llvm_passes=time_llvm_passes,
output_type=output_type,
library_search_paths=library_search_paths,
sysroot=sysroot);
ret sopts;
}
@ -311,61 +271,51 @@ fn build_session(@session::options sopts) -> session::session {
auto target_crate_num = 0;
let vec[@ast::meta_item] md = [];
auto sess =
session::session(target_crate_num, target_cfg, sopts,
crate_cache, md, front::codemap::new_codemap());
session::session(target_crate_num, target_cfg, sopts, crate_cache, md,
front::codemap::new_codemap());
ret sess;
}
fn parse_pretty(session::session sess, &str name) -> pp_mode {
if (str::eq(name, "normal")) { ret ppm_normal; }
else if (str::eq(name, "typed")) { ret ppm_typed; }
else if (str::eq(name, "identified")) { ret ppm_identified; }
if (str::eq(name, "normal")) {
ret ppm_normal;
} else if (str::eq(name, "typed")) {
ret ppm_typed;
} else if (str::eq(name, "identified")) { ret ppm_identified; }
sess.err("argument to `pretty` must be one of `normal`, `typed`, or " +
"`identified`");
"`identified`");
}
fn main(vec[str] args) {
auto opts = [optflag("h"), optflag("help"),
optflag("v"), optflag("version"),
optflag("glue"), optflag("emit-llvm"),
optflagopt("pretty"),
optflag("ls"), optflag("parse-only"),
optflag("O"), optopt("OptLevel"),
optflag("shared"), optmulti("L"),
optflag("S"), optflag("c"), optopt("o"), optflag("g"),
optflag("save-temps"), optopt("sysroot"),
optflag("stats"),
optflag("time-passes"), optflag("time-llvm-passes"),
optflag("no-typestate"), optflag("noverify")];
auto opts =
[optflag("h"), optflag("help"), optflag("v"), optflag("version"),
optflag("glue"), optflag("emit-llvm"), optflagopt("pretty"),
optflag("ls"), optflag("parse-only"), optflag("O"),
optopt("OptLevel"), optflag("shared"), optmulti("L"), optflag("S"),
optflag("c"), optopt("o"), optflag("g"), optflag("save-temps"),
optopt("sysroot"), optflag("stats"), optflag("time-passes"),
optflag("time-llvm-passes"), optflag("no-typestate"),
optflag("noverify")];
auto binary = vec::shift[str](args);
auto match = alt (getopts::getopts(args, opts)) {
case (getopts::success(?m)) { m }
case (getopts::failure(?f)) {
log_err #fmt("error: %s", getopts::fail_str(f));
fail
}
};
if (opt_present(match, "h") ||
opt_present(match, "help")) {
auto match =
alt (getopts::getopts(args, opts)) {
case (getopts::success(?m)) { m }
case (getopts::failure(?f)) {
log_err #fmt("error: %s", getopts::fail_str(f));
fail
}
};
if (opt_present(match, "h") || opt_present(match, "help")) {
usage(binary);
ret;
}
if (opt_present(match, "v") ||
opt_present(match, "version")) {
if (opt_present(match, "v") || opt_present(match, "version")) {
version(binary);
ret;
}
auto sopts = build_session_options(binary, match);
auto sess = build_session(sopts);
auto n_inputs = vec::len[str](match.free);
auto output_file = getopts::opt_maybe_str(match, "o");
auto glue = opt_present(match, "glue");
if (glue) {
@ -376,33 +326,30 @@ fn main(vec[str] args) {
middle::trans::make_common_glue(sess, out);
ret;
}
if (n_inputs == 0u) {
sess.err("No input filename given.");
} else if (n_inputs > 1u) {
sess.err("Multiple input filenames provided.");
}
auto ifile = match.free.(0);
let str saved_out_filename = "";
auto env = default_environment(sess, binary, ifile);
auto pretty = option::map[str,pp_mode](bind parse_pretty(sess, _),
getopts::opt_default(match, "pretty", "normal"));
auto pretty =
option::map[str,
pp_mode](bind parse_pretty(sess, _),
getopts::opt_default(match, "pretty", "normal"));
auto ls = opt_present(match, "ls");
alt (pretty) {
case (some[pp_mode](?ppm)) {
pretty_print_input(sess, env, ifile, ppm);
ret;
}
case (none[pp_mode]) { /* continue */ }
case (none[pp_mode]) {/* continue */ }
}
if (ls) {
front::creader::list_file_metadata(ifile, std::io::stdout());
ret;
}
alt (output_file) {
case (none) {
let vec[str] parts = str::split(ifile, '.' as u8);
@ -412,9 +359,11 @@ fn main(vec[str] args) {
case (link::output_type_none) { parts += ["pp"]; }
case (link::output_type_bitcode) { parts += ["bc"]; }
case (link::output_type_assembly) { parts += ["s"]; }
// Object and exe output both use the '.o' extension here
case (link::output_type_object) { parts += ["o"]; }
case (
// Object and exe output both use the '.o' extension here
link::output_type_object) {
parts += ["o"];
}
case (link::output_type_exe) { parts += ["o"]; }
}
auto ofile = str::connect(parts, ".");
@ -422,18 +371,17 @@ fn main(vec[str] args) {
}
case (some(?ofile)) {
// FIXME: what about windows? This will create a foo.exe.o.
saved_out_filename = ofile;
auto temp_filename;
alt (sopts.output_type) {
case (link::output_type_exe) {
// FIXME: what about shared?
temp_filename = ofile + ".o";
}
case (_) {
temp_filename = ofile;
}
case (_) { temp_filename = ofile; }
}
compile_input(sess, env, ifile, temp_filename);
}
}
@ -449,41 +397,42 @@ fn main(vec[str] args) {
let str stage = "-L" + binary_dir;
let vec[str] gcc_args;
let str prog = "gcc";
// The invocations of gcc share some flags across platforms
let vec[str] common_cflags = ["-fno-strict-aliasing", "-fPIC",
"-Wall", "-fno-rtti", "-fno-exceptions", "-g"];
let vec[str] common_libs = [stage, "-Lrustllvm", "-Lrt",
"-lrustrt", "-lrustllvm", "-lstd", "-lm"];
let vec[str] common_cflags =
["-fno-strict-aliasing", "-fPIC", "-Wall", "-fno-rtti",
"-fno-exceptions", "-g"];
let vec[str] common_libs =
[stage, "-Lrustllvm", "-Lrt", "-lrustrt", "-lrustllvm", "-lstd",
"-lm"];
alt (sess.get_targ_cfg().os) {
case (session::os_win32) {
gcc_args = common_cflags + [
"-march=i686", "-O2",
glu, main, "-o",
saved_out_filename,
saved_out_filename + ".o"] + common_libs;
gcc_args =
common_cflags +
["-march=i686", "-O2", glu, main, "-o",
saved_out_filename, saved_out_filename + ".o"] +
common_libs;
}
case (session::os_macos) {
gcc_args = common_cflags + [
"-arch i386", "-O0", "-m32",
glu, main, "-o",
saved_out_filename,
saved_out_filename + ".o"] + common_libs;
gcc_args =
common_cflags +
["-arch i386", "-O0", "-m32", glu, main, "-o",
saved_out_filename, saved_out_filename + ".o"] +
common_libs;
}
case (session::os_linux) {
gcc_args = common_cflags + [
"-march=i686", "-O2", "-m32",
glu, main, "-o",
saved_out_filename,
saved_out_filename + ".o"] + common_libs;
gcc_args =
common_cflags +
["-march=i686", "-O2", "-m32", glu, main, "-o",
saved_out_filename, saved_out_filename + ".o"] +
common_libs;
}
}
// We run 'gcc' here
run::run_program(prog, gcc_args);
run::run_program(prog, gcc_args);
// Clean up on Darwin
if (sess.get_targ_cfg().os == session::os_macos) {
run::run_program("dsymutil", [saved_out_filename]);
}
@ -494,7 +443,6 @@ fn main(vec[str] args) {
}
}
}
// Local Variables:
// mode: rust
// fill-column: 78;

View File

@ -1,3 +1,4 @@
import front::ast;
import front::codemap;
import util::common::span;
@ -10,163 +11,112 @@ import std::option;
import std::option::some;
import std::option::none;
tag os {
os_win32;
os_macos;
os_linux;
}
tag os { os_win32; os_macos; os_linux; }
tag arch {
arch_x86;
arch_x64;
arch_arm;
}
tag arch { arch_x86; arch_x64; arch_arm; }
type config = rec(os os,
arch arch,
ty_mach int_type,
ty_mach uint_type,
ty_mach float_type);
type config =
rec(os os,
arch arch,
ty_mach int_type,
ty_mach uint_type,
ty_mach float_type);
type options = rec(bool shared,
uint optimize,
bool debuginfo,
bool verify,
bool run_typestate,
bool save_temps,
bool stats,
bool time_passes,
bool time_llvm_passes,
back::link::output_type output_type,
vec[str] library_search_paths,
str sysroot);
type options =
rec(bool shared,
uint optimize,
bool debuginfo,
bool verify,
bool run_typestate,
bool save_temps,
bool stats,
bool time_passes,
bool time_llvm_passes,
back::link::output_type output_type,
vec[str] library_search_paths,
str sysroot);
type crate_metadata = rec(str name,
vec[u8] data);
type crate_metadata = rec(str name, vec[u8] data);
fn span_to_str(span sp, codemap::codemap cm) -> str {
auto lo = codemap::lookup_pos(cm, sp.lo);
auto hi = codemap::lookup_pos(cm, sp.hi);
ret (#fmt("%s:%u:%u:%u:%u", lo.filename, lo.line,
lo.col, hi.line, hi.col));
ret #fmt("%s:%u:%u:%u:%u", lo.filename, lo.line, lo.col, hi.line, hi.col);
}
fn emit_diagnostic(option::t[span] sp, str msg, str kind, u8 color,
codemap::codemap cm) {
auto ss = "<input>:0:0:0:0";
alt (sp) {
case (some(?ssp)) {
ss = span_to_str(ssp, cm);
}
case (none) {}
case (some(?ssp)) { ss = span_to_str(ssp, cm); }
case (none) { }
}
io::stdout().write_str(ss + ": ");
if (term::color_supported()) {
term::fg(io::stdout().get_buf_writer(), color);
}
io::stdout().write_str(#fmt("%s:", kind));
if (term::color_supported()) {
term::reset(io::stdout().get_buf_writer());
}
io::stdout().write_str(#fmt(" %s\n", msg));
}
state obj session(ast::crate_num cnum,
@config targ_cfg, @options opts,
map::hashmap[int, crate_metadata] crates,
mutable vec[@ast::meta_item] metadata,
codemap::codemap cm) {
fn get_targ_cfg() -> @config {
ret targ_cfg;
}
fn get_opts() -> @options {
ret opts;
}
fn get_targ_crate_num() -> ast::crate_num {
ret cnum;
}
obj session(ast::crate_num cnum,
@config targ_cfg,
@options opts,
map::hashmap[int, crate_metadata] crates,
mutable vec[@ast::meta_item] metadata,
codemap::codemap cm) {
fn get_targ_cfg() -> @config { ret targ_cfg; }
fn get_opts() -> @options { ret opts; }
fn get_targ_crate_num() -> ast::crate_num { ret cnum; }
fn span_err(span sp, str msg) -> ! {
// FIXME: Use constants, but rustboot doesn't know how to export them.
emit_diagnostic(some(sp), msg, "error", 9u8, cm);
fail;
}
fn err(str msg) -> ! {
emit_diagnostic(none[span], msg, "error", 9u8, cm);
fail;
}
fn add_metadata(vec[@ast::meta_item] data) {
metadata = metadata + data;
}
fn get_metadata() -> vec[@ast::meta_item] {
ret metadata;
}
fn add_metadata(vec[@ast::meta_item] data) { metadata = metadata + data; }
fn get_metadata() -> vec[@ast::meta_item] { ret metadata; }
fn span_warn(span sp, str msg) {
// FIXME: Use constants, but rustboot doesn't know how to export them.
emit_diagnostic(some(sp), msg, "warning", 11u8, cm);
}
fn warn(str msg) {
emit_diagnostic(none[span], msg, "warning", 11u8, cm);
}
fn span_note(span sp, str msg) {
// FIXME: Use constants, but rustboot doesn't know how to export them.
emit_diagnostic(some(sp), msg, "note", 10u8, cm);
}
fn span_bug(span sp, str msg) -> ! {
self.span_err(sp, #fmt("internal compiler error %s", msg));
}
fn bug(str msg) -> ! {
self.err(#fmt("internal compiler error %s", msg));
}
fn span_unimpl(span sp, str msg) -> ! {
self.span_bug(sp, "unimplemented " + msg);
}
fn unimpl(str msg) -> ! {
self.bug("unimplemented " + msg);
}
fn get_external_crate(int num) -> crate_metadata {
ret crates.get(num);
}
fn unimpl(str msg) -> ! { self.bug("unimplemented " + msg); }
fn get_external_crate(int num) -> crate_metadata { ret crates.get(num); }
fn set_external_crate(int num, &crate_metadata metadata) {
crates.insert(num, metadata);
}
fn has_external_crate(int num) -> bool {
ret crates.contains_key(num);
}
fn get_codemap() -> codemap::codemap {
ret cm;
}
fn has_external_crate(int num) -> bool { ret crates.contains_key(num); }
fn get_codemap() -> codemap::codemap { ret cm; }
fn lookup_pos(uint pos) -> codemap::loc {
ret codemap::lookup_pos(cm, pos);
}
fn span_str(span sp) -> str {
ret span_to_str(sp, self.get_codemap());
}
fn span_str(span sp) -> str { ret span_to_str(sp, self.get_codemap()); }
}
// Local Variables:
// fill-column: 78;
// indent-tabs-mode: nil

View File

@ -1,3 +1,4 @@
import std::option;
import std::str;
import std::vec;
@ -9,15 +10,17 @@ import util::common::filename;
type ident = str;
type path_ = rec(vec[ident] idents, vec[@ty] types);
type path = spanned[path_];
fn path_name(&path p) -> str {
ret str::connect(p.node.idents, "::");
}
fn path_name(&path p) -> str { ret str::connect(p.node.idents, "::"); }
type crate_num = int;
const crate_num local_crate = 0;
type def_num = int;
type def_id = tup(crate_num, def_num);
type ty_param = ident;
@ -33,7 +36,9 @@ tag def {
def_const(def_id);
def_arg(def_id);
def_local(def_id);
def_variant(def_id /* tag */, def_id /* variant */);
def_variant(def_id, /* tag */def_id);
/* variant */
def_ty(def_id);
def_ty_arg(uint);
def_binding(def_id);
@ -44,9 +49,7 @@ tag def {
fn variant_def_ids(&def d) -> tup(def_id, def_id) {
alt (d) {
case (def_variant(?tag_id, ?var_id)) {
ret tup(tag_id, var_id);
}
case (def_variant(?tag_id, ?var_id)) { ret tup(tag_id, var_id); }
}
}
@ -72,16 +75,14 @@ fn def_id_of_def(def d) -> def_id {
}
type crate = spanned[crate_];
type crate_ = rec(vec[@crate_directive] directives,
_mod module);
tag meta_visibility {
export_meta;
local_meta;
}
type crate_ = rec(vec[@crate_directive] directives, _mod module);
tag meta_visibility { export_meta; local_meta; }
tag crate_directive_ {
cdir_expr(@expr);
// FIXME: cdir_let should be eliminated
// and redirected to the use of const stmt_decls inside
// crate directive blocks.
@ -93,18 +94,19 @@ tag crate_directive_ {
cdir_syntax(path);
cdir_auth(path, _auth);
}
type crate_directive = spanned[crate_directive_];
type meta_item = spanned[meta_item_];
type meta_item_ = rec(ident key, str value);
type block = spanned[block_];
type block_ = rec(vec[@stmt] stmts,
option::t[@expr] expr,
ann a);
type block_ = rec(vec[@stmt] stmts, option::t[@expr] expr, ann a);
type pat = spanned[pat_];
tag pat_ {
pat_wild(ann);
pat_bind(ident, def_id, ann);
@ -112,26 +114,13 @@ tag pat_ {
pat_tag(path, vec[@pat], ann);
}
tag mutability {
mut;
imm;
maybe_mut;
}
tag mutability { mut; imm; maybe_mut; }
tag layer {
layer_value;
layer_state;
layer_gc;
}
tag layer { layer_value; layer_state; layer_gc; }
tag _auth {
auth_unsafe;
}
tag _auth { auth_unsafe; }
tag proto {
proto_iter;
proto_fn;
}
tag proto { proto_iter; proto_fn; }
tag binop {
add;
@ -157,102 +146,85 @@ tag binop {
fn binop_to_str(binop op) -> str {
alt (op) {
case (add) {ret "+";}
case (sub) {ret "-";}
case (mul) {ret "*";}
case (div) {ret "/";}
case (rem) {ret "%";}
case (and) {ret "&&";}
case (or) {ret "||";}
case (bitxor) {ret "^";}
case (bitand) {ret "&";}
case (bitor) {ret "|";}
case (lsl) {ret "<<";}
case (lsr) {ret ">>";}
case (asr) {ret ">>>";}
case (eq) {ret "==";}
case (lt) {ret "<";}
case (le) {ret "<=";}
case (ne) {ret "!=";}
case (ge) {ret ">=";}
case (gt) {ret ">";}
case (add) { ret "+"; }
case (sub) { ret "-"; }
case (mul) { ret "*"; }
case (div) { ret "/"; }
case (rem) { ret "%"; }
case (and) { ret "&&"; }
case (or) { ret "||"; }
case (bitxor) { ret "^"; }
case (bitand) { ret "&"; }
case (bitor) { ret "|"; }
case (lsl) { ret "<<"; }
case (lsr) { ret ">>"; }
case (asr) { ret ">>>"; }
case (eq) { ret "=="; }
case (lt) { ret "<"; }
case (le) { ret "<="; }
case (ne) { ret "!="; }
case (ge) { ret ">="; }
case (gt) { ret ">"; }
}
}
tag unop {
box(mutability);
deref;
not;
neg;
}
tag unop { box(mutability); deref; not; neg; }
fn unop_to_str(unop op) -> str {
alt (op) {
case (box(?mt)) {
if (mt == mut) { ret "@mutable "; }
ret "@";
}
case (deref) {ret "*";}
case (not) {ret "!";}
case (neg) {ret "-";}
case (box(?mt)) { if (mt == mut) { ret "@mutable "; } ret "@"; }
case (deref) { ret "*"; }
case (not) { ret "!"; }
case (neg) { ret "-"; }
}
}
tag mode {
val;
alias(bool);
}
tag mode { val; alias(bool); }
type stmt = spanned[stmt_];
tag stmt_ {
stmt_decl(@decl, ann);
stmt_decl(@decl, ann);
stmt_expr(@expr, ann);
// These only exist in crate-level blocks.
stmt_crate_directive(@crate_directive);
}
tag init_op {
init_assign;
init_recv;
init_move;
}
tag init_op { init_assign; init_recv; init_move; }
type initializer = rec(init_op op,
@expr expr);
type initializer = rec(init_op op, @expr expr);
type local_ =
rec(option::t[@ty] ty,
bool infer,
ident ident,
option::t[initializer] init,
def_id id,
ann ann);
type local_ = rec(option::t[@ty] ty,
bool infer,
ident ident,
option::t[initializer] init,
def_id id,
ann ann);
type local = spanned[@local_];
type decl = spanned[decl_];
tag decl_ {
decl_local(@local_);
decl_item(@item);
}
tag decl_ { decl_local(@local_); decl_item(@item); }
type arm = rec(@pat pat, block block);
type elt = rec(mutability mut, @expr expr);
type field_ = rec(mutability mut, ident ident, @expr expr);
type field = spanned[field_];
tag spawn_dom {
dom_implicit;
dom_thread;
}
tag spawn_dom { dom_implicit; dom_thread; }
// FIXME: temporary
tag seq_kind {
sk_unique;
sk_rc;
}
tag seq_kind { sk_unique; sk_rc; }
type expr = spanned[expr_];
tag expr_ {
expr_vec(vec[@expr], mutability, seq_kind, ann);
expr_tup(vec[elt], ann);
@ -273,11 +245,11 @@ tag expr_ {
expr_alt(@expr, vec[arm], ann);
expr_fn(_fn, ann);
expr_block(block, ann);
expr_move(@expr /* TODO: @expr|is_lval */, @expr, ann);
expr_assign(@expr /* TODO: @expr|is_lval */, @expr, ann);
expr_assign_op(binop, @expr /* TODO: @expr|is_lval */, @expr, ann);
expr_send(@expr /* TODO: @expr|is_lval */, @expr, ann);
expr_recv(@expr /* TODO: @expr|is_lval */, @expr, ann);
expr_move(@expr, /* TODO: @expr|is_lval */@expr, ann);
expr_assign(@expr, /* TODO: @expr|is_lval */@expr, ann);
expr_assign_op(binop, @expr, /* TODO: @expr|is_lval */@expr, ann);
expr_send(@expr, /* TODO: @expr|is_lval */@expr, ann);
expr_recv(@expr, /* TODO: @expr|is_lval */@expr, ann);
expr_field(@expr, ident, ann);
expr_index(@expr, @expr, ann);
expr_path(path, ann);
@ -289,9 +261,11 @@ tag expr_ {
expr_put(option::t[@expr], ann);
expr_be(@expr, ann);
expr_log(int, @expr, ann);
/* just an assert, no significance to typestate */
/* just an assert, no significance to typestate */
expr_assert(@expr, ann);
/* preds that typestate is aware of */
/* preds that typestate is aware of */
expr_check(@expr, ann);
expr_port(ann);
expr_chan(@expr, ann);
@ -299,6 +273,7 @@ tag expr_ {
}
type lit = spanned[lit_];
tag lit_ {
lit_str(str, seq_kind);
lit_char(char);
@ -311,39 +286,53 @@ tag lit_ {
lit_bool(bool);
}
// NB: If you change this, you'll probably want to change the corresponding
// type structure in middle/ty.rs as well.
type mt = rec(@ty ty, mutability mut);
type ty_field_ = rec(ident ident, mt mt);
type ty_arg_ = rec(mode mode, @ty ty);
type ty_method_ = rec(proto proto, ident ident,
vec[ty_arg] inputs, @ty output,
controlflow cf, vec[@constr] constrs);
type ty_method_ =
rec(proto proto,
ident ident,
vec[ty_arg] inputs,
@ty output,
controlflow cf,
vec[@constr] constrs);
type ty_field = spanned[ty_field_];
type ty_arg = spanned[ty_arg_];
type ty_method = spanned[ty_method_];
type ty = spanned[ty_];
tag ty_ {
ty_nil;
ty_bot; /* return type of ! functions and type of
ret/fail/break/cont. there is no syntax
for this type. */
/* bot represents the value of functions that don't return a value
locally to their context. in contrast, things like log that do
return, but don't return a meaningful value, have result type nil. */
ty_bool;
/* bot represents the value of functions that don't return a value
locally to their context. in contrast, things like log that do
return, but don't return a meaningful value, have result type nil. */
ty_bool;
ty_int;
ty_uint;
ty_float;
ty_machine(util::common::ty_mach);
ty_char;
ty_str;
ty_istr; // interior string
ty_istr; // interior string
ty_box(mt);
ty_vec(mt);
ty_ivec(mt); // interior vector
ty_ivec(mt); // interior vector
ty_ptr(mt);
ty_task;
ty_port(@ty);
@ -357,6 +346,7 @@ tag ty_ {
ty_constr(@ty, vec[@constr]);
}
/*
A constraint arg that's a function argument is referred to by its position
rather than name. This is so we could have higher-order functions that have
@ -365,62 +355,69 @@ so that the typestate pass doesn't have to map a function name onto its decl.
So, the constr_arg type is parameterized: it's instantiated with uint for
declarations, and ident for uses.
*/
tag constr_arg_general_[T] {
carg_base;
carg_ident(T);
carg_lit(@lit);
}
tag constr_arg_general_[T] { carg_base; carg_ident(T); carg_lit(@lit); }
type constr_arg = constr_arg_general[uint];
type constr_arg_use = constr_arg_general[ident];
type constr_arg_general[T] = spanned[constr_arg_general_[T]];
// The ann field is there so that using the def_map in the type
// context, we can get the def_id for the path.
type constr_general[T] = rec(path path,
vec[@constr_arg_general[T]] args,
ann ann);
type constr_general[T] =
rec(path path, vec[@constr_arg_general[T]] args, ann ann);
type constr = spanned[constr_general[uint]];
type constr_use = spanned[constr_general[ident]];
type arg = rec(mode mode, @ty ty, ident ident, def_id id);
type fn_decl = rec(vec[arg] inputs,
@ty output,
purity purity,
controlflow cf,
vec[@constr] constraints);
type fn_decl =
rec(vec[arg] inputs,
@ty output,
purity purity,
controlflow cf,
vec[@constr] constraints);
tag purity {
pure_fn; // declared with "pred"
pure_fn; // declared with "pred"
impure_fn; // declared with "fn"
}
tag controlflow {
noreturn; // functions with return type _|_ that always
// raise an error or exit (i.e. never return to the caller)
return; // everything else
return; // everything else
}
type _fn = rec(fn_decl decl,
proto proto,
block body);
type _fn = rec(fn_decl decl, proto proto, block body);
type method_ = rec(ident ident, _fn meth, def_id id, ann ann);
type method = spanned[method_];
type obj_field = rec(mutability mut, @ty ty, ident ident, def_id id, ann ann);
type _obj = rec(vec[obj_field] fields,
vec[@method] methods,
option::t[@method] dtor);
type anon_obj = rec(
// New fields and methods, if they exist.
option::t[vec[obj_field]] fields,
vec[@method] methods,
// with_obj: the original object being extended, if it exists.
option::t[@expr] with_obj);
type _obj =
rec(vec[obj_field] fields, vec[@method] methods, option::t[@method] dtor);
type _mod = rec(vec[@view_item] view_items,
vec[@item] items);
type anon_obj =
rec(
// New fields and methods, if they exist.
option::t[vec[obj_field]] fields,
vec[@method] methods,
// with_obj: the original object being extended, if it exists.
option::t[@expr] with_obj);
type _mod = rec(vec[@view_item] view_items, vec[@item] items);
tag native_abi {
native_abi_rust;
@ -429,16 +426,20 @@ tag native_abi {
native_abi_rust_intrinsic;
}
type native_mod = rec(str native_name,
native_abi abi,
vec[@view_item] view_items,
vec[@native_item] items);
type native_mod =
rec(str native_name,
native_abi abi,
vec[@view_item] view_items,
vec[@native_item] items);
type variant_arg = rec(@ty ty, def_id id);
type variant_ = rec(str name, vec[variant_arg] args, def_id id, ann ann);
type variant = spanned[variant_];
type view_item = spanned[view_item_];
tag view_item_ {
view_item_use(ident, vec[@meta_item], def_id, ann);
view_item_import(ident, vec[ident], def_id);
@ -452,18 +453,16 @@ type obj_def_ids = rec(def_id ty, def_id ctor);
// Meta-data associated with an item
type attribute = spanned[attribute_];
// Distinguishes between attributes that decorate items and attributes that
// are contained as statements within items. These two cases need to be
// distinguished for pretty-printing.
tag attr_style {
attr_outer;
attr_inner;
}
tag attr_style { attr_outer; attr_inner; }
type attribute_ = rec(attr_style style,
meta_item value);
type attribute_ = rec(attr_style style, meta_item value);
type item = spanned[item_];
tag item_ {
item_const(ident, @ty, @expr, vec[attribute], def_id, ann);
item_fn(ident, _fn, vec[ty_param], vec[attribute], def_id, ann);
@ -476,97 +475,79 @@ tag item_ {
fn item_ident(@item it) -> ident {
ret alt (it.node) {
case (item_const(?ident, _, _, _, _, _)) { ident }
case (item_fn(?ident, _, _, _, _, _)) { ident }
case (item_mod(?ident, _, _, _)) { ident }
case (item_native_mod(?ident, _, _, _)) { ident }
case (item_ty(?ident, _, _, _, _, _)) { ident }
case (item_tag(?ident, _, _, _, _, _)) { ident }
case (item_obj(?ident, _, _, _, _, _)) { ident }
}
case (item_const(?ident, _, _, _, _, _)) { ident }
case (item_fn(?ident, _, _, _, _, _)) { ident }
case (item_mod(?ident, _, _, _)) { ident }
case (item_native_mod(?ident, _, _, _)) { ident }
case (item_ty(?ident, _, _, _, _, _)) { ident }
case (item_tag(?ident, _, _, _, _, _)) { ident }
case (item_obj(?ident, _, _, _, _, _)) { ident }
}
}
type native_item = spanned[native_item_];
tag native_item_ {
native_item_ty(ident, def_id);
native_item_fn(ident, option::t[str],
fn_decl, vec[ty_param], def_id, ann);
native_item_fn(ident,
option::t[str],
fn_decl,
vec[ty_param],
def_id,
ann);
}
fn is_exported(ident i, _mod m) -> bool {
auto nonlocal = true;
for (@ast::item it in m.items) {
if (item_ident(it) == i) {
nonlocal = false;
}
if (item_ident(it) == i) { nonlocal = false; }
alt (it.node) {
case (item_tag(_, ?variants, _, _, _, _)) {
for (variant v in variants) {
if (v.node.name == i) {
nonlocal = false;
}
if (v.node.name == i) { nonlocal = false; }
}
}
case (_) {}
case (_) { }
}
}
auto count = 0u;
for (@ast::view_item vi in m.view_items) {
alt (vi.node) {
case (ast::view_item_export(?id)) {
if (str::eq(i, id)) {
// even if it's nonlocal (since it's explicit)
ret true;
}
count += 1u;
}
case (_) { /* fall through */ }
case (_) {/* fall through */ }
}
}
// If there are no declared exports then
// everything not imported is exported
if (count == 0u && !nonlocal) {
ret true;
} else {
ret false;
}
if (count == 0u && !nonlocal) { ret true; } else { ret false; }
}
fn is_call_expr(@expr e) -> bool {
alt (e.node) {
case (expr_call(_, _, _)) {
ret true;
}
case (_) {
ret false;
}
case (expr_call(_, _, _)) { ret true; }
case (_) { ret false; }
}
}
fn is_constraint_arg(@expr e) -> bool {
alt (e.node) {
case (expr_lit(_,_)) {
ret true;
}
case (expr_path(_, _)) {
ret true;
}
case (_) {
ret false;
}
case (expr_lit(_, _)) { ret true; }
case (expr_path(_, _)) { ret true; }
case (_) { ret false; }
}
}
fn eq_ty(&@ty a, &@ty b) -> bool {
ret std::box::ptr_eq(a,b);
}
fn hash_ty(&@ty t) -> uint {
ret t.span.lo << 16u + t.span.hi;
}
fn eq_ty(&@ty a, &@ty b) -> bool { ret std::box::ptr_eq(a, b); }
fn hash_ty(&@ty t) -> uint { ret t.span.lo << 16u + t.span.hi; }
//
// Local Variables:
// mode: rust

View File

@ -1,15 +1,16 @@
import std::vec;
/* A codemap is a thing that maps uints to file/line/column positions
* in a crate. This to make it possible to represent the positions
* with single-word things, rather than passing records all over the
* compiler.
*/
type filemap = @rec(str name, uint start_pos, mutable vec[uint] lines);
type filemap = @rec(str name,
uint start_pos,
mutable vec[uint] lines);
type codemap = @rec(mutable vec[filemap] files);
type loc = rec(str filename, uint line, uint col);
fn new_codemap() -> codemap {
@ -18,34 +19,27 @@ fn new_codemap() -> codemap {
}
fn new_filemap(str filename, uint start_pos) -> filemap {
ret @rec(name=filename,
start_pos=start_pos,
mutable lines=[0u]);
ret @rec(name=filename, start_pos=start_pos, mutable lines=[0u]);
}
fn next_line(filemap file, uint pos) {
vec::push[uint](file.lines, pos);
}
fn next_line(filemap file, uint pos) { vec::push[uint](file.lines, pos); }
fn lookup_pos(codemap map, uint pos) -> loc {
auto a = 0u; auto b = vec::len[filemap](map.files);
auto a = 0u;
auto b = vec::len[filemap](map.files);
while (b - a > 1u) {
auto m = (a + b) / 2u;
if (map.files.(m).start_pos > pos) { b = m; }
else { a = m; }
if (map.files.(m).start_pos > pos) { b = m; } else { a = m; }
}
auto f = map.files.(a);
a = 0u; b = vec::len[uint](f.lines);
a = 0u;
b = vec::len[uint](f.lines);
while (b - a > 1u) {
auto m = (a + b) / 2u;
if (f.lines.(m) > pos) { b = m; }
else { a = m; }
if (f.lines.(m) > pos) { b = m; } else { a = m; }
}
ret rec(filename=f.name,
line=a + 1u,
col=pos - f.lines.(a));
ret rec(filename=f.name, line=a + 1u, col=pos - f.lines.(a));
}
//
// Local Variables:
// mode: rust

View File

@ -1,5 +1,6 @@
// -*- rust -*-
// -*- rust -*-
import driver::session;
import front::ast;
import lib::llvm::False;
@ -18,7 +19,6 @@ import util::common::respan;
import util::common::a_bang;
import util::common::a_ty;
import util::common::may_begin_ident;
import std::str;
import std::uint;
import std::vec;
@ -40,16 +40,15 @@ import std::map::hashmap;
// contain pipe characters.
// Callback to translate defs to strs or back:
type str_def = fn(str) -> ast::def_id;
type str_def = fn(str) -> ast::def_id ;
type pstate = rec(vec[u8] data, int crate,
mutable uint pos, uint len, ty::ctxt tcx);
type pstate =
rec(vec[u8] data, int crate, mutable uint pos, uint len, ty::ctxt tcx);
type ty_or_bang = util::common::ty_or_bang[ty::t];
fn peek(@pstate st) -> u8 {
ret st.data.(st.pos);
}
fn peek(@pstate st) -> u8 { ret st.data.(st.pos); }
fn next(@pstate st) -> u8 {
auto ch = st.data.(st.pos);
st.pos = st.pos + 1u;
@ -64,10 +63,10 @@ fn parse_ident(@pstate st, str_def sd, char last) -> ast::ident {
ret res;
}
fn parse_ty_data(vec[u8] data, int crate_num, uint pos, uint len,
str_def sd, ty::ctxt tcx) -> ty::t {
auto st = @rec(data=data, crate=crate_num,
mutable pos=pos, len=len, tcx=tcx);
fn parse_ty_data(vec[u8] data, int crate_num, uint pos, uint len, str_def sd,
ty::ctxt tcx) -> ty::t {
auto st =
@rec(data=data, crate=crate_num, mutable pos=pos, len=len, tcx=tcx);
auto result = parse_ty(st, sd);
ret result;
}
@ -75,7 +74,7 @@ fn parse_ty_data(vec[u8] data, int crate_num, uint pos, uint len,
fn parse_ty_or_bang(@pstate st, str_def sd) -> ty_or_bang {
alt (peek(st) as char) {
case ('!') { auto ignore = next(st); ret a_bang[ty::t]; }
case (_) { ret a_ty[ty::t](parse_ty(st, sd)); }
case (_) { ret a_ty[ty::t](parse_ty(st, sd)); }
}
}
@ -83,19 +82,18 @@ fn parse_constrs(@pstate st, str_def sd) -> vec[@ast::constr] {
let vec[@ast::constr] res = [];
alt (peek(st) as char) {
case (':') {
do {
do {
auto ignore = next(st);
vec::push(res, parse_constr(st, sd));
} while (peek(st) as char == ',')
}
case (_) {}
case (_) { }
}
ret res;
}
fn parse_constr(@pstate st, str_def sd) -> @ast::constr {
st.tcx.sess.unimpl("Reading constraints "
+ " isn't implemented");
st.tcx.sess.unimpl("Reading constraints " + " isn't implemented");
/*
let vec[@ast::constr_arg] args = [];
auto sp = rec(lo=0u,hi=0u); // FIXME
@ -137,6 +135,7 @@ fn parse_constr(@pstate st, str_def sd) -> @ast::constr {
} while (next(st) as char == ',');
ignore = next(st) as char;
*/
}
fn parse_ty(@pstate st, str_def sd) -> ty::t {
@ -168,9 +167,7 @@ fn parse_ty(@pstate st, str_def sd) -> ty::t {
assert (next(st) as char == '[');
auto def = parse_def(st, sd);
let vec[ty::t] params = [];
while (peek(st) as char != ']') {
params += [parse_ty(st, sd)];
}
while (peek(st) as char != ']') { params += [parse_ty(st, sd)]; }
st.pos = st.pos + 1u;
ret ty::mk_tag(st.tcx, def, params);
}
@ -185,9 +182,7 @@ fn parse_ty(@pstate st, str_def sd) -> ty::t {
case ('T') {
assert (next(st) as char == '[');
let vec[ty::mt] params = [];
while (peek(st) as char != ']') {
params += [parse_mt(st, sd)];
}
while (peek(st) as char != ']') { params += [parse_mt(st, sd)]; }
st.pos = st.pos + 1u;
ret ty::mk_tup(st.tcx, params);
}
@ -207,13 +202,13 @@ fn parse_ty(@pstate st, str_def sd) -> ty::t {
}
case ('F') {
auto func = parse_ty_fn(st, sd);
ret ty::mk_fn(st.tcx, ast::proto_fn, func._0,
func._1, func._2, func._3);
ret ty::mk_fn(st.tcx, ast::proto_fn, func._0, func._1, func._2,
func._3);
}
case ('W') {
auto func = parse_ty_fn(st, sd);
ret ty::mk_fn(st.tcx, ast::proto_iter, func._0,
func._1, func._2, func._3);
ret ty::mk_fn(st.tcx, ast::proto_iter, func._0, func._1, func._2,
func._3);
}
case ('N') {
auto abi;
@ -224,7 +219,7 @@ fn parse_ty(@pstate st, str_def sd) -> ty::t {
case ('l') { abi = ast::native_abi_llvm; }
}
auto func = parse_ty_fn(st, sd);
ret ty::mk_native_fn(st.tcx,abi,func._0,func._1);
ret ty::mk_native_fn(st.tcx, abi, func._0, func._1);
}
case ('O') {
assert (next(st) as char == '[');
@ -232,20 +227,21 @@ fn parse_ty(@pstate st, str_def sd) -> ty::t {
while (peek(st) as char != ']') {
auto proto;
alt (next(st) as char) {
case ('W') {proto = ast::proto_iter;}
case ('F') {proto = ast::proto_fn;}
case ('W') { proto = ast::proto_iter; }
case ('F') { proto = ast::proto_fn; }
}
auto name = "";
while (peek(st) as char != '[') {
name += str::unsafe_from_byte(next(st));
}
auto func = parse_ty_fn(st, sd);
methods += [rec(proto=proto,
ident=name,
inputs=func._0,
output=func._1,
cf=func._2,
constrs=func._3)];
methods +=
[rec(proto=proto,
ident=name,
inputs=func._0,
output=func._1,
cf=func._2,
constrs=func._3)];
}
st.pos += 1u;
ret ty::mk_obj(st.tcx, methods);
@ -258,12 +254,12 @@ fn parse_ty(@pstate st, str_def sd) -> ty::t {
assert (next(st) as char == ':');
auto len = parse_hex(st);
assert (next(st) as char == '#');
alt (st.tcx.rcache.find(tup(st.crate,pos,len))) {
alt (st.tcx.rcache.find(tup(st.crate, pos, len))) {
case (some(?tt)) { ret tt; }
case (none) {
auto ps = @rec(pos=pos, len=len with *st);
auto tt = parse_ty(ps, sd);
st.tcx.rcache.insert(tup(st.crate,pos,len), tt);
st.tcx.rcache.insert(tup(st.crate, pos, len), tt);
ret tt;
}
}
@ -279,9 +275,9 @@ fn parse_ty(@pstate st, str_def sd) -> ty::t {
fn parse_mt(@pstate st, str_def sd) -> ty::mt {
auto mut;
alt (peek(st) as char) {
case ('m') {next(st); mut = ast::mut;}
case ('?') {next(st); mut = ast::maybe_mut;}
case (_) {mut=ast::imm;}
case ('m') { next(st); mut = ast::mut; }
case ('?') { next(st); mut = ast::maybe_mut; }
case (_) { mut = ast::imm; }
}
ret rec(ty=parse_ty(st, sd), mut=mut);
}
@ -299,7 +295,7 @@ fn parse_int(@pstate st) -> int {
auto n = 0;
while (true) {
auto cur = peek(st) as char;
if (cur < '0' || cur > '9') {break;}
if (cur < '0' || cur > '9') { break; }
st.pos = st.pos + 1u;
n *= 10;
n += (cur as int) - ('0' as int);
@ -311,22 +307,18 @@ fn parse_hex(@pstate st) -> uint {
auto n = 0u;
while (true) {
auto cur = peek(st) as char;
if ((cur < '0' || cur > '9') &&
(cur < 'a' || cur > 'f')) {break;}
if ((cur < '0' || cur > '9') && (cur < 'a' || cur > 'f')) { break; }
st.pos = st.pos + 1u;
n *= 16u;
if ('0' <= cur && cur <= '9') {
n += (cur as uint) - ('0' as uint);
} else {
n += (10u + (cur as uint) - ('a' as uint));
}
} else { n += 10u + (cur as uint) - ('a' as uint); }
}
ret n;
}
fn parse_ty_fn(@pstate st, str_def sd) -> tup(vec[ty::arg], ty::t,
ast::controlflow,
vec[@ast::constr]) {
fn parse_ty_fn(@pstate st, str_def sd) ->
tup(vec[ty::arg], ty::t, ast::controlflow, vec[@ast::constr]) {
assert (next(st) as char == '[');
let vec[ty::arg] inputs = [];
while (peek(st) as char != ']') {
@ -342,33 +334,28 @@ fn parse_ty_fn(@pstate st, str_def sd) -> tup(vec[ty::arg], ty::t,
inputs += [rec(mode=mode, ty=parse_ty(st, sd))];
}
st.pos = st.pos + 1u;
auto cs = parse_constrs(st, sd);
auto cs = parse_constrs(st, sd);
auto res = parse_ty_or_bang(st, sd);
alt (res) {
case (a_bang) {
ret tup(inputs, ty::mk_bot(st.tcx), ast::noreturn, cs);
}
case (a_ty(?t)) {
ret tup(inputs, t, ast::return, cs);
}
case (a_ty(?t)) { ret tup(inputs, t, ast::return, cs); }
}
}
// Rust metadata parsing
fn parse_def_id(vec[u8] buf) -> ast::def_id {
auto colon_idx = 0u;
auto len = vec::len[u8](buf);
while (colon_idx < len && buf.(colon_idx) != (':' as u8)) {
while (colon_idx < len && buf.(colon_idx) != ':' as u8) {
colon_idx += 1u;
}
if (colon_idx == len) {
log_err "didn't find ':' when parsing def id";
fail;
}
auto crate_part = vec::slice[u8](buf, 0u, colon_idx);
auto def_part = vec::slice[u8](buf, colon_idx + 1u, len);
auto crate_num = uint::parse_buf(crate_part, 10u) as int;
@ -376,26 +363,27 @@ fn parse_def_id(vec[u8] buf) -> ast::def_id {
ret tup(crate_num, def_num);
}
fn lookup_hash(&ebml::doc d, fn(vec[u8]) -> bool eq_fn, uint hash)
-> vec[ebml::doc] {
fn lookup_hash(&ebml::doc d, fn(vec[u8]) -> bool eq_fn, uint hash) ->
vec[ebml::doc] {
auto index = ebml::get_doc(d, metadata::tag_index);
auto table = ebml::get_doc(index, metadata::tag_index_table);
auto hash_pos = table.start + (hash % 256u) * 4u;
auto hash_pos = table.start + hash % 256u * 4u;
auto pos = ebml::be_uint_from_bytes(d.data, hash_pos, 4u);
auto bucket = ebml::doc_at(d.data, pos);
// Awkward logic because we can't ret from foreach yet
let vec[ebml::doc] result = [];
auto belt = metadata::tag_index_buckets_bucket_elt;
for each (ebml::doc elt in ebml::tagged_docs(bucket, belt)) {
auto pos = ebml::be_uint_from_bytes(elt.data, elt.start, 4u);
if (eq_fn(vec::slice[u8](elt.data, elt.start+4u, elt.end))) {
if (eq_fn(vec::slice[u8](elt.data, elt.start + 4u, elt.end))) {
vec::push(result, ebml::doc_at(d.data, pos));
}
}
ret result;
}
// Given a path and serialized crate metadata, returns the ID of the
// definition the path refers to.
fn resolve_path(vec[ast::ident] path, vec[u8] data) -> vec[ast::def_id] {
@ -422,15 +410,14 @@ fn maybe_find_item(int item_id, &ebml::doc items) -> option::t[ebml::doc] {
auto found = lookup_hash(items, eqer, metadata::hash_def_num(item_id));
if (vec::len(found) == 0u) {
ret option::none[ebml::doc];
} else {
ret option::some[ebml::doc](found.(0));
}
} else { ret option::some[ebml::doc](found.(0)); }
}
fn find_item(int item_id, &ebml::doc items) -> ebml::doc {
ret option::get(maybe_find_item(item_id, items));
}
// Looks up an item in the given metadata and returns an ebml doc pointing
// to the item data.
fn lookup_item(int item_id, vec[u8] data) -> ebml::doc {
@ -459,11 +446,11 @@ fn item_type(&ebml::doc item, int this_cnum, ty::ctxt tcx) -> ty::t {
// that, in turn, links against another crate. We need a mapping
// from crate ID to crate "meta" attributes as part of the crate
// metadata:
auto buf = str::bytes(s);
auto external_def_id = parse_def_id(buf);
ret tup(this_cnum, external_def_id._1);
}
auto tp = ebml::get_doc(item, metadata::tag_items_data_item_type);
auto s = str::unsafe_from_bytes(ebml::doc_data(tp));
ret parse_ty_data(item.data, this_cnum, tp.start, tp.end - tp.start,
@ -490,9 +477,10 @@ fn tag_variant_ids(&ebml::doc item, int this_cnum) -> vec[ast::def_id] {
}
fn get_metadata_section(str filename) -> option::t[vec[u8]] {
auto mb = llvm::LLVMRustCreateMemoryBufferWithContentsOfFile
(str::buf(filename));
if (mb as int == 0) {ret option::none[vec[u8]];}
auto b = str::buf(filename);
auto mb =
llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(b);
if (mb as int == 0) { ret option::none[vec[u8]]; }
auto of = mk_object_file(mb);
auto si = mk_section_iter(of.llof);
while (llvm::LLVMIsSectionIteratorAtEnd(of.llof, si.llsi) == False) {
@ -509,73 +497,60 @@ fn get_metadata_section(str filename) -> option::t[vec[u8]] {
ret option::none[vec[u8]];
}
fn get_exported_metadata(&session::session sess,
&str path,
&vec[u8] data) -> hashmap[str,str] {
auto meta_items = ebml::get_doc(ebml::new_doc(data),
metadata::tag_meta_export);
fn get_exported_metadata(&session::session sess, &str path, &vec[u8] data) ->
hashmap[str, str] {
auto meta_items =
ebml::get_doc(ebml::new_doc(data), metadata::tag_meta_export);
auto mm = common::new_str_hash[str]();
for each (ebml::doc m in ebml::tagged_docs(meta_items,
metadata::tag_meta_item)) {
for each (ebml::doc m in
ebml::tagged_docs(meta_items, metadata::tag_meta_item)) {
auto kd = ebml::get_doc(m, metadata::tag_meta_item_key);
auto vd = ebml::get_doc(m, metadata::tag_meta_item_value);
auto k = str::unsafe_from_bytes(ebml::doc_data(kd));
auto v = str::unsafe_from_bytes(ebml::doc_data(vd));
log #fmt("metadata in %s: %s = %s", path, k, v);
if (!mm.insert(k,v)) {
if (!mm.insert(k, v)) {
sess.warn(#fmt("Duplicate metadata item in %s: %s", path, k));
}
}
ret mm;
}
fn metadata_matches(hashmap[str,str] mm,
&vec[@ast::meta_item] metas) -> bool {
fn metadata_matches(hashmap[str, str] mm, &vec[@ast::meta_item] metas) ->
bool {
log #fmt("matching %u metadata requirements against %u metadata items",
vec::len(metas), mm.size());
for (@ast::meta_item mi in metas) {
alt (mm.find(mi.node.key)) {
case (some(?v)) {
if (v == mi.node.value) {
log #fmt("matched '%s': '%s'",
mi.node.key, mi.node.value);
log #fmt("matched '%s': '%s'", mi.node.key,
mi.node.value);
} else {
log #fmt("missing '%s': '%s' (got '%s')",
mi.node.key, mi.node.value, v);
log #fmt("missing '%s': '%s' (got '%s')", mi.node.key,
mi.node.value, v);
ret false;
}
}
case (none) {
log #fmt("missing '%s': '%s'",
mi.node.key, mi.node.value);
ret false;
log #fmt("missing '%s': '%s'", mi.node.key, mi.node.value);
ret false;
}
}
}
ret true;
}
fn find_library_crate(&session::session sess,
&ast::ident ident,
fn find_library_crate(&session::session sess, &ast::ident ident,
&vec[@ast::meta_item] metas,
&vec[str] library_search_paths)
-> option::t[tup(str, vec[u8])] {
&vec[str] library_search_paths) ->
option::t[tup(str, vec[u8])] {
let str crate_name = ident;
for (@ast::meta_item mi in metas) {
if (mi.node.key == "name") {
crate_name = mi.node.value;
break;
}
if (mi.node.key == "name") { crate_name = mi.node.value; break; }
}
auto nn = parser::default_native_lib_naming(sess);
let str prefix = nn.prefix + crate_name;
// FIXME: we could probably use a 'glob' function in std::fs but it will
// be much easier to write once the unsafe module knows more about FFI
// tricks. Currently the glob(3) interface is a bit more than we can
@ -583,17 +558,14 @@ fn find_library_crate(&session::session sess,
// manually filtering fs::list_dir here.
for (str library_search_path in library_search_paths) {
for (str path in fs::list_dir(library_search_path)) {
let str f = fs::basename(path);
if (! (str::starts_with(f, prefix) &&
str::ends_with(f, nn.suffix))) {
log #fmt("skipping %s, doesn't look like %s*%s",
path, prefix, nn.suffix);
if (!(str::starts_with(f, prefix) &&
str::ends_with(f, nn.suffix))) {
log #fmt("skipping %s, doesn't look like %s*%s", path, prefix,
nn.suffix);
cont;
}
alt (get_metadata_section(path)) {
case (option::some(?cvec)) {
auto mm = get_exported_metadata(sess, path, cvec);
@ -604,37 +576,33 @@ fn find_library_crate(&session::session sess,
log #fmt("found %s with matching metadata", path);
ret some(tup(path, cvec));
}
case (_) {}
case (_) { }
}
}
}
ret none;
}
fn load_library_crate(&session::session sess,
&int cnum,
&ast::ident ident,
fn load_library_crate(&session::session sess, &int cnum, &ast::ident ident,
&vec[@ast::meta_item] metas,
&vec[str] library_search_paths) {
alt (find_library_crate(sess, ident, metas, library_search_paths)) {
case (some(?t)) {
sess.set_external_crate(cnum, rec(name=ident,
data=t._1));
sess.set_external_crate(cnum, rec(name=ident, data=t._1));
ret;
}
case (_) {}
case (_) { }
}
log_err #fmt("can't find crate for '%s'", ident);
fail;
}
type env = @rec(
session::session sess,
resolve::crate_map crate_map,
@hashmap[str, int] crate_cache,
vec[str] library_search_paths,
mutable int next_crate_num
);
type env =
@rec(session::session sess,
resolve::crate_map crate_map,
@hashmap[str, int] crate_cache,
vec[str] library_search_paths,
mutable int next_crate_num);
fn visit_view_item(env e, &@ast::view_item i) {
alt (i.node) {
@ -646,9 +614,7 @@ fn visit_view_item(env e, &@ast::view_item i) {
e.library_search_paths);
e.crate_cache.insert(ident, e.next_crate_num);
e.next_crate_num += 1;
} else {
cnum = e.crate_cache.get(ident);
}
} else { cnum = e.crate_cache.get(ident); }
e.crate_map.insert(ann.id, cnum);
}
case (_) { }
@ -657,66 +623,70 @@ fn visit_view_item(env e, &@ast::view_item i) {
// Reads external crates referenced by "use" directives.
fn read_crates(session::session sess,
resolve::crate_map crate_map,
fn read_crates(session::session sess, resolve::crate_map crate_map,
&ast::crate crate) {
auto e = @rec(
sess=sess,
crate_map=crate_map,
crate_cache=@common::new_str_hash[int](),
library_search_paths=sess.get_opts().library_search_paths,
mutable next_crate_num=1
);
auto v = rec(visit_view_item_pre=bind visit_view_item(e, _)
with walk::default_visitor());
auto e =
@rec(sess=sess,
crate_map=crate_map,
crate_cache=@common::new_str_hash[int](),
library_search_paths=sess.get_opts().library_search_paths,
mutable next_crate_num=1);
auto v =
rec(visit_view_item_pre=bind visit_view_item(e, _)
with walk::default_visitor());
walk::walk_crate(v, crate);
}
fn kind_has_type_params(u8 kind_ch) -> bool {
ret alt (kind_ch as char) {
case ('c') { false } case ('f') { true } case ('F') { true }
case ('y') { true } case ('o') { true } case ('t') { true }
case ('T') { false } case ('m') { false } case ('n') { false }
case ('v') { true }
};
case ('c') { false }
case ('f') { true }
case ('F') { true }
case ('y') { true }
case ('o') { true }
case ('t') { true }
case ('T') { false }
case ('m') { false }
case ('n') { false }
case ('v') { true }
};
}
// Crate metadata queries
fn lookup_defs(session::session sess, int cnum, vec[ast::ident] path)
-> vec[ast::def] {
fn lookup_defs(session::session sess, int cnum, vec[ast::ident] path) ->
vec[ast::def] {
auto data = sess.get_external_crate(cnum).data;
ret vec::map(bind lookup_def(cnum, data, _),
resolve_path(path, data));
ret vec::map(bind lookup_def(cnum, data, _), resolve_path(path, data));
}
// FIXME doesn't yet handle re-exported externals
fn lookup_def(int cnum, vec[u8] data, &ast::def_id did_) -> ast::def {
auto item = lookup_item(did_._1, data);
auto kind_ch = item_kind(item);
auto did = tup(cnum, did_._1);
auto def = alt (kind_ch as char) {
case ('c') { ast::def_const(did) }
case ('f') { ast::def_fn(did) }
case ('F') { ast::def_native_fn(did) }
case ('y') { ast::def_ty(did) }
case ('o') { ast::def_obj(did) }
case ('T') { ast::def_native_ty(did) }
// We treat references to tags as references to types.
case ('t') { ast::def_ty(did) }
case ('m') { ast::def_mod(did) }
case ('n') { ast::def_native_mod(did) }
case ('v') {
auto tid = variant_tag_id(item);
tid = tup(cnum, tid._1);
ast::def_variant(tid, did)
}
};
auto def =
alt (kind_ch as char) {
case ('c') { ast::def_const(did) }
case ('f') { ast::def_fn(did) }
case ('F') { ast::def_native_fn(did) }
case ('y') { ast::def_ty(did) }
case ('o') { ast::def_obj(did) }
case ('T') { ast::def_native_ty(did) }
case (
// We treat references to tags as references to types.
't') {
ast::def_ty(did)
}
case ('m') { ast::def_mod(did) }
case ('n') { ast::def_native_mod(did) }
case ('v') {
auto tid = variant_tag_id(item);
tid = tup(cnum, tid._1);
ast::def_variant(tid, did)
}
};
ret def;
}
@ -725,16 +695,12 @@ fn get_type(ty::ctxt tcx, ast::def_id def) -> ty::ty_param_count_and_ty {
auto data = tcx.sess.get_external_crate(external_crate_id).data;
auto item = lookup_item(def._1, data);
auto t = item_type(item, external_crate_id, tcx);
auto tp_count;
auto kind_ch = item_kind(item);
auto has_ty_params = kind_has_type_params(kind_ch);
if (has_ty_params) {
tp_count = item_ty_param_count(item, external_crate_id);
} else {
tp_count = 0u;
}
} else { tp_count = 0u; }
ret tup(tp_count, t);
}
@ -744,13 +710,11 @@ fn get_symbol(session::session sess, ast::def_id def) -> str {
ret item_symbol(lookup_item(def._1, data));
}
fn get_tag_variants(ty::ctxt tcx, ast::def_id def)
-> vec[ty::variant_info] {
fn get_tag_variants(ty::ctxt tcx, ast::def_id def) -> vec[ty::variant_info] {
auto external_crate_id = def._0;
auto data = tcx.sess.get_external_crate(external_crate_id).data;
auto items = ebml::get_doc(ebml::new_doc(data), metadata::tag_items);
auto item = find_item(def._1, items);
let vec[ty::variant_info] infos = [];
auto variant_ids = tag_variant_ids(item, external_crate_id);
for (ast::def_id did in variant_ids) {
@ -759,25 +723,21 @@ fn get_tag_variants(ty::ctxt tcx, ast::def_id def)
let vec[ty::t] arg_tys = [];
alt (ty::struct(tcx, ctor_ty)) {
case (ty::ty_fn(_, ?args, _, _, _)) {
for (ty::arg a in args) {
arg_tys += [a.ty];
}
for (ty::arg a in args) { arg_tys += [a.ty]; }
}
case (_) {
// Nullary tag variant.
}
}
infos += [rec(args=arg_tys, ctor_ty=ctor_ty, id=did)];
}
ret infos;
}
fn list_file_metadata(str path, io::writer out) {
alt (get_metadata_section(path)) {
case (option::some(?bytes)) {
list_crate_metadata(bytes, out);
}
case (option::some(?bytes)) { list_crate_metadata(bytes, out); }
case (option::none) {
out.write_str("Could not find metadata in " + path + ".\n");
}
@ -799,7 +759,7 @@ fn list_crate_metadata(vec[u8] bytes, io::writer out) {
auto index = ebml::get_doc(paths, metadata::tag_index);
auto bs = ebml::get_doc(index, metadata::tag_index_buckets);
for each (ebml::doc bucket in
ebml::tagged_docs(bs, metadata::tag_index_buckets_bucket)) {
ebml::tagged_docs(bs, metadata::tag_index_buckets_bucket)) {
auto et = metadata::tag_index_buckets_bucket_elt;
for each (ebml::doc elt in ebml::tagged_docs(bucket, et)) {
auto data = read_path(elt);
@ -819,19 +779,18 @@ fn describe_def(&ebml::doc items, ast::def_id id) -> str {
fn item_kind_to_str(u8 kind) -> str {
alt (kind as char) {
case ('c') {ret "const";}
case ('f') {ret "fn";}
case ('F') {ret "native fn";}
case ('y') {ret "type";}
case ('o') {ret "obj";}
case ('T') {ret "native type";}
case ('t') {ret "type";}
case ('m') {ret "mod";}
case ('n') {ret "native mod";}
case ('v') {ret "tag";}
case ('c') { ret "const"; }
case ('f') { ret "fn"; }
case ('F') { ret "native fn"; }
case ('y') { ret "type"; }
case ('o') { ret "obj"; }
case ('T') { ret "native type"; }
case ('t') { ret "type"; }
case ('m') { ret "mod"; }
case ('n') { ret "native mod"; }
case ('v') { ret "tag"; }
}
}
// Local Variables:
// mode: rust
// fill-column: 78;

View File

@ -1,10 +1,10 @@
import std::vec;
import std::str;
import std::option;
import std::option::some;
import std::option::none;
import std::map::hashmap;
import driver::session;
import ast::ident;
import front::parser::parser;
@ -18,76 +18,49 @@ import util::common::new_str_hash;
// Simple dynamic-typed value type for eval_expr.
tag val {
val_bool(bool);
val_int(int);
val_str(str);
}
tag val { val_bool(bool); val_int(int); val_str(str); }
tag eval_mode {
mode_depend;
mode_parse;
}
tag eval_mode { mode_depend; mode_parse; }
type env = vec[tup(ident, val)];
type ctx = @rec(parser p,
eval_mode mode,
mutable vec[str] deps,
session::session sess,
mutable uint chpos,
mutable uint next_ann);
fn mk_env() -> env {
ret [];
}
type ctx =
@rec(parser p,
eval_mode mode,
mutable vec[str] deps,
session::session sess,
mutable uint chpos,
mutable uint next_ann);
fn mk_env() -> env { ret []; }
fn val_is_bool(val v) -> bool {
alt (v) {
case (val_bool(_)) { true }
case (_) { false }
}
alt (v) { case (val_bool(_)) { true } case (_) { false } }
}
fn val_is_int(val v) -> bool {
alt (v) {
case (val_int(_)) { true }
case (_) { false }
}
alt (v) { case (val_int(_)) { true } case (_) { false } }
}
fn val_is_str(val v) -> bool {
alt (v) {
case (val_str(_)) { true }
case (_) { false }
}
alt (v) { case (val_str(_)) { true } case (_) { false } }
}
fn val_as_bool(val v) -> bool {
alt (v) {
case (val_bool(?b)) { b }
case (_) { fail }
}
alt (v) { case (val_bool(?b)) { b } case (_) { fail } }
}
fn val_as_int(val v) -> int {
alt (v) {
case (val_int(?i)) { i }
case (_) { fail }
}
alt (v) { case (val_int(?i)) { i } case (_) { fail } }
}
fn val_as_str(val v) -> str {
alt (v) {
case (val_str(?s)) { s }
case (_) { fail }
}
alt (v) { case (val_str(?s)) { s } case (_) { fail } }
}
fn lookup(session::session sess, env e, span sp, ident i) -> val {
for (tup(ident, val) pair in e) {
if (str::eq(i, pair._0)) {
ret pair._1;
}
if (str::eq(i, pair._0)) { ret pair._1; }
}
sess.span_err(sp, "unknown variable: " + i)
}
@ -96,10 +69,8 @@ fn eval_lit(ctx cx, span sp, @ast::lit lit) -> val {
alt (lit.node) {
case (ast::lit_bool(?b)) { val_bool(b) }
case (ast::lit_int(?i)) { val_int(i) }
case (ast::lit_str(?s,_)) { val_str(s) }
case (_) {
cx.sess.span_err(sp, "evaluating unsupported literal")
}
case (ast::lit_str(?s, _)) { val_str(s) }
case (_) { cx.sess.span_err(sp, "evaluating unsupported literal") }
}
}
@ -107,23 +78,17 @@ fn eval_expr(ctx cx, env e, @ast::expr x) -> val {
alt (x.node) {
case (ast::expr_path(?pth, _)) {
if (vec::len[ident](pth.node.idents) == 1u &&
vec::len[@ast::ty](pth.node.types) == 0u) {
vec::len[@ast::ty](pth.node.types) == 0u) {
ret lookup(cx.sess, e, x.span, pth.node.idents.(0));
}
cx.sess.span_err(x.span, "evaluating structured path-name");
}
case (ast::expr_lit(?lit, _)) {
ret eval_lit(cx, x.span, lit);
}
case (ast::expr_lit(?lit, _)) { ret eval_lit(cx, x.span, lit); }
case (ast::expr_unary(?op, ?a, _)) {
auto av = eval_expr(cx, e, a);
alt (op) {
case (ast::not) {
if (val_is_bool(av)) {
ret val_bool(!val_as_bool(av));
}
if (val_is_bool(av)) { ret val_bool(!val_as_bool(av)); }
cx.sess.span_err(x.span, "bad types in '!' expression");
}
case (_) {
@ -131,7 +96,6 @@ fn eval_expr(ctx cx, env e, @ast::expr x) -> val {
}
}
}
case (ast::expr_binary(?op, ?a, ?b, _)) {
auto av = eval_expr(cx, e, a);
auto bv = eval_expr(cx, e, b);
@ -145,57 +109,48 @@ fn eval_expr(ctx cx, env e, @ast::expr x) -> val {
}
cx.sess.span_err(x.span, "bad types in '+' expression");
}
case (ast::sub) {
if (val_is_int(av) && val_is_int(bv)) {
ret val_int(val_as_int(av) - val_as_int(bv));
}
cx.sess.span_err(x.span, "bad types in '-' expression");
}
case (ast::mul) {
if (val_is_int(av) && val_is_int(bv)) {
ret val_int(val_as_int(av) * val_as_int(bv));
}
cx.sess.span_err(x.span, "bad types in '*' expression");
}
case (ast::div) {
if (val_is_int(av) && val_is_int(bv)) {
ret val_int(val_as_int(av) / val_as_int(bv));
}
cx.sess.span_err(x.span, "bad types in '/' expression");
}
case (ast::rem) {
if (val_is_int(av) && val_is_int(bv)) {
ret val_int(val_as_int(av) % val_as_int(bv));
}
cx.sess.span_err(x.span, "bad types in '%' expression");
}
case (ast::and) {
if (val_is_bool(av) && val_is_bool(bv)) {
ret val_bool(val_as_bool(av) && val_as_bool(bv));
}
cx.sess.span_err(x.span, "bad types in '&&' expression");
}
case (ast::or) {
if (val_is_bool(av) && val_is_bool(bv)) {
ret val_bool(val_as_bool(av) || val_as_bool(bv));
}
cx.sess.span_err(x.span, "bad types in '||' expression");
}
case (ast::eq) {
ret val_bool(val_eq(cx.sess, x.span, av, bv));
}
case (ast::ne) {
ret val_bool(! val_eq(cx.sess, x.span, av, bv));
ret val_bool(!val_eq(cx.sess, x.span, av, bv));
}
case (_) {
cx.sess.span_err(x.span, "evaluating unsupported binop");
}
@ -214,52 +169,34 @@ fn val_eq(session::session sess, span sp, val av, val bv) -> bool {
} else if (val_is_int(av) && val_is_int(bv)) {
val_as_int(av) == val_as_int(bv)
} else if (val_is_str(av) && val_is_str(bv)) {
str::eq(val_as_str(av),
val_as_str(bv))
} else {
sess.span_err(sp, "bad types in comparison")
}
str::eq(val_as_str(av), val_as_str(bv))
} else { sess.span_err(sp, "bad types in comparison") }
}
fn eval_crate_directives(ctx cx,
env e,
vec[@ast::crate_directive] cdirs,
str prefix,
&mutable vec[@ast::view_item] view_items,
&mutable vec[@ast::item] items) {
fn eval_crate_directives(ctx cx, env e, vec[@ast::crate_directive] cdirs,
str prefix, &mutable vec[@ast::view_item] view_items,
&mutable vec[@ast::item] items) {
for (@ast::crate_directive sub_cdir in cdirs) {
eval_crate_directive(cx, e, sub_cdir, prefix,
view_items, items);
eval_crate_directive(cx, e, sub_cdir, prefix, view_items, items);
}
}
fn eval_crate_directives_to_mod(ctx cx, env e,
vec[@ast::crate_directive] cdirs,
str prefix) -> ast::_mod {
vec[@ast::crate_directive] cdirs, str prefix)
-> ast::_mod {
let vec[@ast::view_item] view_items = [];
let vec[@ast::item] items = [];
eval_crate_directives(cx, e, cdirs, prefix,
view_items, items);
eval_crate_directives(cx, e, cdirs, prefix, view_items, items);
ret rec(view_items=view_items, items=items);
}
fn eval_crate_directive_block(ctx cx,
env e,
&ast::block blk,
str prefix,
&mutable vec[@ast::view_item] view_items,
&mutable vec[@ast::item] items) {
fn eval_crate_directive_block(ctx cx, env e, &ast::block blk, str prefix,
&mutable vec[@ast::view_item] view_items,
&mutable vec[@ast::item] items) {
for (@ast::stmt s in blk.node.stmts) {
alt (s.node) {
case (ast::stmt_crate_directive(?cdir)) {
eval_crate_directive(cx, e, cdir, prefix,
view_items, items);
eval_crate_directive(cx, e, cdir, prefix, view_items, items);
}
case (_) {
cx.sess.span_err(s.span,
@ -269,25 +206,19 @@ fn eval_crate_directive_block(ctx cx,
}
}
fn eval_crate_directive_expr(ctx cx,
env e,
@ast::expr x,
str prefix,
&mutable vec[@ast::view_item] view_items,
&mutable vec[@ast::item] items) {
fn eval_crate_directive_expr(ctx cx, env e, @ast::expr x, str prefix,
&mutable vec[@ast::view_item] view_items,
&mutable vec[@ast::item] items) {
alt (x.node) {
case (ast::expr_if(?cond, ?thn, ?elopt, _)) {
auto cv = eval_expr(cx, e, cond);
if (!val_is_bool(cv)) {
cx.sess.span_err(x.span, "bad cond type in 'if'");
}
if (val_as_bool(cv)) {
ret eval_crate_directive_block(cx, e, thn, prefix,
view_items, items);
ret eval_crate_directive_block(cx, e, thn, prefix, view_items,
items);
}
alt (elopt) {
case (some(?els)) {
ret eval_crate_directive_expr(cx, e, els, prefix,
@ -295,10 +226,10 @@ fn eval_crate_directive_expr(ctx cx,
}
case (_) {
// Absent-else is ok.
}
}
}
case (ast::expr_alt(?v, ?arms, _)) {
auto vv = eval_expr(cx, e, v);
for (ast::arm arm in arms) {
@ -306,14 +237,15 @@ fn eval_crate_directive_expr(ctx cx,
case (ast::pat_lit(?lit, _)) {
auto pv = eval_lit(cx, arm.pat.span, lit);
if (val_eq(cx.sess, arm.pat.span, vv, pv)) {
ret eval_crate_directive_block
(cx, e, arm.block, prefix, view_items, items);
ret eval_crate_directive_block(cx, e, arm.block,
prefix, view_items,
items);
}
}
case (ast::pat_wild(_)) {
ret eval_crate_directive_block
(cx, e, arm.block, prefix,
view_items, items);
ret eval_crate_directive_block(cx, e, arm.block,
prefix, view_items,
items);
}
case (_) {
cx.sess.span_err(arm.pat.span,
@ -323,61 +255,42 @@ fn eval_crate_directive_expr(ctx cx,
}
cx.sess.span_err(x.span, "no cases matched in 'alt'");
}
case (ast::expr_block(?block, _)) {
ret eval_crate_directive_block(cx, e, block, prefix,
view_items, items);
}
case (_) {
cx.sess.span_err(x.span, "unsupported expr type");
ret eval_crate_directive_block(cx, e, block, prefix, view_items,
items);
}
case (_) { cx.sess.span_err(x.span, "unsupported expr type"); }
}
}
fn eval_crate_directive(ctx cx,
env e,
@ast::crate_directive cdir,
str prefix,
&mutable vec[@ast::view_item] view_items,
&mutable vec[@ast::item] items) {
fn eval_crate_directive(ctx cx, env e, @ast::crate_directive cdir, str prefix,
&mutable vec[@ast::view_item] view_items,
&mutable vec[@ast::item] items) {
alt (cdir.node) {
case (ast::cdir_let(?id, ?x, ?cdirs)) {
auto v = eval_expr(cx, e, x);
auto e0 = [tup(id, v)] + e;
eval_crate_directives(cx, e0, cdirs, prefix,
view_items, items);
eval_crate_directives(cx, e0, cdirs, prefix, view_items, items);
}
case (ast::cdir_expr(?x)) {
eval_crate_directive_expr(cx, e, x, prefix,
view_items, items);
eval_crate_directive_expr(cx, e, x, prefix, view_items, items);
}
case (ast::cdir_src_mod(?id, ?file_opt)) {
auto file_path = id + ".rs";
alt (file_opt) {
case (some(?f)) {
file_path = f;
}
case (none) {}
case (some(?f)) { file_path = f; }
case (none) { }
}
auto full_path = prefix + std::fs::path_sep() + file_path;
if (cx.mode == mode_depend) {
cx.deps += [full_path];
ret;
}
if (cx.mode == mode_depend) { cx.deps += [full_path]; ret; }
auto start_id = cx.p.next_def_id();
auto p0 = new_parser(cx.sess, e, start_id, full_path, cx.chpos,
cx.next_ann);
auto p0 =
new_parser(cx.sess, e, start_id, full_path, cx.chpos,
cx.next_ann);
auto m0 = parse_mod_items(p0, token::EOF);
auto next_id = p0.next_def_id();
// Thread defids and chpos through the parsers
cx.p.set_def(next_id._1);
cx.chpos = p0.get_chpos();
cx.next_ann = p0.next_ann_num();
@ -385,40 +298,25 @@ fn eval_crate_directive(ctx cx,
auto i = @spanned(cdir.span.lo, cdir.span.hi, im);
vec::push[@ast::item](items, i);
}
case (ast::cdir_dir_mod(?id, ?dir_opt, ?cdirs)) {
auto path = id;
alt (dir_opt) {
case (some(?d)) {
path = d;
}
case (none) {}
}
alt (dir_opt) { case (some(?d)) { path = d; } case (none) { } }
auto full_path = prefix + std::fs::path_sep() + path;
auto m0 = eval_crate_directives_to_mod(cx, e, cdirs, full_path);
auto im = ast::item_mod(id, m0, [], cx.p.next_def_id());
auto i = @spanned(cdir.span.lo, cdir.span.hi, im);
vec::push[@ast::item](items, i);
}
case (ast::cdir_view_item(?vi)) {
vec::push[@ast::view_item](view_items, vi);
}
case (ast::cdir_meta(?vi, ?mi)) {
if (vi == ast::export_meta) {
cx.sess.add_metadata(mi);
}
if (vi == ast::export_meta) { cx.sess.add_metadata(mi); }
}
case (ast::cdir_syntax(?pth)) {}
case (ast::cdir_auth(?pth, ?eff)) {}
case (ast::cdir_syntax(?pth)) { }
case (ast::cdir_auth(?pth, ?eff)) { }
}
}
//
// Local Variables:
// mode: rust

View File

@ -1,19 +1,18 @@
import std::option;
import std::map::hashmap;
import driver::session::session;
import front::parser::parser;
import util::common::span;
import util::common::new_str_hash;
type syntax_expander = fn(&ext_ctxt, span,
&vec[@ast::expr],
option::t[str]) -> @ast::expr;
type syntax_expander =
fn(&ext_ctxt, span, &vec[@ast::expr], option::t[str]) -> @ast::expr ;
// Temporary: to introduce a tag in order to make a recursive type work
tag syntax_extension {
x(syntax_expander);
}
tag syntax_extension { x(syntax_expander); }
// A temporary hard-coded map of methods for expanding syntax extension
// AST nodes into full ASTs
@ -24,36 +23,32 @@ fn syntax_expander_table() -> hashmap[str, syntax_extension] {
ret syntax_expanders;
}
type span_msg_fn = fn (span sp, str msg) -> !;
type next_ann_fn = fn () -> ast::ann;
type span_msg_fn = fn(span, str) -> ! ;
type next_ann_fn = fn() -> ast::ann ;
// Provides a limited set of services necessary for syntax extensions
// to do their thing
type ext_ctxt = rec(span_msg_fn span_err,
span_msg_fn span_unimpl,
next_ann_fn next_ann);
type ext_ctxt =
rec(span_msg_fn span_err, span_msg_fn span_unimpl, next_ann_fn next_ann);
fn mk_ctxt(parser parser) -> ext_ctxt {
auto sess = parser.get_session();
fn ext_span_err_(session sess, span sp, str msg) -> ! {
sess.span_err(sp, msg);
}
auto ext_span_err = bind ext_span_err_(sess, _, _);
fn ext_span_unimpl_(session sess, span sp, str msg) -> ! {
sess.span_unimpl(sp, msg);
}
auto ext_span_unimpl = bind ext_span_unimpl_(sess, _, _);
fn ext_next_ann_(parser parser) -> ast::ann { parser.get_ann() }
auto ext_next_ann = bind ext_next_ann_(parser);
ret rec(span_err = ext_span_err,
span_unimpl = ext_span_unimpl,
next_ann = ext_next_ann);
ret rec(span_err=ext_span_err,
span_unimpl=ext_span_unimpl,
next_ann=ext_next_ann);
}
//
// Local Variables:
// mode: rust

View File

@ -1,50 +1,40 @@
/*
* The compiler code necessary to support the #env extension. Eventually this
* should all get sucked into either the compiler syntax extension plugin
* interface.
*/
import util::common;
import std::str;
import std::vec;
import std::option;
import std::generic_os;
import ext::*;
export expand_syntax_ext;
fn expand_syntax_ext(&ext_ctxt cx,
common::span sp,
&vec[@ast::expr] args,
fn expand_syntax_ext(&ext_ctxt cx, common::span sp, &vec[@ast::expr] args,
option::t[str] body) -> @ast::expr {
if (vec::len[@ast::expr](args) != 1u) {
cx.span_err(sp, "malformed #env call");
}
// FIXME: if this was more thorough it would manufacture an
// option::t[str] rather than just an maybe-empty string.
auto var = expr_to_str(cx, args.(0));
alt (generic_os::getenv(var)) {
case (option::none) {
ret make_new_str(cx, sp, "");
}
case (option::some(?s)) {
ret make_new_str(cx, sp, s);
}
case (option::none) { ret make_new_str(cx, sp, ""); }
case (option::some(?s)) { ret make_new_str(cx, sp, s); }
}
}
// FIXME: duplicate code copied from extfmt:
// FIXME: duplicate code copied from extfmt:
fn expr_to_str(&ext_ctxt cx, @ast::expr expr) -> str {
alt (expr.node) {
case (ast::expr_lit(?l, _)) {
alt (l.node) {
case (ast::lit_str(?s,_)) { ret s; }
case (ast::lit_str(?s, _)) { ret s; }
case (_) { cx.span_err(l.span, "malformed #env call"); }
}
}
@ -52,8 +42,7 @@ fn expr_to_str(&ext_ctxt cx, @ast::expr expr) -> str {
}
}
fn make_new_lit(&ext_ctxt cx, common::span sp, ast::lit_ lit)
-> @ast::expr {
fn make_new_lit(&ext_ctxt cx, common::span sp, ast::lit_ lit) -> @ast::expr {
auto sp_lit = @rec(node=lit, span=sp);
auto expr = ast::expr_lit(sp_lit, cx.next_ann());
ret @rec(node=expr, span=sp);
@ -62,7 +51,6 @@ fn make_new_lit(&ext_ctxt cx, common::span sp, ast::lit_ lit)
fn make_new_str(&ext_ctxt cx, common::span sp, str s) -> @ast::expr {
ret make_new_lit(cx, sp, ast::lit_str(s, ast::sk_rc));
}
//
// Local Variables:
// mode: rust

View File

@ -1,42 +1,32 @@
/*
* The compiler code necessary to support the #fmt extension. Eventually this
* should all get sucked into either the standard library extfmt module or the
* compiler syntax extension plugin interface.
*/
import util::common;
import std::str;
import std::vec;
import std::option;
import std::option::none;
import std::option::some;
import std::extfmt::ct::*;
import ext::*;
export expand_syntax_ext;
fn expand_syntax_ext(&ext_ctxt cx,
common::span sp,
&vec[@ast::expr] args,
fn expand_syntax_ext(&ext_ctxt cx, common::span sp, &vec[@ast::expr] args,
option::t[str] body) -> @ast::expr {
if (vec::len[@ast::expr](args) == 0u) {
cx.span_err(sp, "#fmt requires a format string");
}
auto fmt = expr_to_str(cx, args.(0));
auto fmtspan = args.(0).span;
log "Format string:";
log fmt;
fn parse_fmt_err_(&ext_ctxt cx, common::span sp, str msg) -> ! {
cx.span_err(sp, msg);
}
auto parse_fmt_err = bind parse_fmt_err_(cx, fmtspan, _);
auto pieces = parse_fmt_string(fmt, parse_fmt_err);
auto args_len = vec::len[@ast::expr](args);
@ -49,52 +39,45 @@ fn expr_to_str(&ext_ctxt cx, @ast::expr expr) -> str {
alt (expr.node) {
case (ast::expr_lit(?l, _)) {
alt (l.node) {
case (ast::lit_str(?s,_)) { ret s; }
case (ast::lit_str(?s, _)) { ret s; }
case (_) { cx.span_err(l.span, err_msg); }
}
}
case (_) {
cx.span_err(expr.span, err_msg);
}
case (_) { cx.span_err(expr.span, err_msg); }
}
}
// FIXME: A lot of these functions for producing expressions can probably
// be factored out in common with other code that builds expressions.
// FIXME: Cleanup the naming of these functions
fn pieces_to_expr(&ext_ctxt cx, common::span sp,
vec[piece] pieces, vec[@ast::expr] args) -> @ast::expr {
fn make_new_lit(&ext_ctxt cx,
common::span sp, ast::lit_ lit) -> @ast::expr {
fn pieces_to_expr(&ext_ctxt cx, common::span sp, vec[piece] pieces,
vec[@ast::expr] args) -> @ast::expr {
fn make_new_lit(&ext_ctxt cx, common::span sp, ast::lit_ lit) ->
@ast::expr {
auto sp_lit = @rec(node=lit, span=sp);
auto expr = ast::expr_lit(sp_lit, cx.next_ann());
ret @rec(node=expr, span=sp);
}
fn make_new_str(&ext_ctxt cx, common::span sp, str s) -> @ast::expr {
auto lit = ast::lit_str(s, ast::sk_rc);
ret make_new_lit(cx, sp, lit);
}
fn make_new_int(&ext_ctxt cx, common::span sp, int i) -> @ast::expr {
auto lit = ast::lit_int(i);
ret make_new_lit(cx, sp, lit);
}
fn make_new_uint(&ext_ctxt cx, common::span sp, uint u) -> @ast::expr {
auto lit = ast::lit_uint(u);
ret make_new_lit(cx, sp, lit);
}
fn make_add_expr(&ext_ctxt cx, common::span sp,
@ast::expr lhs, @ast::expr rhs) -> @ast::expr {
fn make_add_expr(&ext_ctxt cx, common::span sp, @ast::expr lhs,
@ast::expr rhs) -> @ast::expr {
auto binexpr = ast::expr_binary(ast::add, lhs, rhs, cx.next_ann());
ret @rec(node=binexpr, span=sp);
}
fn make_path_expr(&ext_ctxt cx, common::span sp, vec[ast::ident] idents)
-> @ast::expr {
-> @ast::expr {
let vec[@ast::ty] types = [];
auto path = rec(idents=idents, types=types);
auto sp_path = rec(node=path, span=sp);
@ -102,15 +85,13 @@ fn pieces_to_expr(&ext_ctxt cx, common::span sp,
auto sp_pathexpr = @rec(node=pathexpr, span=sp);
ret sp_pathexpr;
}
fn make_vec_expr(&ext_ctxt cx, common::span sp, vec[@ast::expr] exprs)
-> @ast::expr {
auto vecexpr = ast::expr_vec(exprs, ast::imm, ast::sk_rc,
cx.next_ann());
fn make_vec_expr(&ext_ctxt cx, common::span sp, vec[@ast::expr] exprs) ->
@ast::expr {
auto vecexpr =
ast::expr_vec(exprs, ast::imm, ast::sk_rc, cx.next_ann());
auto sp_vecexpr = @rec(node=vecexpr, span=sp);
ret sp_vecexpr;
}
fn make_call(&ext_ctxt cx, common::span sp, vec[ast::ident] fn_path,
vec[@ast::expr] args) -> @ast::expr {
auto pathexpr = make_path_expr(cx, sp, fn_path);
@ -118,80 +99,64 @@ fn pieces_to_expr(&ext_ctxt cx, common::span sp,
auto sp_callexpr = @rec(node=callexpr, span=sp);
ret sp_callexpr;
}
fn make_rec_expr(&ext_ctxt cx, common::span sp,
vec[tup(ast::ident, @ast::expr)] fields) -> @ast::expr {
let vec[ast::field] astfields = [];
for (tup(ast::ident, @ast::expr) field in fields) {
auto ident = field._0;
auto val = field._1;
auto astfield = rec(node=rec(mut = ast::imm,
ident = ident,
expr = val), span=sp);
auto astfield =
rec(node=rec(mut=ast::imm, ident=ident, expr=val), span=sp);
astfields += [astfield];
}
auto recexpr = ast::expr_rec(astfields,
option::none[@ast::expr],
cx.next_ann());
auto recexpr =
ast::expr_rec(astfields, option::none[@ast::expr], cx.next_ann());
auto sp_recexpr = @rec(node=recexpr, span=sp);
ret sp_recexpr;
}
fn make_path_vec(str ident) -> vec[str] {
// FIXME: #fmt can't currently be used from within std
// because we're explicitly referencing the 'std' crate here
ret ["std", "extfmt", "rt", ident];
}
fn make_rt_path_expr(&ext_ctxt cx,
common::span sp, str ident) -> @ast::expr {
fn make_rt_path_expr(&ext_ctxt cx, common::span sp, str ident) ->
@ast::expr {
auto path = make_path_vec(ident);
ret make_path_expr(cx, sp, path);
}
// Produces an AST expression that represents a RT::conv record,
// which tells the RT::conv* functions how to perform the conversion
fn make_rt_conv_expr(&ext_ctxt cx,
common::span sp, &conv cnv) -> @ast::expr {
fn make_flags(&ext_ctxt cx, common::span sp, vec[flag] flags)
-> @ast::expr {
fn make_rt_conv_expr(&ext_ctxt cx, common::span sp, &conv cnv) ->
@ast::expr {
fn make_flags(&ext_ctxt cx, common::span sp, vec[flag] flags) ->
@ast::expr {
let vec[@ast::expr] flagexprs = [];
for (flag f in flags) {
auto fstr;
alt (f) {
case (flag_left_justify) {
fstr = "flag_left_justify";
}
case (flag_left_zero_pad) {
fstr = "flag_left_zero_pad";
}
case (flag_left_justify) { fstr = "flag_left_justify"; }
case (flag_left_zero_pad) { fstr = "flag_left_zero_pad"; }
case (flag_space_for_sign) {
fstr = "flag_space_for_sign";
}
case (flag_sign_always) {
fstr = "flag_sign_always";
}
case (flag_alternate) {
fstr = "flag_alternate";
}
case (flag_sign_always) { fstr = "flag_sign_always"; }
case (flag_alternate) { fstr = "flag_alternate"; }
}
flagexprs += [make_rt_path_expr(cx, sp, fstr)];
}
// FIXME: 0-length vectors can't have their type inferred
// through the rec that these flags are a member of, so
// this is a hack placeholder flag
if (vec::len[@ast::expr](flagexprs) == 0u) {
flagexprs += [make_rt_path_expr(cx, sp, "flag_none")];
}
ret make_vec_expr(cx, sp, flagexprs);
}
fn make_count(&ext_ctxt cx,
common::span sp, &count cnt) -> @ast::expr {
fn make_count(&ext_ctxt cx, common::span sp, &count cnt) ->
@ast::expr {
alt (cnt) {
case (count_implied) {
ret make_rt_path_expr(cx, sp, "count_implied");
@ -207,143 +172,96 @@ fn pieces_to_expr(&ext_ctxt cx, common::span sp,
}
}
}
fn make_ty(&ext_ctxt cx, common::span sp, &ty t) -> @ast::expr {
auto rt_type;
alt (t) {
case (ty_hex(?c)) {
alt (c) {
case (case_upper) {
rt_type = "ty_hex_upper";
}
case (case_lower) {
rt_type = "ty_hex_lower";
}
case (case_upper) { rt_type = "ty_hex_upper"; }
case (case_lower) { rt_type = "ty_hex_lower"; }
}
}
case (ty_bits) {
rt_type = "ty_bits";
}
case (ty_octal) {
rt_type = "ty_octal";
}
case (_) {
rt_type = "ty_default";
}
case (ty_bits) { rt_type = "ty_bits"; }
case (ty_octal) { rt_type = "ty_octal"; }
case (_) { rt_type = "ty_default"; }
}
ret make_rt_path_expr(cx, sp, rt_type);
}
fn make_conv_rec(&ext_ctxt cx,
common::span sp,
@ast::expr flags_expr,
@ast::expr width_expr,
@ast::expr precision_expr,
fn make_conv_rec(&ext_ctxt cx, common::span sp, @ast::expr flags_expr,
@ast::expr width_expr, @ast::expr precision_expr,
@ast::expr ty_expr) -> @ast::expr {
ret make_rec_expr(cx, sp, [tup("flags", flags_expr),
tup("width", width_expr),
tup("precision", precision_expr),
tup("ty", ty_expr)]);
ret make_rec_expr(cx, sp,
[tup("flags", flags_expr),
tup("width", width_expr),
tup("precision", precision_expr),
tup("ty", ty_expr)]);
}
auto rt_conv_flags = make_flags(cx, sp, cnv.flags);
auto rt_conv_width = make_count(cx, sp, cnv.width);
auto rt_conv_precision = make_count(cx, sp, cnv.precision);
auto rt_conv_ty = make_ty(cx, sp, cnv.ty);
ret make_conv_rec(cx,
sp,
rt_conv_flags,
rt_conv_width,
rt_conv_precision,
rt_conv_ty);
ret make_conv_rec(cx, sp, rt_conv_flags, rt_conv_width,
rt_conv_precision, rt_conv_ty);
}
fn make_conv_call(&ext_ctxt cx, common::span sp, str conv_type,
&conv cnv, @ast::expr arg) -> @ast::expr {
fn make_conv_call(&ext_ctxt cx, common::span sp, str conv_type, &conv cnv,
@ast::expr arg) -> @ast::expr {
auto fname = "conv_" + conv_type;
auto path = make_path_vec(fname);
auto cnv_expr = make_rt_conv_expr(cx, sp, cnv);
auto args = [cnv_expr, arg];
ret make_call(cx, arg.span, path, args);
}
fn make_new_conv(&ext_ctxt cx, common::span sp,
conv cnv, @ast::expr arg) -> @ast::expr {
fn make_new_conv(&ext_ctxt cx, common::span sp, conv cnv, @ast::expr arg)
-> @ast::expr {
// FIXME: Extract all this validation into extfmt::ct
fn is_signed_type(conv cnv) -> bool {
alt (cnv.ty) {
case (ty_int(?s)) {
alt (s) {
case (signed) {
ret true;
}
case (unsigned) {
ret false;
}
case (signed) { ret true; }
case (unsigned) { ret false; }
}
}
case (_) {
ret false;
}
case (_) { ret false; }
}
}
auto unsupported = "conversion not supported in #fmt string";
alt (cnv.param) {
case (option::none) {
}
case (_) {
cx.span_unimpl(sp, unsupported);
}
case (option::none) { }
case (_) { cx.span_unimpl(sp, unsupported); }
}
for (flag f in cnv.flags) {
alt (f) {
case (flag_left_justify) {
}
case (flag_left_justify) { }
case (flag_sign_always) {
if (!is_signed_type(cnv)) {
cx.span_err(sp, "+ flag only valid in "
+ "signed #fmt conversion");
cx.span_err(sp,
"+ flag only valid in " +
"signed #fmt conversion");
}
}
case (flag_space_for_sign) {
if (!is_signed_type(cnv)) {
cx.span_err(sp, "space flag only valid in "
+ "signed #fmt conversions");
cx.span_err(sp,
"space flag only valid in " +
"signed #fmt conversions");
}
}
case (flag_left_zero_pad) {
}
case (_) {
cx.span_unimpl(sp, unsupported);
}
case (flag_left_zero_pad) { }
case (_) { cx.span_unimpl(sp, unsupported); }
}
}
alt (cnv.width) {
case (count_implied) {
}
case (count_is(_)) {
}
case (_) {
cx.span_unimpl(sp, unsupported);
}
case (count_implied) { }
case (count_is(_)) { }
case (_) { cx.span_unimpl(sp, unsupported); }
}
alt (cnv.precision) {
case (count_implied) {
}
case (count_is(_)) {
}
case (_) {
cx.span_unimpl(sp, unsupported);
}
case (count_implied) { }
case (count_is(_)) { }
case (_) { cx.span_unimpl(sp, unsupported); }
}
alt (cnv.ty) {
case (ty_str) {
ret make_conv_call(cx, arg.span, "str", cnv, arg);
@ -373,38 +291,21 @@ fn pieces_to_expr(&ext_ctxt cx, common::span sp,
case (ty_octal) {
ret make_conv_call(cx, arg.span, "uint", cnv, arg);
}
case (_) {
cx.span_unimpl(sp, unsupported);
}
case (_) { cx.span_unimpl(sp, unsupported); }
}
}
fn log_conv(conv c) {
alt (c.param) {
case (some(?p)) {
log "param: " + std::int::to_str(p, 10u);
}
case (_) {
log "param: none";
}
case (some(?p)) { log "param: " + std::int::to_str(p, 10u); }
case (_) { log "param: none"; }
}
for (flag f in c.flags) {
alt (f) {
case (flag_left_justify) {
log "flag: left justify";
}
case (flag_left_zero_pad) {
log "flag: left zero pad";
}
case (flag_space_for_sign) {
log "flag: left space pad";
}
case (flag_sign_always) {
log "flag: sign always";
}
case (flag_alternate) {
log "flag: alternate";
}
case (flag_left_justify) { log "flag: left justify"; }
case (flag_left_zero_pad) { log "flag: left zero pad"; }
case (flag_space_for_sign) { log "flag: left space pad"; }
case (flag_sign_always) { log "flag: sign always"; }
case (flag_alternate) { log "flag: alternate"; }
}
}
alt (c.width) {
@ -414,12 +315,8 @@ fn pieces_to_expr(&ext_ctxt cx, common::span sp,
case (count_is_param(?i)) {
log "width: count is param " + std::int::to_str(i, 10u);
}
case (count_is_next_param) {
log "width: count is next param";
}
case (count_implied) {
log "width: count is implied";
}
case (count_is_next_param) { log "width: count is next param"; }
case (count_implied) { log "width: count is implied"; }
}
alt (c.precision) {
case (count_is(?i)) {
@ -428,57 +325,33 @@ fn pieces_to_expr(&ext_ctxt cx, common::span sp,
case (count_is_param(?i)) {
log "prec: count is param " + std::int::to_str(i, 10u);
}
case (count_is_next_param) {
log "prec: count is next param";
}
case (count_implied) {
log "prec: count is implied";
}
case (count_is_next_param) { log "prec: count is next param"; }
case (count_implied) { log "prec: count is implied"; }
}
alt (c.ty) {
case (ty_bool) {
log "type: bool";
}
case (ty_str) {
log "type: str";
}
case (ty_char) {
log "type: char";
}
case (ty_bool) { log "type: bool"; }
case (ty_str) { log "type: str"; }
case (ty_char) { log "type: char"; }
case (ty_int(?s)) {
alt (s) {
case (signed) {
log "type: signed";
}
case (unsigned) {
log "type: unsigned";
}
case (signed) { log "type: signed"; }
case (unsigned) { log "type: unsigned"; }
}
}
case (ty_bits) {
log "type: bits";
}
case (ty_bits) { log "type: bits"; }
case (ty_hex(?cs)) {
alt (cs) {
case (case_upper) {
log "type: uhex";
}
case (case_lower) {
log "type: lhex";
}
case (case_upper) { log "type: uhex"; }
case (case_lower) { log "type: lhex"; }
}
}
case (ty_octal) {
log "type: octal";
}
case (ty_octal) { log "type: octal"; }
}
}
auto fmt_sp = args.(0).span;
auto n = 0u;
auto tmp_expr = make_new_str(cx, sp, "");
auto nargs = vec::len[@ast::expr](args);
for (piece pc in pieces) {
alt (pc) {
case (piece_string(?s)) {
@ -487,32 +360,28 @@ fn pieces_to_expr(&ext_ctxt cx, common::span sp,
}
case (piece_conv(?conv)) {
n += 1u;
if (n >= nargs) {
cx.span_err(sp, "not enough arguments to #fmt "
+ "for the given format string");
cx.span_err(sp,
"not enough arguments to #fmt " +
"for the given format string");
}
log "Building conversion:";
log_conv(conv);
auto arg_expr = args.(n);
auto c_expr = make_new_conv(cx, fmt_sp, conv, arg_expr);
tmp_expr = make_add_expr(cx, fmt_sp, tmp_expr, c_expr);
}
}
}
auto expected_nargs = n + 1u; // n conversions + the fmt string
if (expected_nargs < nargs) {
cx.span_err(sp,
#fmt("too many arguments to #fmt. found %u, expected %u",
nargs, expected_nargs));
}
ret tmp_expr;
}
//
// Local Variables:
// mode: rust

View File

@ -1,3 +1,4 @@
import std::io;
import std::str;
import std::vec;
@ -11,59 +12,49 @@ import driver::session::session;
import util::common;
import util::common::*;
import util::data::interner;
import util::data::interner::intern;
state type reader = state obj {
fn is_eof() -> bool;
fn curr() -> char;
fn next() -> char;
fn init();
fn bump();
fn mark();
fn get_mark_chpos() -> uint;
fn get_mark_str() -> str;
fn get_interner() -> @interner::interner[str];
fn get_chpos() -> uint;
fn get_col() -> uint;
fn get_filemap() -> codemap::filemap;
fn err(str m);
};
type reader =
obj {
fn is_eof() -> bool ;
fn curr() -> char ;
fn next() -> char ;
fn init() ;
fn bump() ;
fn mark() ;
fn get_mark_chpos() -> uint ;
fn get_mark_str() -> str ;
fn get_interner() -> @interner::interner[str] ;
fn get_chpos() -> uint ;
fn get_col() -> uint ;
fn get_filemap() -> codemap::filemap ;
fn err(str) ;
};
fn new_reader(session sess, io::reader rdr,
codemap::filemap filemap,
fn new_reader(session sess, io::reader rdr, codemap::filemap filemap,
@interner::interner[str] itr) -> reader {
state obj reader(session sess,
str file,
uint len,
mutable uint col,
mutable uint pos,
mutable char ch,
mutable uint mark_chpos,
mutable uint chpos,
mutable vec[str] strs,
codemap::filemap fm,
@interner::interner[str] itr) {
fn is_eof() -> bool {
ret ch == -1 as char;
}
obj reader(session sess,
str file,
uint len,
mutable uint col,
mutable uint pos,
mutable char ch,
mutable uint mark_chpos,
mutable uint chpos,
mutable vec[str] strs,
codemap::filemap fm,
@interner::interner[str] itr) {
fn is_eof() -> bool { ret ch == -1 as char; }
fn mark() { mark_chpos = chpos; }
fn get_mark_str() -> str {
ret str::slice(file, mark_chpos, chpos);
}
fn get_mark_str() -> str { ret str::slice(file, mark_chpos, chpos); }
fn get_mark_chpos() -> uint { ret mark_chpos; }
fn get_chpos() -> uint { ret chpos; }
fn curr() -> char {
ret ch;
}
fn curr() -> char { ret ch; }
fn next() -> char {
if (pos < len) {ret str::char_at(file, pos);}
else {ret -1 as char;}
if (pos < len) {
ret str::char_at(file, pos);
} else { ret -1 as char; }
}
fn init() {
if (pos < len) {
auto next = str::char_range_at(file, pos);
@ -71,80 +62,47 @@ fn new_reader(session sess, io::reader rdr,
ch = next._0;
}
}
fn bump() {
if (pos < len) {
col += 1u;
chpos += 1u;
if (ch == '\n') {
codemap::next_line(fm, chpos);
col = 0u;
}
if (ch == '\n') { codemap::next_line(fm, chpos); col = 0u; }
auto next = str::char_range_at(file, pos);
pos = next._1;
ch = next._0;
} else {
ch = -1 as char;
}
} else { ch = -1 as char; }
}
fn get_interner() -> @interner::interner[str] { ret itr; }
fn get_col() -> uint {
ret col;
}
fn get_filemap() -> codemap::filemap {
ret fm;
}
fn err(str m) {
sess.span_err(rec(lo=chpos, hi=chpos), m);
}
fn get_col() -> uint { ret col; }
fn get_filemap() -> codemap::filemap { ret fm; }
fn err(str m) { sess.span_err(rec(lo=chpos, hi=chpos), m); }
}
auto file = str::unsafe_from_bytes(rdr.read_whole_stream());
let vec[str] strs = [];
auto rd = reader(sess, file, str::byte_len(file), 0u, 0u,
-1 as char, filemap.start_pos, filemap.start_pos,
strs, filemap, itr);
auto rd =
reader(sess, file, str::byte_len(file), 0u, 0u, -1 as char,
filemap.start_pos, filemap.start_pos, strs, filemap, itr);
rd.init();
ret rd;
}
fn dec_digit_val(char c) -> int {
ret (c as int) - ('0' as int);
}
fn dec_digit_val(char c) -> int { ret (c as int) - ('0' as int); }
fn hex_digit_val(char c) -> int {
if (in_range(c, '0', '9')) {
ret (c as int) - ('0' as int);
}
if (in_range(c, 'a', 'f')) {
ret ((c as int) - ('a' as int)) + 10;
}
if (in_range(c, 'A', 'F')) {
ret ((c as int) - ('A' as int)) + 10;
}
if (in_range(c, '0', '9')) { ret (c as int) - ('0' as int); }
if (in_range(c, 'a', 'f')) { ret (c as int) - ('a' as int) + 10; }
if (in_range(c, 'A', 'F')) { ret (c as int) - ('A' as int) + 10; }
fail;
}
fn bin_digit_value(char c) -> int {
if (c == '0') { ret 0; }
ret 1;
}
fn bin_digit_value(char c) -> int { if (c == '0') { ret 0; } ret 1; }
fn is_whitespace(char c) -> bool {
ret c == ' ' || c == '\t' || c == '\r' || c == '\n';
}
fn consume_whitespace_and_comments(&reader rdr) {
while (is_whitespace(rdr.curr())) {
rdr.bump();
}
while (is_whitespace(rdr.curr())) { rdr.bump(); }
be consume_any_line_comment(rdr);
}
@ -152,10 +110,9 @@ fn consume_any_line_comment(&reader rdr) {
if (rdr.curr() == '/') {
alt (rdr.next()) {
case ('/') {
while (rdr.curr() != '\n' && !rdr.is_eof()) {
rdr.bump();
}
while (rdr.curr() != '\n' && !rdr.is_eof()) { rdr.bump(); }
// Restart whitespace munch.
be consume_whitespace_and_comments(rdr);
}
case ('*') {
@ -163,21 +120,15 @@ fn consume_any_line_comment(&reader rdr) {
rdr.bump();
be consume_block_comment(rdr);
}
case (_) {
ret;
}
case (_) { ret; }
}
}
}
fn consume_block_comment(&reader rdr) {
let int level = 1;
while (level > 0) {
if (rdr.is_eof()) {
rdr.err("unterminated block comment");
fail;
}
if (rdr.is_eof()) { rdr.err("unterminated block comment"); fail; }
if (rdr.curr() == '/' && rdr.next() == '*') {
rdr.bump();
rdr.bump();
@ -187,32 +138,27 @@ fn consume_block_comment(&reader rdr) {
rdr.bump();
rdr.bump();
level -= 1;
} else {
rdr.bump();
}
} else { rdr.bump(); }
}
}
// restart whitespace munch.
be consume_whitespace_and_comments(rdr);
}
fn digits_to_string(str s) -> int {
let int accum_int = 0;
let int i = 0;
for (u8 c in s) {
accum_int *= 10;
accum_int += dec_digit_val(c as char);
}
ret accum_int;
}
fn scan_exponent(&reader rdr) -> option::t[str] {
auto c = rdr.curr();
auto res = "";
if (c == 'e' || c == 'E') {
res += str::from_bytes([c as u8]);
rdr.bump();
@ -223,31 +169,19 @@ fn scan_exponent(&reader rdr) -> option::t[str] {
}
auto exponent = scan_dec_digits(rdr);
if (str::byte_len(exponent) > 0u) {
ret(some(res + exponent));
}
else {
rdr.err("scan_exponent: bad fp literal");
fail;
}
}
else {
ret none[str];
}
ret some(res + exponent);
} else { rdr.err("scan_exponent: bad fp literal"); fail; }
} else { ret none[str]; }
}
fn scan_dec_digits(&reader rdr) -> str {
auto c = rdr.curr();
let str res = "";
while (is_dec_digit (c) || c == '_') {
if (c != '_') {
res += str::from_bytes([c as u8]);
}
while (is_dec_digit(c) || c == '_') {
if (c != '_') { res += str::from_bytes([c as u8]); }
rdr.bump();
c = rdr.curr();
}
ret res;
}
@ -256,16 +190,12 @@ fn scan_number(char c, &reader rdr) -> token::token {
let str dec_str = "";
let bool is_dec_integer = false;
auto n = rdr.next();
if (c == '0' && n == 'x') {
rdr.bump();
rdr.bump();
c = rdr.curr();
while (is_hex_digit(c) || c == '_') {
if (c != '_') {
accum_int *= 16;
accum_int += hex_digit_val(c);
}
if (c != '_') { accum_int *= 16; accum_int += hex_digit_val(c); }
rdr.bump();
c = rdr.curr();
}
@ -274,125 +204,100 @@ fn scan_number(char c, &reader rdr) -> token::token {
rdr.bump();
c = rdr.curr();
while (is_bin_digit(c) || c == '_') {
if (c != '_') {
accum_int *= 2;
accum_int += bin_digit_value(c);
}
if (c != '_') { accum_int *= 2; accum_int += bin_digit_value(c); }
rdr.bump();
c = rdr.curr();
}
} else {
dec_str = scan_dec_digits(rdr);
is_dec_integer = true;
}
if (is_dec_integer) {
accum_int = digits_to_string(dec_str);
}
} else { dec_str = scan_dec_digits(rdr); is_dec_integer = true; }
if (is_dec_integer) { accum_int = digits_to_string(dec_str); }
c = rdr.curr();
n = rdr.next();
if (c == 'u' || c == 'i') {
let bool signed = (c == 'i');
let bool signed = c == 'i';
rdr.bump();
c = rdr.curr();
if (c == '8') {
rdr.bump();
if (signed) {
ret token::LIT_MACH_INT(common::ty_i8, accum_int);
} else {
ret token::LIT_MACH_INT(common::ty_u8, accum_int);
}
} else { ret token::LIT_MACH_INT(common::ty_u8, accum_int); }
}
n = rdr.next();
if (c == '1' && n == '6') {
rdr.bump();
rdr.bump();
if (signed) {
ret token::LIT_MACH_INT(common::ty_i16, accum_int);
} else {
ret token::LIT_MACH_INT(common::ty_u16, accum_int);
}
} else { ret token::LIT_MACH_INT(common::ty_u16, accum_int); }
}
if (c == '3' && n == '2') {
rdr.bump();
rdr.bump();
if (signed) {
ret token::LIT_MACH_INT(common::ty_i32, accum_int);
} else {
ret token::LIT_MACH_INT(common::ty_u32, accum_int);
}
} else { ret token::LIT_MACH_INT(common::ty_u32, accum_int); }
}
if (c == '6' && n == '4') {
rdr.bump();
rdr.bump();
if (signed) {
ret token::LIT_MACH_INT(common::ty_i64, accum_int);
} else {
ret token::LIT_MACH_INT(common::ty_u64, accum_int);
}
} else { ret token::LIT_MACH_INT(common::ty_u64, accum_int); }
}
if (signed) {
ret token::LIT_INT(accum_int);
} else {
// FIXME: should cast in the target bit-width.
ret token::LIT_UINT(accum_int as uint);
}
}
c = rdr.curr();
if (c == '.') {
// Parse a floating-point number.
rdr.bump();
auto dec_part = scan_dec_digits(rdr);
auto float_str = dec_str + "." + dec_part;
c = rdr.curr();
auto exponent_str = scan_exponent(rdr);
alt (exponent_str) {
case (some(?s)) {
float_str += s;
}
case (none) {
}
case (some(?s)) { float_str += s; }
case (none) { }
}
c = rdr.curr();
if (c == 'f') {
rdr.bump();
c = rdr.curr();
n = rdr.next();
if (c == '3' && n == '2') {
rdr.bump(); rdr.bump();
rdr.bump();
rdr.bump();
ret token::LIT_MACH_FLOAT(util::common::ty_f32,
interner::intern[str](*rdr.get_interner(), float_str));
}
else if (c == '6' && n == '4') {
rdr.bump(); rdr.bump();
intern(*rdr.get_interner(),
float_str));
} else if (c == '6' && n == '4') {
rdr.bump();
rdr.bump();
ret token::LIT_MACH_FLOAT(util::common::ty_f64,
interner::intern[str](*rdr.get_interner(), float_str));
intern(*rdr.get_interner(),
float_str));
/* FIXME: if this is out of range for either a 32-bit or
64-bit float, it won't be noticed till the back-end */
}
}
else {
} else {
ret token::LIT_FLOAT(interner::intern[str](*rdr.get_interner(),
float_str));
}
}
auto maybe_exponent = scan_exponent(rdr);
alt(maybe_exponent) {
case(some(?s)) {
alt (maybe_exponent) {
case (some(?s)) {
ret token::LIT_FLOAT(interner::intern[str](*rdr.get_interner(),
dec_str + s));
}
case(none) {
ret token::LIT_INT(accum_int);
}
case (none) { ret token::LIT_INT(accum_int); }
}
}
@ -412,50 +317,38 @@ fn scan_numeric_escape(&reader rdr, uint n_hex_digits) -> char {
ret accum_int as char;
}
fn next_token(&reader rdr) -> token::token {
auto accum_str = "";
consume_whitespace_and_comments(rdr);
if (rdr.is_eof()) { ret token::EOF; }
rdr.mark();
auto c = rdr.curr();
if (is_alpha(c) || c == '_') {
while (is_alnum(c) || c == '_') {
str::push_char(accum_str, c);
rdr.bump();
c = rdr.curr();
}
if (str::eq(accum_str, "_")) {
ret token::UNDERSCORE;
}
if (str::eq(accum_str, "_")) { ret token::UNDERSCORE; }
auto is_mod_name = c == ':' && rdr.next() == ':';
ret token::IDENT(interner::intern[str](*rdr.get_interner(),
accum_str), is_mod_name);
}
if (is_dec_digit(c)) {
ret scan_number(c, rdr);
}
if (is_dec_digit(c)) { ret scan_number(c, rdr); }
fn binop(&reader rdr, token::binop op) -> token::token {
rdr.bump();
if (rdr.curr() == '=') {
rdr.bump();
ret token::BINOPEQ(op);
} else {
ret token::BINOP(op);
}
} else { ret token::BINOP(op); }
}
alt (c) {
// One-byte tokens.
case ('?') { rdr.bump(); ret token::QUES; }
case (
// One-byte tokens.
'?') {
rdr.bump();
ret token::QUES;
}
case (';') { rdr.bump(); ret token::SEMI; }
case (',') { rdr.bump(); ret token::COMMA; }
case ('.') { rdr.bump(); ret token::DOT; }
@ -473,80 +366,47 @@ fn next_token(&reader rdr) -> token::token {
if (rdr.curr() == ':') {
rdr.bump();
ret token::MOD_SEP;
}
else {
ret token::COLON;
};
} else { ret token::COLON; }
}
// Multi-byte tokens.
case ('=') {
case (
// Multi-byte tokens.
'=') {
rdr.bump();
if (rdr.curr() == '=') {
rdr.bump();
ret token::EQEQ;
} else {
ret token::EQ;
}
} else { ret token::EQ; }
}
case ('!') {
rdr.bump();
if (rdr.curr() == '=') {
rdr.bump();
ret token::NE;
} else {
ret token::NOT;
}
} else { ret token::NOT; }
}
case ('<') {
rdr.bump();
alt (rdr.curr()) {
case ('=') {
rdr.bump();
ret token::LE;
}
case ('<') {
ret binop(rdr, token::LSL);
}
case ('-') {
rdr.bump();
ret token::LARROW;
}
case ('|') {
rdr.bump();
ret token::SEND;
}
case (_) {
ret token::LT;
}
case ('=') { rdr.bump(); ret token::LE; }
case ('<') { ret binop(rdr, token::LSL); }
case ('-') { rdr.bump(); ret token::LARROW; }
case ('|') { rdr.bump(); ret token::SEND; }
case (_) { ret token::LT; }
}
}
case ('>') {
rdr.bump();
alt (rdr.curr()) {
case ('=') {
rdr.bump();
ret token::GE;
}
case ('=') { rdr.bump(); ret token::GE; }
case ('>') {
if (rdr.next() == '>') {
rdr.bump();
ret binop(rdr, token::ASR);
} else {
ret binop(rdr, token::LSR);
}
}
case (_) {
ret token::GT;
} else { ret binop(rdr, token::LSR); }
}
case (_) { ret token::GT; }
}
}
case ('\'') {
rdr.bump();
auto c2 = rdr.curr();
@ -560,11 +420,9 @@ fn next_token(&reader rdr) -> token::token {
case ('t') { c2 = '\t'; }
case ('\\') { c2 = '\\'; }
case ('\'') { c2 = '\''; }
case ('x') { c2 = scan_numeric_escape(rdr, 2u); }
case ('u') { c2 = scan_numeric_escape(rdr, 4u); }
case ('U') { c2 = scan_numeric_escape(rdr, 8u); }
case (?c2) {
rdr.err(#fmt("unknown character escape: %d",
c2 as int));
@ -572,15 +430,14 @@ fn next_token(&reader rdr) -> token::token {
}
}
}
if (rdr.curr() != '\'') {
rdr.err("unterminated character constant");
fail;
}
rdr.bump(); // advance curr past token
ret token::LIT_CHAR(c2);
}
case ('"') {
rdr.bump();
while (rdr.curr() != '"') {
@ -606,25 +463,19 @@ fn next_token(&reader rdr) -> token::token {
case ('"') {
str::push_byte(accum_str, '"' as u8);
}
case ('\n') {
consume_whitespace(rdr);
}
case ('\n') { consume_whitespace(rdr); }
case ('x') {
str::push_char(accum_str,
scan_numeric_escape(rdr, 2u));
}
case ('u') {
str::push_char(accum_str,
scan_numeric_escape(rdr, 4u));
}
case ('U') {
str::push_char(accum_str,
scan_numeric_escape(rdr, 8u));
}
case (?c2) {
rdr.err(#fmt("unknown string escape: %d",
c2 as int));
@ -632,88 +483,54 @@ fn next_token(&reader rdr) -> token::token {
}
}
}
case (_) {
str::push_char(accum_str, ch);
}
case (_) { str::push_char(accum_str, ch); }
}
}
rdr.bump();
ret token::LIT_STR(interner::intern[str](*rdr.get_interner(),
accum_str));
}
case ('-') {
if (rdr.next() == '>') {
rdr.bump();
rdr.bump();
ret token::RARROW;
} else {
ret binop(rdr, token::MINUS);
}
} else { ret binop(rdr, token::MINUS); }
}
case ('&') {
if (rdr.next() == '&') {
rdr.bump();
rdr.bump();
ret token::ANDAND;
} else {
ret binop(rdr, token::AND);
}
} else { ret binop(rdr, token::AND); }
}
case ('|') {
alt (rdr.next()) {
case ('|') {
rdr.bump();
rdr.bump();
ret token::OROR;
}
case ('>') {
rdr.bump();
rdr.bump();
ret token::RECV;
}
case (_) {
ret binop(rdr, token::OR);
}
case ('|') { rdr.bump(); rdr.bump(); ret token::OROR; }
case ('>') { rdr.bump(); rdr.bump(); ret token::RECV; }
case (_) { ret binop(rdr, token::OR); }
}
}
case ('+') {
ret binop(rdr, token::PLUS);
}
case ('*') {
ret binop(rdr, token::STAR);
}
case ('/') {
ret binop(rdr, token::SLASH);
}
case ('^') {
ret binop(rdr, token::CARET);
}
case ('%') {
ret binop(rdr, token::PERCENT);
}
case ('+') { ret binop(rdr, token::PLUS); }
case ('*') { ret binop(rdr, token::STAR); }
case ('/') { ret binop(rdr, token::SLASH); }
case ('^') { ret binop(rdr, token::CARET); }
case ('%') { ret binop(rdr, token::PERCENT); }
case (?c) {
rdr.err(#fmt("unkown start of token: %d", c as int));
fail;
}
}
fail;
}
tag cmnt_style {
isolated; // No code on either side of each line of the comment
trailing; // Code exists to the left of the comment
mixed; // Code before /* foo */ and after the comment
isolated; // No code on either side of each line of the comment
trailing; // Code exists to the left of the comment
mixed; // Code before /* foo */ and after the comment
}
type cmnt = rec(cmnt_style style, vec[str] lines, uint pos);
@ -724,80 +541,64 @@ fn read_to_eol(&reader rdr) -> str {
str::push_char(val, rdr.curr());
rdr.bump();
}
if (rdr.curr() == '\n') {
rdr.bump();
} else {
assert rdr.is_eof();
}
if (rdr.curr() == '\n') { rdr.bump(); } else { assert (rdr.is_eof()); }
ret val;
}
fn read_one_line_comment(&reader rdr) -> str {
auto val = read_to_eol(rdr);
assert val.(0) == ('/' as u8) && val.(1) == ('/' as u8);
assert (val.(0) == '/' as u8 && val.(1) == '/' as u8);
ret val;
}
fn consume_whitespace(&reader rdr) {
while (is_whitespace(rdr.curr()) && !rdr.is_eof()) {
rdr.bump();
}
while (is_whitespace(rdr.curr()) && !rdr.is_eof()) { rdr.bump(); }
}
fn consume_non_eol_whitespace(&reader rdr) {
while (is_whitespace(rdr.curr()) &&
rdr.curr() != '\n' && !rdr.is_eof()) {
while (is_whitespace(rdr.curr()) && rdr.curr() != '\n' && !rdr.is_eof()) {
rdr.bump();
}
}
fn read_line_comments(&reader rdr, bool code_to_the_left) -> cmnt {
log ">>> line comments";
auto p = rdr.get_chpos();
let vec[str] lines = [];
while (rdr.curr() == '/' && rdr.next() == '/') {
auto line = read_one_line_comment(rdr);
auto line = read_one_line_comment(rdr);
log line;
lines += [line];
consume_non_eol_whitespace(rdr);
}
log "<<< line comments";
ret rec(style = if (code_to_the_left) { trailing } else { isolated },
lines = lines,
ret rec(style=if (code_to_the_left) { trailing } else { isolated },
lines=lines,
pos=p);
}
fn all_whitespace(&str s, uint begin, uint end) -> bool {
let uint i = begin;
while (i != end) {
if (!is_whitespace(s.(i) as char)) {
ret false;
}
if (!is_whitespace(s.(i) as char)) { ret false; }
i += 1u;
}
ret true;
}
fn trim_whitespace_prefix_and_push_line(&mutable vec[str] lines,
&str s, uint col) {
fn trim_whitespace_prefix_and_push_line(&mutable vec[str] lines, &str s,
uint col) {
auto s1;
if (all_whitespace(s, 0u, col)) {
if (col < str::byte_len(s)) {
s1 = str::slice(s, col, str::byte_len(s));
} else {
s1 = "";
}
} else {
s1 = s;
}
} else { s1 = ""; }
} else { s1 = s; }
log "pushing line: " + s1;
lines += [s1];
}
fn read_block_comment(&reader rdr,
bool code_to_the_left) -> cmnt {
fn read_block_comment(&reader rdr, bool code_to_the_left) -> cmnt {
log ">>> block comment";
auto p = rdr.get_chpos();
let vec[str] lines = [];
@ -808,10 +609,7 @@ fn read_block_comment(&reader rdr,
let int level = 1;
while (level > 0) {
log #fmt("=== block comment level %d", level);
if (rdr.is_eof()) {
rdr.err("unterminated block comment");
fail;
}
if (rdr.is_eof()) { rdr.err("unterminated block comment"); fail; }
if (rdr.curr() == '\n') {
trim_whitespace_prefix_and_push_line(lines, curr_line, col);
curr_line = "";
@ -829,63 +627,56 @@ fn read_block_comment(&reader rdr,
rdr.bump();
curr_line += "/";
level -= 1;
} else {
rdr.bump();
}
} else { rdr.bump(); }
}
}
}
if (str::byte_len(curr_line) != 0u) {
trim_whitespace_prefix_and_push_line(lines, curr_line, col);
}
auto style = if (code_to_the_left) { trailing } else { isolated };
consume_non_eol_whitespace(rdr);
if (!rdr.is_eof() &&
rdr.curr() != '\n' &&
vec::len(lines) == 1u) {
if (!rdr.is_eof() && rdr.curr() != '\n' && vec::len(lines) == 1u) {
style = mixed;
}
log "<<< block comment";
ret rec(style = style, lines = lines, pos=p);
ret rec(style=style, lines=lines, pos=p);
}
fn peeking_at_comment(&reader rdr) -> bool {
ret (rdr.curr() == '/' && rdr.next() == '/') ||
(rdr.curr() == '/' && rdr.next() == '*');
ret rdr.curr() == '/' && rdr.next() == '/' ||
rdr.curr() == '/' && rdr.next() == '*';
}
fn consume_comment(&reader rdr, bool code_to_the_left,
&mutable vec[cmnt] comments) {
log ">>> consume comment";
if (rdr.curr() == '/' && rdr.next() == '/') {
vec::push[cmnt](comments,
read_line_comments(rdr, code_to_the_left));
vec::push[cmnt](comments, read_line_comments(rdr, code_to_the_left));
} else if (rdr.curr() == '/' && rdr.next() == '*') {
vec::push[cmnt](comments,
read_block_comment(rdr, code_to_the_left));
vec::push[cmnt](comments, read_block_comment(rdr, code_to_the_left));
} else { fail; }
log "<<< consume comment";
}
fn is_lit(&token::token t) -> bool {
ret alt (t) {
case (token::LIT_INT(_)) { true }
case (token::LIT_UINT(_)) { true }
case (token::LIT_MACH_INT(_,_)) { true }
case (token::LIT_FLOAT(_)) { true }
case (token::LIT_MACH_FLOAT(_,_)) { true }
case (token::LIT_STR(_)) { true }
case (token::LIT_CHAR(_)) { true }
case (token::LIT_BOOL(_)) { true }
case (_) { false }
}
case (token::LIT_INT(_)) { true }
case (token::LIT_UINT(_)) { true }
case (token::LIT_MACH_INT(_, _)) { true }
case (token::LIT_FLOAT(_)) { true }
case (token::LIT_MACH_FLOAT(_, _)) { true }
case (token::LIT_STR(_)) { true }
case (token::LIT_CHAR(_)) { true }
case (token::LIT_BOOL(_)) { true }
case (_) { false }
}
}
type lit = rec(str lit, uint pos);
fn gather_comments_and_literals(session sess, str path)
-> rec(vec[cmnt] cmnts, vec[lit] lits) {
fn gather_comments_and_literals(session sess, str path) ->
rec(vec[cmnt] cmnts, vec[lit] lits) {
auto srdr = io::file_reader(path);
auto itr = @interner::mk[str](str::hash, str::eq);
auto rdr = new_reader(sess, srdr, codemap::new_filemap(path, 0u), itr);
@ -907,15 +698,14 @@ fn gather_comments_and_literals(session sess, str path)
break;
}
if (is_lit(next_token(rdr))) {
vec::push[lit](literals, rec(lit=rdr.get_mark_str(),
pos=rdr.get_mark_chpos()));
vec::push[lit](literals,
rec(lit=rdr.get_mark_str(),
pos=rdr.get_mark_chpos()));
}
first_read = false;
}
ret rec(cmnts=comments, lits=literals);
}
}
//
// Local Variables:
// mode: rust

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +1,4 @@
import util::common::ty_mach;
import util::common::ty_mach_to_str;
import util::common::new_str_hash;
@ -23,6 +24,7 @@ tag binop {
}
tag token {
/* Expression-operator symbols. */
EQ;
LT;
@ -35,7 +37,6 @@ tag token {
OROR;
NOT;
TILDE;
BINOP(binop);
BINOPEQ(binop);
@ -57,7 +58,6 @@ tag token {
RBRACKET;
LBRACE;
RBRACE;
POUND;
/* Literals */
@ -74,7 +74,6 @@ tag token {
IDENT(str_num, bool);
IDX(int);
UNDERSCORE;
BRACEQUOTE(str_num);
EOF;
}
@ -97,7 +96,6 @@ fn binop_to_str(binop o) -> str {
fn to_str(lexer::reader r, token t) -> str {
alt (t) {
case (EQ) { ret "="; }
case (LT) { ret "<"; }
case (LE) { ret "<="; }
@ -109,12 +107,13 @@ fn to_str(lexer::reader r, token t) -> str {
case (TILDE) { ret "~"; }
case (OROR) { ret "||"; }
case (ANDAND) { ret "&&"; }
case (BINOP(?op)) { ret binop_to_str(op); }
case (BINOPEQ(?op)) { ret binop_to_str(op) + "="; }
/* Structural symbols */
case (AT) { ret "@"; }
case (
/* Structural symbols */
AT) {
ret "@";
}
case (DOT) { ret "."; }
case (COMMA) { ret ","; }
case (SEMI) { ret ";"; }
@ -131,49 +130,46 @@ fn to_str(lexer::reader r, token t) -> str {
case (RBRACKET) { ret "]"; }
case (LBRACE) { ret "{"; }
case (RBRACE) { ret "}"; }
case (POUND) { ret "#"; }
/* Literals */
case (LIT_INT(?i)) { ret int::to_str(i, 10u); }
case (
/* Literals */
LIT_INT(?i)) {
ret int::to_str(i, 10u);
}
case (LIT_UINT(?u)) { ret uint::to_str(u, 10u); }
case (LIT_MACH_INT(?tm, ?i)) {
ret int::to_str(i, 10u)
+ "_" + ty_mach_to_str(tm);
ret int::to_str(i, 10u) + "_" + ty_mach_to_str(tm);
}
case (LIT_MACH_FLOAT(?tm, ?s)) {
ret interner::get[str](*r.get_interner(), s) + "_" +
ty_mach_to_str(tm);
ty_mach_to_str(tm);
}
case (LIT_FLOAT(?s)) { ret interner::get[str](*r.get_interner(), s); }
case (LIT_STR(?s)) {
// FIXME: escape.
ret "\"" + interner::get[str](*r.get_interner(), s) + "\"";
}
case (LIT_CHAR(?c)) {
// FIXME: escape.
auto tmp = "'";
str::push_char(tmp, c);
str::push_byte(tmp, '\'' as u8);
ret tmp;
}
case (LIT_BOOL(?b)) {
if (b) { ret "true"; } else { ret "false"; }
case (LIT_BOOL(?b)) { if (b) { ret "true"; } else { ret "false"; } }
case (
/* Name components */
IDENT(?s, _)) {
ret interner::get[str](*r.get_interner(), s);
}
/* Name components */
case (IDENT(?s, _)) { ret interner::get[str](*r.get_interner(), s); }
case (IDX(?i)) { ret "_" + int::to_str(i, 10u); }
case (UNDERSCORE) { ret "_"; }
case (BRACEQUOTE(_)) { ret "<bracequote>"; }
case (EOF) { ret "<eof>"; }
}
}
// Local Variables:
// fill-column: 78;
// indent-tabs-mode: nil

View File

@ -1,3 +1,4 @@
import front::ast;
import front::ast::ident;
import front::ast::def_num;
@ -10,6 +11,7 @@ import std::option::some;
import std::option::none;
import std::option::is_none;
// This is not an alias-analyser (though it would merit from becoming one, or
// at getting input from one, to be more precise). It is a pass that checks
// whether aliases are used in a safe way. Beyond that, though it doesn't have
@ -17,40 +19,38 @@ import std::option::is_none;
// (using an lval, which is actually mutable), since it already has all the
// information needed to do that (and the typechecker, which would be a
// logical place for such a check, doesn't).
tag valid { valid; overwritten(span, ast::path); val_taken(span, ast::path); }
tag valid {
valid;
overwritten(span, ast::path);
val_taken(span, ast::path);
}
type restrict =
@rec(vec[def_num] root_vars,
def_num block_defnum,
vec[def_num] bindings,
vec[ty::t] tys,
vec[uint] depends_on,
mutable valid ok);
type restrict = @rec(vec[def_num] root_vars,
def_num block_defnum,
vec[def_num] bindings,
vec[ty::t] tys,
vec[uint] depends_on,
mutable valid ok);
type scope = vec[restrict];
tag local_info {
arg(ast::mode);
objfield(ast::mutability);
}
tag local_info { arg(ast::mode); objfield(ast::mutability); }
type ctx = rec(@ty::ctxt tcx,
resolve::def_map dm,
std::map::hashmap[def_num,local_info] local_map);
type ctx =
rec(@ty::ctxt tcx,
resolve::def_map dm,
std::map::hashmap[def_num, local_info] local_map);
fn check_crate(@ty::ctxt tcx, resolve::def_map dm, &@ast::crate crate) {
auto cx = @rec(tcx = tcx,
dm = dm,
// Stores information about object fields and function
// arguments that's otherwise not easily available.
local_map = util::common::new_int_hash());
auto v = @rec(visit_fn = bind visit_fn(cx, _, _, _, _, _, _, _, _),
visit_item = bind visit_item(cx, _, _, _),
visit_expr = bind visit_expr(cx, _, _, _)
with *visit::default_visitor[scope]());
auto cx =
@rec(tcx=tcx,
dm=dm,
// Stores information about object fields and function
// arguments that's otherwise not easily available.
local_map=util::common::new_int_hash());
auto v =
@rec(visit_fn=bind visit_fn(cx, _, _, _, _, _, _, _, _),
visit_item=bind visit_item(cx, _, _, _),
visit_expr=bind visit_expr(cx, _, _, _)
with *visit::default_visitor[scope]());
visit::visit_crate(*crate, [], visit::vtor(v));
}
@ -71,7 +71,7 @@ fn visit_item(@ctx cx, &@ast::item i, &scope sc, &vt[scope] v) {
cx.local_map.insert(f.id._1, objfield(f.mut));
}
}
case (_) {}
case (_) { }
}
visit::visit_item(i, sc, v);
}
@ -79,9 +79,7 @@ fn visit_item(@ctx cx, &@ast::item i, &scope sc, &vt[scope] v) {
fn visit_expr(@ctx cx, &@ast::expr ex, &scope sc, &vt[scope] v) {
auto handled = false;
alt (ex.node) {
case (ast::expr_call(?f, ?args, _)) {
check_call(*cx, f, args, sc);
}
case (ast::expr_call(?f, ?args, _)) { check_call(*cx, f, args, sc); }
case (ast::expr_alt(?input, ?arms, _)) {
check_alt(*cx, input, arms, sc, v);
handled = true;
@ -91,13 +89,13 @@ fn visit_expr(@ctx cx, &@ast::expr ex, &scope sc, &vt[scope] v) {
case (some(?ex)) {
auto root = expr_root(*cx, ex, false);
if (mut_field(root.ds)) {
cx.tcx.sess.span_err
(ex.span,
"result of put must be immutably rooted");
cx.tcx.sess.span_err(ex.span,
"result of put must be"
+ " immutably rooted");
}
visit_expr(cx, ex, sc, v);
}
case (_) {}
case (_) { }
}
handled = true;
}
@ -109,7 +107,6 @@ fn visit_expr(@ctx cx, &@ast::expr ex, &scope sc, &vt[scope] v) {
check_for(*cx, decl, seq, block, sc, v);
handled = true;
}
case (ast::expr_path(?pt, ?ann)) {
check_var(*cx, ex, pt, ann, false, sc);
}
@ -125,25 +122,23 @@ fn visit_expr(@ctx cx, &@ast::expr ex, &scope sc, &vt[scope] v) {
check_assign(cx, dest, src, sc, v);
handled = true;
}
case (_) {}
case (_) { }
}
if (!handled) { visit::visit_expr(ex, sc, v); }
}
fn check_call(&ctx cx, &@ast::expr f, &vec[@ast::expr] args, &scope sc)
-> rec(vec[def_num] root_vars, vec[ty::t] unsafe_ts) {
fn check_call(&ctx cx, &@ast::expr f, &vec[@ast::expr] args, &scope sc) ->
rec(vec[def_num] root_vars, vec[ty::t] unsafe_ts) {
auto fty = ty::expr_ty(*cx.tcx, f);
auto arg_ts = alt (ty::struct(*cx.tcx, fty)) {
case (ty::ty_fn(_, ?args, _, _, _)) { args }
case (ty::ty_native_fn(_, ?args, _)) { args }
};
auto arg_ts =
alt (ty::struct(*cx.tcx, fty)) {
case (ty::ty_fn(_, ?args, _, _, _)) { args }
case (ty::ty_native_fn(_, ?args, _)) { args }
};
let vec[def_num] roots = [];
let vec[tup(uint, def_num)] mut_roots = [];
let vec[ty::t] unsafe_ts = [];
let vec[uint] unsafe_t_offsets = [];
auto i = 0u;
for (ty::arg arg_t in arg_ts) {
if (arg_t.mode != ty::mo_val) {
@ -156,39 +151,38 @@ fn check_call(&ctx cx, &@ast::expr f, &vec[@ast::expr] args, &scope sc)
}
case (_) {
if (!mut_field(root.ds)) {
cx.tcx.sess.span_err
(arg.span, "passing a temporary value or \
immutable field by mutable alias");
auto m = "passing a temporary value or \
immutable field by mutable alias";
cx.tcx.sess.span_err(arg.span, m);
}
}
}
}
alt (path_def_id(cx, root.ex)) {
case (some(?did)) { vec::push(roots, did._1); }
case (_) {}
case (_) { }
}
alt (inner_mut(root.ds)) {
case (some(?t)) {
vec::push(unsafe_ts, t);
vec::push(unsafe_t_offsets, i);
}
case (_) {}
case (_) { }
}
}
i += 1u;
}
if (vec::len(unsafe_ts) > 0u) {
alt (f.node) {
case (ast::expr_path(_, ?ann)) {
if (def_is_local(cx.dm.get(ann.id))) {
cx.tcx.sess.span_err
(f.span, #fmt("function may alias with argument \
%u, which is not immutably rooted",
unsafe_t_offsets.(0)));
cx.tcx.sess.span_err(f.span,
#fmt("function may alias with \
argument %u, which is not immutably rooted",
unsafe_t_offsets.(0)));
}
}
case (_) {}
case (_) { }
}
}
auto j = 0u;
@ -199,16 +193,18 @@ fn check_call(&ctx cx, &@ast::expr f, &vec[@ast::expr] args, &scope sc)
for (ty::arg arg_t in arg_ts) {
auto mut_alias = arg_t.mode == ty::mo_alias(true);
if (i != offset &&
ty_can_unsafely_include(cx, unsafe, arg_t.ty, mut_alias)) {
cx.tcx.sess.span_err
(args.(i).span, #fmt("argument %u may alias with \
argument %u, which is not immutably rooted", i, offset));
ty_can_unsafely_include(cx, unsafe, arg_t.ty, mut_alias))
{
cx.tcx.sess.span_err(args.(i).span,
#fmt("argument %u may alias with \
argument %u, which is not immutably rooted",
i, offset));
}
i += 1u;
}
}
// Ensure we're not passing a root by mutable alias.
for (tup(uint, def_num) root in mut_roots) {
auto mut_alias_to_root = vec::count(root._1, roots) > 1u;
for (restrict r in sc) {
@ -217,38 +213,37 @@ fn check_call(&ctx cx, &@ast::expr f, &vec[@ast::expr] args, &scope sc)
}
}
if (mut_alias_to_root) {
cx.tcx.sess.span_err
(args.(root._0).span, "passing a mutable alias to a \
cx.tcx.sess.span_err(args.(root._0).span,
"passing a mutable alias to a \
variable that roots another alias");
}
}
ret rec(root_vars = roots, unsafe_ts = unsafe_ts);
ret rec(root_vars=roots, unsafe_ts=unsafe_ts);
}
fn check_alt(&ctx cx, &@ast::expr input, &vec[ast::arm] arms,
&scope sc, &vt[scope] v) {
fn check_alt(&ctx cx, &@ast::expr input, &vec[ast::arm] arms, &scope sc,
&vt[scope] v) {
visit::visit_expr(input, sc, v);
auto root = expr_root(cx, input, true);
auto roots = alt (path_def_id(cx, root.ex)) {
case (some(?did)) { [did._1] }
case (_) { [] }
};
let vec[ty::t] forbidden_tp = alt (inner_mut(root.ds)) {
case (some(?t)) { [t] }
case (_) { [] }
};
auto roots =
alt (path_def_id(cx, root.ex)) {
case (some(?did)) { [did._1] }
case (_) { [] }
};
let vec[ty::t] forbidden_tp =
alt (inner_mut(root.ds)) { case (some(?t)) { [t] } case (_) { [] } };
for (ast::arm a in arms) {
auto dnums = arm_defnums(a);
auto new_sc = sc;
if (vec::len(dnums) > 0u) {
new_sc = sc + [@rec(root_vars=roots,
block_defnum=dnums.(0),
bindings=dnums,
tys=forbidden_tp,
depends_on=deps(sc, roots),
mutable ok=valid)];
new_sc =
sc +
[@rec(root_vars=roots,
block_defnum=dnums.(0),
bindings=dnums,
tys=forbidden_tp,
depends_on=deps(sc, roots),
mutable ok=valid)];
}
visit::visit_arm(a, new_sc, v);
}
@ -258,15 +253,11 @@ fn arm_defnums(&ast::arm arm) -> vec[def_num] {
auto dnums = [];
fn walk_pat(&mutable vec[def_num] found, &@ast::pat p) {
alt (p.node) {
case (ast::pat_bind(_, ?did, _)) {
vec::push(found, did._1);
}
case (ast::pat_bind(_, ?did, _)) { vec::push(found, did._1); }
case (ast::pat_tag(_, ?children, _)) {
for (@ast::pat child in children) {
walk_pat(found, child);
}
for (@ast::pat child in children) { walk_pat(found, child); }
}
case (_) {}
case (_) { }
}
}
walk_pat(dnums, arm.pat);
@ -280,47 +271,46 @@ fn check_for_each(&ctx cx, &@ast::local local, &@ast::expr call,
case (ast::expr_call(?f, ?args, _)) {
auto data = check_call(cx, f, args, sc);
auto defnum = local.node.id._1;
auto new_sc = @rec(root_vars=data.root_vars,
block_defnum=defnum,
bindings=[defnum],
tys=data.unsafe_ts,
depends_on=deps(sc, data.root_vars),
mutable ok=valid);
auto new_sc =
@rec(root_vars=data.root_vars,
block_defnum=defnum,
bindings=[defnum],
tys=data.unsafe_ts,
depends_on=deps(sc, data.root_vars),
mutable ok=valid);
visit::visit_block(block, sc + [new_sc], v);
}
}
}
fn check_for(&ctx cx, &@ast::local local, &@ast::expr seq,
&ast::block block, &scope sc, &vt[scope] v) {
fn check_for(&ctx cx, &@ast::local local, &@ast::expr seq, &ast::block block,
&scope sc, &vt[scope] v) {
visit::visit_expr(seq, sc, v);
auto defnum = local.node.id._1;
auto root = expr_root(cx, seq, false);
auto root_def = alt (path_def_id(cx, root.ex)) {
case (some(?did)) { [did._1] }
case (_) { [] }
};
auto unsafe = alt (inner_mut(root.ds)) {
case (some(?t)) { [t] }
case (_) { [] }
};
auto root_def =
alt (path_def_id(cx, root.ex)) {
case (some(?did)) { [did._1] }
case (_) { [] }
};
auto unsafe =
alt (inner_mut(root.ds)) { case (some(?t)) { [t] } case (_) { [] } };
// If this is a mutable vector, don't allow it to be touched.
auto seq_t = ty::expr_ty(*cx.tcx, seq);
alt (ty::struct(*cx.tcx, seq_t)) {
case (ty::ty_vec(?mt)) {
if (mt.mut != ast::imm) { unsafe = [seq_t]; }
}
case (ty::ty_str) {}
case (ty::ty_str) { }
}
auto new_sc = @rec(root_vars=root_def,
block_defnum=defnum,
bindings=[defnum],
tys=unsafe,
depends_on=deps(sc, root_def),
mutable ok=valid);
auto new_sc =
@rec(root_vars=root_def,
block_defnum=defnum,
bindings=[defnum],
tys=unsafe,
depends_on=deps(sc, root_def),
mutable ok=valid);
visit::visit_block(block, sc + [new_sc], v);
}
@ -331,6 +321,7 @@ fn check_var(&ctx cx, &@ast::expr ex, &ast::path p, ast::ann ann, bool assign,
auto my_defnum = ast::def_id_of_def(def)._1;
auto var_t = ty::expr_ty(*cx.tcx, ex);
for (restrict r in sc) {
// excludes variables introduced since the alias was made
if (my_defnum < r.block_defnum) {
for (ty::t t in r.tys) {
@ -344,22 +335,21 @@ fn check_var(&ctx cx, &@ast::expr ex, &ast::path p, ast::ann ann, bool assign,
}
}
// FIXME does not catch assigning to immutable object fields yet
fn check_assign(&@ctx cx, &@ast::expr dest, &@ast::expr src,
&scope sc, &vt[scope] v) {
fn check_assign(&@ctx cx, &@ast::expr dest, &@ast::expr src, &scope sc,
&vt[scope] v) {
visit_expr(cx, src, sc, v);
alt (dest.node) {
case (ast::expr_path(?p, ?ann)) {
auto dnum = ast::def_id_of_def(cx.dm.get(ann.id))._1;
if (is_immutable_alias(cx, sc, dnum)) {
cx.tcx.sess.span_err
(dest.span, "assigning to immutable alias");
cx.tcx.sess.span_err(dest.span,
"assigning to immutable alias");
} else if (is_immutable_objfield(cx, dnum)) {
cx.tcx.sess.span_err
(dest.span, "assigning to immutable obj field");
cx.tcx.sess.span_err(dest.span,
"assigning to immutable obj field");
}
auto var_t = ty::expr_ty(*cx.tcx, dest);
for (restrict r in sc) {
if (vec::member(dnum, r.root_vars)) {
@ -373,13 +363,14 @@ fn check_assign(&@ctx cx, &@ast::expr dest, &@ast::expr src,
if (vec::len(root.ds) == 0u) {
cx.tcx.sess.span_err(dest.span, "assignment to non-lvalue");
} else if (!root.ds.(0).mut) {
auto name = alt (root.ds.(0).kind) {
case (unbox) { "box" }
case (field) { "field" }
case (index) { "vec content" }
};
cx.tcx.sess.span_err
(dest.span, "assignment to immutable " + name);
auto name =
alt (root.ds.(0).kind) {
case (unbox) { "box" }
case (field) { "field" }
case (index) { "vec content" }
};
cx.tcx.sess.span_err(dest.span,
"assignment to immutable " + name);
}
visit_expr(cx, dest, sc, v);
}
@ -389,13 +380,14 @@ fn check_assign(&@ctx cx, &@ast::expr dest, &@ast::expr src,
fn is_immutable_alias(&@ctx cx, &scope sc, def_num dnum) -> bool {
alt (cx.local_map.find(dnum)) {
case (some(arg(ast::alias(false)))) { ret true; }
case (_) {}
case (_) { }
}
for (restrict r in sc) {
if (vec::member(dnum, r.bindings)) { ret true; }
}
ret false;
}
fn is_immutable_objfield(&@ctx cx, def_num dnum) -> bool {
ret cx.local_map.find(dnum) == some(objfield(ast::imm));
}
@ -407,17 +399,18 @@ fn test_scope(&ctx cx, &scope sc, &restrict r, &ast::path p) {
prob = sc.(dep).ok;
}
if (prob != valid) {
auto msg = alt (prob) {
case (overwritten(?sp, ?wpt)) {
tup(sp, "overwriting " + ast::path_name(wpt))
}
case (val_taken(?sp, ?vpt)) {
tup(sp, "taking the value of " + ast::path_name(vpt))
}
};
cx.tcx.sess.span_err
(msg._0, msg._1 + " will invalidate alias " +
ast::path_name(p) + ", which is still used");
auto msg =
alt (prob) {
case (overwritten(?sp, ?wpt)) {
tup(sp, "overwriting " + ast::path_name(wpt))
}
case (val_taken(?sp, ?vpt)) {
tup(sp, "taking the value of " + ast::path_name(vpt))
}
};
cx.tcx.sess.span_err(msg._0,
msg._1 + " will invalidate alias " +
ast::path_name(p) + ", which is still used");
}
}
@ -426,55 +419,45 @@ fn deps(&scope sc, vec[def_num] roots) -> vec[uint] {
auto result = [];
for (restrict r in sc) {
for (def_num dn in roots) {
if (vec::member(dn, r.bindings)) {
vec::push(result, i);
}
if (vec::member(dn, r.bindings)) { vec::push(result, i); }
}
i += 1u;
}
ret result;
}
tag deref_t {
unbox;
field;
index;
}
tag deref_t { unbox; field; index; }
type deref = rec(bool mut, deref_t kind, ty::t outer_t);
// Finds the root (the thing that is dereferenced) for the given expr, and a
// vec of dereferences that were used on this root. Note that, in this vec,
// the inner derefs come in front, so foo.bar.baz becomes rec(ex=foo,
// ds=[field(baz),field(bar)])
fn expr_root(&ctx cx, @ast::expr ex, bool autoderef)
-> rec(@ast::expr ex, vec[deref] ds) {
fn maybe_auto_unbox(&ctx cx, &ty::t t)
-> rec(ty::t t, option::t[deref] d) {
fn expr_root(&ctx cx, @ast::expr ex, bool autoderef) ->
rec(@ast::expr ex, vec[deref] ds) {
fn maybe_auto_unbox(&ctx cx, &ty::t t) ->
rec(ty::t t, option::t[deref] d) {
alt (ty::struct(*cx.tcx, t)) {
case (ty::ty_box(?mt)) {
ret rec(t=mt.ty, d=some(rec(mut=mt.mut != ast::imm,
kind=unbox,
outer_t=t)));
}
case (_) {
ret rec(t=t, d=none);
ret rec(t=mt.ty,
d=some(rec(mut=mt.mut != ast::imm,
kind=unbox,
outer_t=t)));
}
case (_) { ret rec(t=t, d=none); }
}
}
fn maybe_push_auto_unbox(&option::t[deref] d, &mutable vec[deref] ds) {
alt (d) {
case (some(?d)) { vec::push(ds, d); }
case (none) {}
}
alt (d) { case (some(?d)) { vec::push(ds, d); } case (none) { } }
}
let vec[deref] ds = [];
while (true) {
alt ({ex.node}) {
alt ({ ex.node }) {
case (ast::expr_field(?base, ?ident, _)) {
auto auto_unbox = maybe_auto_unbox
(cx, ty::expr_ty(*cx.tcx, base));
auto auto_unbox =
maybe_auto_unbox(cx, ty::expr_ty(*cx.tcx, base));
auto mut = false;
alt (ty::struct(*cx.tcx, auto_unbox.t)) {
case (ty::ty_tup(?fields)) {
@ -489,22 +472,21 @@ fn expr_root(&ctx cx, @ast::expr ex, bool autoderef)
}
}
}
case (ty::ty_obj(_)) {}
case (ty::ty_obj(_)) { }
}
vec::push(ds, rec(mut=mut,
kind=field,
outer_t=auto_unbox.t));
vec::push(ds, rec(mut=mut, kind=field, outer_t=auto_unbox.t));
maybe_push_auto_unbox(auto_unbox.d, ds);
ex = base;
}
case (ast::expr_index(?base, _, _)) {
auto auto_unbox = maybe_auto_unbox
(cx, ty::expr_ty(*cx.tcx, base));
auto auto_unbox =
maybe_auto_unbox(cx, ty::expr_ty(*cx.tcx, base));
alt (ty::struct(*cx.tcx, auto_unbox.t)) {
case (ty::ty_vec(?mt)) {
vec::push(ds, rec(mut=mt.mut != ast::imm,
kind=index,
outer_t=auto_unbox.t));
vec::push(ds,
rec(mut=mt.mut != ast::imm,
kind=index,
outer_t=auto_unbox.t));
}
}
maybe_push_auto_unbox(auto_unbox.d, ds);
@ -515,15 +497,14 @@ fn expr_root(&ctx cx, @ast::expr ex, bool autoderef)
auto base_t = ty::expr_ty(*cx.tcx, base);
alt (ty::struct(*cx.tcx, base_t)) {
case (ty::ty_box(?mt)) {
vec::push(ds, rec(mut=mt.mut != ast::imm,
kind=unbox,
outer_t=base_t));
vec::push(ds,
rec(mut=mt.mut != ast::imm,
kind=unbox,
outer_t=base_t));
}
}
ex = base;
} else {
break;
}
} else { break; }
}
case (_) { break; }
}
@ -536,16 +517,12 @@ fn expr_root(&ctx cx, @ast::expr ex, bool autoderef)
}
fn mut_field(&vec[deref] ds) -> bool {
for (deref d in ds) {
if (d.mut) { ret true; }
}
for (deref d in ds) { if (d.mut) { ret true; } }
ret false;
}
fn inner_mut(&vec[deref] ds) -> option::t[ty::t] {
for (deref d in ds) {
if (d.mut) { ret some(d.outer_t); }
}
for (deref d in ds) { if (d.mut) { ret some(d.outer_t); } }
ret none;
}
@ -554,14 +531,12 @@ fn path_def_id(&ctx cx, &@ast::expr ex) -> option::t[ast::def_id] {
case (ast::expr_path(_, ?ann)) {
ret some(ast::def_id_of_def(cx.dm.get(ann.id)));
}
case (_) {
ret none;
}
case (_) { ret none; }
}
}
fn ty_can_unsafely_include(&ctx cx, ty::t needle, ty::t haystack, bool mut)
-> bool {
fn ty_can_unsafely_include(&ctx cx, ty::t needle, ty::t haystack, bool mut) ->
bool {
fn get_mut(bool cur, &ty::mt mt) -> bool {
ret cur || mt.mut != ast::imm;
}
@ -599,13 +574,20 @@ fn ty_can_unsafely_include(&ctx cx, ty::t needle, ty::t haystack, bool mut)
}
ret false;
}
// These may contain anything.
case (ty::ty_fn(_, _, _, _, _)) { ret true; }
case (
// These may contain anything.
ty::ty_fn(_, _, _, _, _)) {
ret true;
}
case (ty::ty_obj(_)) { ret true; }
// A type param may include everything, but can only be treated as
// opaque downstream, and is thus safe unless we saw mutable
// fields, in which case the whole thing can be overwritten.
case (ty::ty_param(_)) { ret mut; }
case (
// A type param may include everything, but can only be
// treated as opaque downstream, and is thus safe unless we
// saw mutable fields, in which case the whole thing can be
// overwritten.
ty::ty_param(_)) {
ret mut;
}
case (_) { ret false; }
}
}
@ -614,14 +596,13 @@ fn ty_can_unsafely_include(&ctx cx, ty::t needle, ty::t haystack, bool mut)
fn def_is_local(&ast::def d) -> bool {
ret alt (d) {
case (ast::def_local(_)) { true }
case (ast::def_arg(_)) { true }
case (ast::def_obj_field(_)) { true }
case (ast::def_binding(_)) { true }
case (_) { false }
};
case (ast::def_local(_)) { true }
case (ast::def_arg(_)) { true }
case (ast::def_obj_field(_)) { true }
case (ast::def_binding(_)) { true }
case (_) { false }
};
}
// Local Variables:
// mode: rust
// fill-column: 78;

View File

@ -1,3 +1,4 @@
import std::str;
import std::uint;
import std::vec;
@ -7,7 +8,6 @@ import std::io;
import std::option;
import std::option::some;
import std::option::none;
import front::ast;
import front::ast::*;
import middle::trans;
@ -17,77 +17,90 @@ import back::x86;
import back::link;
import util::common;
import pretty::ppaux::lit_to_str;
import lib::llvm::llvm;
import lib::llvm::llvm::ValueRef;
import lib::llvm::False;
const uint tag_paths = 0x01u;
const uint tag_items = 0x02u;
const uint tag_paths_data = 0x03u;
const uint tag_paths_data_name = 0x04u;
const uint tag_paths_data_item = 0x05u;
const uint tag_paths_data_mod = 0x06u;
const uint tag_def_id = 0x07u;
const uint tag_items_data = 0x08u;
const uint tag_items_data_item = 0x09u;
const uint tag_items_data_item_kind = 0x0au;
const uint tag_items_data_item_ty_param_count = 0x0bu;
const uint tag_items_data_item_type = 0x0cu;
const uint tag_items_data_item_symbol = 0x0du;
const uint tag_items_data_item_variant = 0x0eu;
const uint tag_items_data_item_tag_id = 0x0fu;
const uint tag_index = 0x11u;
const uint tag_index_buckets = 0x12u;
const uint tag_index_buckets_bucket = 0x13u;
const uint tag_index_buckets_bucket_elt = 0x14u;
const uint tag_index_table = 0x15u;
const uint tag_meta_export = 0x16u;
const uint tag_meta_local = 0x17u;
const uint tag_meta_item = 0x18u;
const uint tag_meta_item_key = 0x19u;
const uint tag_meta_item_value = 0x20u;
// Type encoding
// Compact string representation for ty.t values. API ty_str & parse_from_str.
// Extra parameters are for converting to/from def_ids in the string rep.
// Whatever format you choose should not contain pipe characters.
type ty_abbrev = rec(uint pos, uint len, str s);
tag abbrev_ctxt {
ac_no_abbrevs;
ac_use_abbrevs(hashmap[ty::t, ty_abbrev]);
}
tag abbrev_ctxt { ac_no_abbrevs; ac_use_abbrevs(hashmap[ty::t, ty_abbrev]); }
mod Encode {
type ctxt =
rec(fn(&ast::def_id) -> str ds, // Def -> str Callback:
type ctxt = rec(
fn(&ast::def_id) -> str ds, // Def -> str Callback:
ty::ctxt tcx, // The type context.
abbrev_ctxt abbrevs
);
ty::ctxt tcx, // The type context.
abbrev_ctxt abbrevs);
fn cx_uses_abbrevs(&@ctxt cx) -> bool {
alt (cx.abbrevs) {
case (ac_no_abbrevs) { ret false; }
case (ac_no_abbrevs) { ret false; }
case (ac_use_abbrevs(_)) { ret true; }
}
}
fn ty_str(&@ctxt cx, &ty::t t) -> str {
assert (!cx_uses_abbrevs(cx));
auto sw = io::string_writer();
enc_ty(sw.get_writer(), cx, t);
ret sw.get_str();
}
fn enc_ty(&io::writer w, &@ctxt cx, &ty::t t) {
alt (cx.abbrevs) {
case (ac_no_abbrevs) {
@ -105,32 +118,26 @@ mod Encode {
}
case (ac_use_abbrevs(?abbrevs)) {
alt (abbrevs.find(t)) {
case (some(?a)) {
w.write_str(a.s);
ret;
}
case (some(?a)) { w.write_str(a.s); ret; }
case (none) {
auto pos = w.get_buf_writer().tell();
auto ss = enc_sty(w, cx, ty::struct(cx.tcx, t));
auto end = w.get_buf_writer().tell();
auto len = end-pos;
auto len = end - pos;
fn estimate_sz(uint u) -> uint {
auto n = u;
auto len = 0u;
while (n != 0u) {
len += 1u;
n = n >> 4u;
}
while (n != 0u) { len += 1u; n = n >> 4u; }
ret len;
}
auto abbrev_len =
3u + estimate_sz(pos) + estimate_sz(len);
if (abbrev_len < len) {
// I.e. it's actually an abbreviation.
auto s = ("#"
+ uint::to_str(pos, 16u) + ":"
+ uint::to_str(len, 16u) + "#");
auto s =
"#" + uint::to_str(pos, 16u) + ":" +
uint::to_str(len, 16u) + "#";
auto a = rec(pos=pos, len=len, s=s);
abbrevs.insert(t, a);
}
@ -140,16 +147,14 @@ mod Encode {
}
}
}
fn enc_mt(&io::writer w, &@ctxt cx, &ty::mt mt) {
alt (mt.mut) {
case (ast::imm) { }
case (ast::mut) { w.write_char('m'); }
case (ast::imm) { }
case (ast::mut) { w.write_char('m'); }
case (ast::maybe_mut) { w.write_char('?'); }
}
enc_ty(w, cx, mt.ty);
}
fn enc_sty(&io::writer w, &@ctxt cx, &ty::sty st) {
alt (st) {
case (ty::ty_nil) { w.write_char('n'); }
@ -172,29 +177,25 @@ mod Encode {
case (common::ty_f64) { w.write_str("MF"); }
}
}
case (ty::ty_char) {w.write_char('c');}
case (ty::ty_str) {w.write_char('s');}
case (ty::ty_istr) {w.write_char('S');}
case (ty::ty_tag(?def,?tys)) {
case (ty::ty_char) { w.write_char('c'); }
case (ty::ty_str) { w.write_char('s'); }
case (ty::ty_istr) { w.write_char('S'); }
case (ty::ty_tag(?def, ?tys)) {
w.write_str("t[");
w.write_str(cx.ds(def));
w.write_char('|');
for (ty::t t in tys) {
enc_ty(w, cx, t);
}
for (ty::t t in tys) { enc_ty(w, cx, t); }
w.write_char(']');
}
case (ty::ty_box(?mt)) {w.write_char('@'); enc_mt(w, cx, mt); }
case (ty::ty_ptr(?mt)) {w.write_char('*'); enc_mt(w, cx, mt); }
case (ty::ty_vec(?mt)) {w.write_char('V'); enc_mt(w, cx, mt); }
case (ty::ty_ivec(?mt)) {w.write_char('I'); enc_mt(w, cx, mt); }
case (ty::ty_port(?t)) {w.write_char('P'); enc_ty(w, cx, t); }
case (ty::ty_chan(?t)) {w.write_char('C'); enc_ty(w, cx, t); }
case (ty::ty_box(?mt)) { w.write_char('@'); enc_mt(w, cx, mt); }
case (ty::ty_ptr(?mt)) { w.write_char('*'); enc_mt(w, cx, mt); }
case (ty::ty_vec(?mt)) { w.write_char('V'); enc_mt(w, cx, mt); }
case (ty::ty_ivec(?mt)) { w.write_char('I'); enc_mt(w, cx, mt); }
case (ty::ty_port(?t)) { w.write_char('P'); enc_ty(w, cx, t); }
case (ty::ty_chan(?t)) { w.write_char('C'); enc_ty(w, cx, t); }
case (ty::ty_tup(?mts)) {
w.write_str("T[");
for (ty::mt mt in mts) {
enc_mt(w, cx, mt);
}
for (ty::mt mt in mts) { enc_mt(w, cx, mt); }
w.write_char(']');
}
case (ty::ty_rec(?fields)) {
@ -206,11 +207,11 @@ mod Encode {
}
w.write_char(']');
}
case (ty::ty_fn(?proto,?args,?out,?cf,?constrs)) {
case (ty::ty_fn(?proto, ?args, ?out, ?cf, ?constrs)) {
enc_proto(w, proto);
enc_ty_fn(w, cx, args, out, cf, constrs);
}
case (ty::ty_native_fn(?abi,?args,?out)) {
case (ty::ty_native_fn(?abi, ?args, ?out)) {
w.write_char('N');
alt (abi) {
case (ast::native_abi_rust) { w.write_char('r'); }
@ -236,23 +237,21 @@ mod Encode {
w.write_char('X');
w.write_str(common::istr(id));
}
case (ty::ty_native) {w.write_char('E');}
case (ty::ty_native) { w.write_char('E'); }
case (ty::ty_param(?id)) {
w.write_char('p');
w.write_str(common::uistr(id));
}
case (ty::ty_type) {w.write_char('Y');}
case (ty::ty_task) {w.write_char('a');}
case (ty::ty_type) { w.write_char('Y'); }
case (ty::ty_task) { w.write_char('a'); }
}
}
fn enc_proto(&io::writer w, ast::proto proto) {
alt (proto) {
case (ast::proto_iter) { w.write_char('W'); }
case (ast::proto_fn) { w.write_char('F'); }
}
}
fn enc_ty_fn(&io::writer w, &@ctxt cx, &vec[ty::arg] args, &ty::t out,
&ast::controlflow cf, &vec[@ast::constr] constrs) {
w.write_char('[');
@ -262,54 +261,40 @@ mod Encode {
w.write_char('&');
if (mut) { w.write_char('m'); }
}
case (ty::mo_val) {}
case (ty::mo_val) { }
}
enc_ty(w, cx, arg.ty);
}
w.write_char(']');
alt (cf) {
case (ast::noreturn) {
w.write_char('!');
}
case (_) {
enc_ty(w, cx, out);
}
case (ast::noreturn) { w.write_char('!'); }
case (_) { enc_ty(w, cx, out); }
}
auto colon = true;
for (@ast::constr c in constrs) {
if (colon) { w.write_char(':'); colon = false; }
else { w.write_char(','); }
if (colon) {
w.write_char(':');
colon = false;
} else { w.write_char(','); }
enc_constr(w, cx, c);
}
}
fn enc_constr(&io::writer w, &@ctxt cx, &@ast::constr c) {
w.write_str(path_to_str(c.node.path));
w.write_char('(');
// FIXME
// w.write_str(cx.ds(c.node.id));
auto comma = false;
for (@constr_arg a in c.node.args) {
if (comma) {
w.write_char(',');
}
else {
comma = true;
}
if (comma) { w.write_char(','); } else { comma = true; }
alt (a.node) {
case (carg_base) {
w.write_char('*');
}
case (carg_ident(?i)) {
w.write_uint(i);
}
case (carg_lit(?l)) {
w.write_str(lit_to_str(l));
}
case (carg_base) { w.write_char('*'); }
case (carg_ident(?i)) { w.write_uint(i); }
case (carg_lit(?l)) { w.write_str(lit_to_str(l)); }
}
}
}
}
@ -320,7 +305,6 @@ fn C_postr(&str s) -> ValueRef {
// Path table encoding
fn encode_name(&ebml::writer ebml_w, &str name) {
ebml::start_tag(ebml_w, tag_paths_data_name);
ebml_w.writer.write(str::bytes(name));
@ -333,8 +317,7 @@ fn encode_def_id(&ebml::writer ebml_w, &ast::def_id id) {
ebml::end_tag(ebml_w);
}
fn encode_tag_variant_paths(&ebml::writer ebml_w,
&vec[ast::variant] variants,
fn encode_tag_variant_paths(&ebml::writer ebml_w, &vec[ast::variant] variants,
&vec[str] path,
&mutable vec[tup(str, uint)] index) {
for (ast::variant variant in variants) {
@ -346,17 +329,14 @@ fn encode_tag_variant_paths(&ebml::writer ebml_w,
}
}
fn add_to_index(&ebml::writer ebml_w,
&vec[str] path,
&mutable vec[tup(str, uint)] index,
&str name) {
fn add_to_index(&ebml::writer ebml_w, &vec[str] path,
&mutable vec[tup(str, uint)] index, &str name) {
auto full_path = path + [name];
index += [tup(str::connect(full_path, "::"), ebml_w.writer.tell())];
}
fn encode_native_module_item_paths(&ebml::writer ebml_w,
&ast::native_mod nmod,
&vec[str] path,
&ast::native_mod nmod, &vec[str] path,
&mutable vec[tup(str, uint)] index) {
for (@ast::native_item nitem in nmod.items) {
alt (nitem.node) {
@ -378,15 +358,11 @@ fn encode_native_module_item_paths(&ebml::writer ebml_w,
}
}
fn encode_module_item_paths(&ebml::writer ebml_w,
&ast::_mod module,
fn encode_module_item_paths(&ebml::writer ebml_w, &ast::_mod module,
&vec[str] path,
&mutable vec[tup(str, uint)] index) {
for (@ast::item it in module.items) {
if (!ast::is_exported(ast::item_ident(it), module)) {
cont;
}
if (!ast::is_exported(ast::item_ident(it), module)) { cont; }
alt (it.node) {
case (ast::item_const(?id, _, ?tps, _, ?did, ?ann)) {
add_to_index(ebml_w, path, index, id);
@ -432,7 +408,6 @@ fn encode_module_item_paths(&ebml::writer ebml_w,
encode_name(ebml_w, id);
encode_def_id(ebml_w, did);
ebml::end_tag(ebml_w);
encode_tag_variant_paths(ebml_w, variants, path, index);
}
case (ast::item_obj(?id, _, ?tps, _, ?odid, ?ann)) {
@ -441,7 +416,6 @@ fn encode_module_item_paths(&ebml::writer ebml_w,
encode_name(ebml_w, id);
encode_def_id(ebml_w, odid.ctor);
ebml::end_tag(ebml_w);
add_to_index(ebml_w, path, index, id);
ebml::start_tag(ebml_w, tag_paths_data_item);
encode_name(ebml_w, id);
@ -452,8 +426,8 @@ fn encode_module_item_paths(&ebml::writer ebml_w,
}
}
fn encode_item_paths(&ebml::writer ebml_w, &@ast::crate crate)
-> vec[tup(str, uint)] {
fn encode_item_paths(&ebml::writer ebml_w, &@ast::crate crate) ->
vec[tup(str, uint)] {
let vec[tup(str, uint)] index = [];
let vec[str] path = [];
ebml::start_tag(ebml_w, tag_paths);
@ -464,16 +438,13 @@ fn encode_item_paths(&ebml::writer ebml_w, &@ast::crate crate)
// Item info table encoding
fn encode_kind(&ebml::writer ebml_w, u8 c) {
ebml::start_tag(ebml_w, tag_items_data_item_kind);
ebml_w.writer.write([c]);
ebml::end_tag(ebml_w);
}
fn def_to_str(&ast::def_id did) -> str {
ret #fmt("%d:%d", did._0, did._1);
}
fn def_to_str(&ast::def_id did) -> str { ret #fmt("%d:%d", did._0, did._1); }
fn encode_type_param_count(&ebml::writer ebml_w, &vec[ast::ty_param] tps) {
ebml::start_tag(ebml_w, tag_items_data_item_ty_param_count);
@ -489,10 +460,9 @@ fn encode_variant_id(&ebml::writer ebml_w, &ast::def_id vid) {
fn encode_type(&@trans::crate_ctxt cx, &ebml::writer ebml_w, &ty::t typ) {
ebml::start_tag(ebml_w, tag_items_data_item_type);
auto f = def_to_str;
auto ty_str_ctxt = @rec(ds=f, tcx=cx.tcx,
abbrevs=ac_use_abbrevs(cx.type_abbrevs));
auto ty_str_ctxt =
@rec(ds=f, tcx=cx.tcx, abbrevs=ac_use_abbrevs(cx.type_abbrevs));
Encode::enc_ty(io::new_writer_(ebml_w.writer), ty_str_ctxt, typ);
ebml::end_tag(ebml_w);
}
@ -517,15 +487,12 @@ fn encode_tag_id(&ebml::writer ebml_w, &ast::def_id id) {
ebml::end_tag(ebml_w);
}
fn encode_tag_variant_info(&@trans::crate_ctxt cx, &ebml::writer ebml_w,
&ast::def_id did, &vec[ast::variant] variants,
&mutable vec[tup(int, uint)] index,
&vec[ast::ty_param] ty_params) {
for (ast::variant variant in variants) {
index += [tup(variant.node.id._1, ebml_w.writer.tell())];
ebml::start_tag(ebml_w, tag_items_data_item);
encode_def_id(ebml_w, variant.node.id);
encode_kind(ebml_w, 'v' as u8);
@ -590,7 +557,6 @@ fn encode_info_for_item(@trans::crate_ctxt cx, &ebml::writer ebml_w,
encode_variant_id(ebml_w, v.node.id);
}
ebml::end_tag(ebml_w);
encode_tag_variant_info(cx, ebml_w, did, variants, index, tps);
}
case (ast::item_obj(?id, _, ?tps, _, ?odid, ?ann)) {
@ -602,7 +568,6 @@ fn encode_info_for_item(@trans::crate_ctxt cx, &ebml::writer ebml_w,
encode_type(cx, ebml_w, fn_ty);
encode_symbol(cx, ebml_w, odid.ctor);
ebml::end_tag(ebml_w);
index += [tup(odid.ty._1, ebml_w.writer.tell())];
ebml::start_tag(ebml_w, tag_items_data_item);
encode_def_id(ebml_w, odid.ty);
@ -634,22 +599,20 @@ fn encode_info_for_native_item(&@trans::crate_ctxt cx, &ebml::writer ebml_w,
ebml::end_tag(ebml_w);
}
fn encode_info_for_items(&@trans::crate_ctxt cx, &ebml::writer ebml_w)
-> vec[tup(int, uint)] {
fn encode_info_for_items(&@trans::crate_ctxt cx, &ebml::writer ebml_w) ->
vec[tup(int, uint)] {
let vec[tup(int, uint)] index = [];
ebml::start_tag(ebml_w, tag_items_data);
for each (@tup(ast::def_id, @ast::item) kvp in cx.items.items()) {
index += [tup(kvp._0._1, ebml_w.writer.tell())];
encode_info_for_item(cx, ebml_w, kvp._1, index);
}
for each (@tup(ast::def_id, @ast::native_item) kvp in
cx.native_items.items()) {
cx.native_items.items()) {
index += [tup(kvp._0._1, ebml_w.writer.tell())];
encode_info_for_native_item(cx, ebml_w, kvp._1);
}
ebml::end_tag(ebml_w);
ret index;
}
@ -657,46 +620,33 @@ fn encode_info_for_items(&@trans::crate_ctxt cx, &ebml::writer ebml_w)
// Path and definition ID indexing
// djb's cdb hashes.
fn hash_def_num(&int def_num) -> uint {
ret 177573u ^ (def_num as uint);
}
fn hash_def_num(&int def_num) -> uint { ret 177573u ^ (def_num as uint); }
fn hash_path(&str s) -> uint {
auto h = 5381u;
for (u8 ch in str::bytes(s)) {
h = ((h << 5u) + h) ^ (ch as uint);
}
for (u8 ch in str::bytes(s)) { h = (h << 5u) + h ^ (ch as uint); }
ret h;
}
fn create_index[T](&vec[tup(T, uint)] index, fn(&T) -> uint hash_fn)
-> vec[vec[tup(T, uint)]] {
fn create_index[T](&vec[tup(T, uint)] index, fn(&T) -> uint hash_fn) ->
vec[vec[tup(T, uint)]] {
let vec[mutable vec[tup(T, uint)]] buckets = vec::empty_mut();
for each (uint i in uint::range(0u, 256u)) {
buckets += [mutable []];
}
for each (uint i in uint::range(0u, 256u)) { buckets += [mutable []]; }
for (tup(T, uint) elt in index) {
auto h = hash_fn(elt._0);
buckets.(h % 256u) += [elt];
}
ret vec::freeze(buckets);
}
fn encode_index[T](&ebml::writer ebml_w,
&vec[vec[tup(T, uint)]] buckets,
fn(&io::writer, &T) write_fn) {
fn encode_index[T](&ebml::writer ebml_w, &vec[vec[tup(T, uint)]] buckets,
fn(&io::writer, &T) write_fn) {
auto writer = io::new_writer_(ebml_w.writer);
ebml::start_tag(ebml_w, tag_index);
let vec[uint] bucket_locs = [];
ebml::start_tag(ebml_w, tag_index_buckets);
for (vec[tup(T, uint)] bucket in buckets) {
bucket_locs += [ebml_w.writer.tell()];
ebml::start_tag(ebml_w, tag_index_buckets_bucket);
for (tup(T, uint) elt in bucket) {
ebml::start_tag(ebml_w, tag_index_buckets_bucket_elt);
@ -707,27 +657,19 @@ fn encode_index[T](&ebml::writer ebml_w,
ebml::end_tag(ebml_w);
}
ebml::end_tag(ebml_w);
ebml::start_tag(ebml_w, tag_index_table);
for (uint pos in bucket_locs) {
writer.write_be_uint(pos, 4u);
}
for (uint pos in bucket_locs) { writer.write_be_uint(pos, 4u); }
ebml::end_tag(ebml_w);
ebml::end_tag(ebml_w);
}
fn write_str(&io::writer writer, &str s) {
writer.write_str(s);
}
fn write_str(&io::writer writer, &str s) { writer.write_str(s); }
fn write_int(&io::writer writer, &int n) {
writer.write_be_uint(n as uint, 4u);
}
fn encode_meta_items(&ebml::writer ebml_w, &ast::crate crate) {
fn encode_meta_item(&ebml::writer ebml_w, &ast::meta_item mi) {
ebml::start_tag(ebml_w, tag_meta_item);
ebml::start_tag(ebml_w, tag_meta_item_key);
@ -738,13 +680,11 @@ fn encode_meta_items(&ebml::writer ebml_w, &ast::crate crate) {
ebml::end_tag(ebml_w);
ebml::end_tag(ebml_w);
}
ebml::start_tag(ebml_w, tag_meta_export);
for each (@ast::meta_item mi in link::crate_export_metas(crate)) {
encode_meta_item(ebml_w, *mi);
}
ebml::end_tag(ebml_w);
ebml::start_tag(ebml_w, tag_meta_local);
for each (@ast::meta_item mi in link::crate_local_metas(crate)) {
encode_meta_item(ebml_w, *mi);
@ -752,16 +692,15 @@ fn encode_meta_items(&ebml::writer ebml_w, &ast::crate crate) {
ebml::end_tag(ebml_w);
}
fn encode_metadata(&@trans::crate_ctxt cx, &@ast::crate crate)
-> ValueRef {
fn encode_metadata(&@trans::crate_ctxt cx, &@ast::crate crate) -> ValueRef {
auto string_w = io::string_writer();
auto buf_w = string_w.get_writer().get_buf_writer();
auto ebml_w = ebml::create_writer(buf_w);
// Encode the meta items
encode_meta_items(ebml_w, *crate);
encode_meta_items(ebml_w, *crate);
// Encode and index the paths.
ebml::start_tag(ebml_w, tag_paths);
auto paths_index = encode_item_paths(ebml_w, crate);
auto str_writer = write_str;
@ -769,8 +708,8 @@ fn encode_metadata(&@trans::crate_ctxt cx, &@ast::crate crate)
auto paths_buckets = create_index[str](paths_index, path_hasher);
encode_index[str](ebml_w, paths_buckets, str_writer);
ebml::end_tag(ebml_w);
// Encode and index the items.
ebml::start_tag(ebml_w, tag_items);
auto items_index = encode_info_for_items(cx, ebml_w);
auto int_writer = write_int;
@ -778,27 +717,23 @@ fn encode_metadata(&@trans::crate_ctxt cx, &@ast::crate crate)
auto items_buckets = create_index[int](items_index, item_hasher);
encode_index[int](ebml_w, items_buckets, int_writer);
ebml::end_tag(ebml_w);
// Pad this, since something (LLVM, presumably) is cutting off the
// remaining % 4 bytes.
buf_w.write([0u8, 0u8, 0u8, 0u8]);
buf_w.write([0u8, 0u8, 0u8, 0u8]);
ret C_postr(string_w.get_str());
}
fn write_metadata(&@trans::crate_ctxt cx, &@ast::crate crate) {
if (!cx.sess.get_opts().shared) {
ret;
}
if (!cx.sess.get_opts().shared) { ret; }
auto llmeta = encode_metadata(cx, crate);
auto llconst = trans::C_struct([llmeta]);
auto llglobal = llvm::LLVMAddGlobal(cx.llmod, trans::val_ty(llconst),
str::buf("rust_metadata"));
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()));
}
//
// Local Variables:
// mode: rust

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,160 +1,169 @@
import front::ast::ident;
import std::vec;
import std::bitv;
/*
This says: this expression requires the idents in <pre> to be initialized,
and given the precondition, it guarantees that the idents in <post> are
initialized.
*/
type precond = bitv::t; /* 1 means "this variable must be initialized"
0 means "don't care about this variable" */
type postcond = bitv::t; /* 1 means "this variable is initialized"
0 means "don't know about this variable */
type precond = bitv::t;
type prestate = bitv::t; /* 1 means "this variable is definitely initialized"
0 means "don't know whether this variable is
initialized" */
type poststate = bitv::t; /* 1 means "this variable is definitely initialized"
0 means "don't know whether this variable is
initialized" */
/* 1 means "this variable must be initialized"
0 means "don't care about this variable" */
type postcond = bitv::t;
/* named thus so as not to confuse with prestate and poststate */
/* 1 means "this variable is initialized"
0 means "don't know about this variable */
type prestate = bitv::t;
/* 1 means "this variable is definitely initialized"
0 means "don't know whether this variable is
initialized" */
type poststate = bitv::t;
/* 1 means "this variable is definitely initialized"
0 means "don't know whether this variable is
initialized" */
/* named thus so as not to confuse with prestate and poststate */
type pre_and_post = @rec(precond precondition, postcond postcondition);
/* FIXME: once it's implemented: */
// : ((*.precondition).nbits == (*.postcondition).nbits);
/* FIXME: once it's implemented: */
// : ((*.precondition).nbits == (*.postcondition).nbits);
type pre_and_post_state = rec(prestate prestate, poststate poststate);
type ts_ann = @rec(pre_and_post conditions, pre_and_post_state states);
fn true_precond(uint num_vars) -> precond {
be bitv::create(num_vars, false);
be bitv::create(num_vars, false);
}
fn true_postcond(uint num_vars) -> postcond {
be true_precond(num_vars);
}
fn true_postcond(uint num_vars) -> postcond { be true_precond(num_vars); }
fn empty_prestate(uint num_vars) -> prestate {
be true_precond(num_vars);
}
fn empty_prestate(uint num_vars) -> prestate { be true_precond(num_vars); }
fn empty_poststate(uint num_vars) -> poststate {
be true_precond(num_vars);
}
fn empty_poststate(uint num_vars) -> poststate { be true_precond(num_vars); }
fn false_postcond(uint num_vars) -> postcond {
be bitv::create(num_vars, true);
}
fn empty_pre_post(uint num_vars) -> pre_and_post {
ret(@rec(precondition=empty_prestate(num_vars),
postcondition=empty_poststate(num_vars)));
ret @rec(precondition=empty_prestate(num_vars),
postcondition=empty_poststate(num_vars));
}
fn empty_states(uint num_vars) -> pre_and_post_state {
ret(rec(prestate=true_precond(num_vars),
poststate=true_postcond(num_vars)));
ret rec(prestate=true_precond(num_vars),
poststate=true_postcond(num_vars));
}
fn empty_ann(uint num_vars) -> ts_ann {
ret(@rec(conditions=empty_pre_post(num_vars),
states=empty_states(num_vars)));
ret @rec(conditions=empty_pre_post(num_vars),
states=empty_states(num_vars));
}
fn get_pre(&pre_and_post p) -> precond {
ret p.precondition;
}
fn get_pre(&pre_and_post p) -> precond { ret p.precondition; }
fn get_post(&pre_and_post p) -> postcond {
ret p.postcondition;
}
fn get_post(&pre_and_post p) -> postcond { ret p.postcondition; }
fn difference(&precond p1, &precond p2) -> bool {
be bitv::difference(p1, p2);
be bitv::difference(p1, p2);
}
fn union(&precond p1, &precond p2) -> bool {
be bitv::union(p1, p2);
}
fn union(&precond p1, &precond p2) -> bool { be bitv::union(p1, p2); }
fn intersect(&precond p1, &precond p2) -> bool {
be bitv::intersect(p1, p2);
}
fn intersect(&precond p1, &precond p2) -> bool { be bitv::intersect(p1, p2); }
fn pps_len(&pre_and_post p) -> uint {
// gratuitous check
assert (p.precondition.nbits == p.postcondition.nbits);
ret p.precondition.nbits;
// gratuitous check
assert (p.precondition.nbits == p.postcondition.nbits);
ret p.precondition.nbits;
}
fn require(uint i, &pre_and_post p) -> () {
// sets the ith bit in p's pre
bitv::set(p.precondition, i, true);
fn require(uint i, &pre_and_post p) {
// sets the ith bit in p's pre
bitv::set(p.precondition, i, true);
}
fn require_and_preserve(uint i, &pre_and_post p) -> () {
// sets the ith bit in p's pre and post
bitv::set(p.precondition, i, true);
bitv::set(p.postcondition, i, true);
fn require_and_preserve(uint i, &pre_and_post p) {
// sets the ith bit in p's pre and post
bitv::set(p.precondition, i, true);
bitv::set(p.postcondition, i, true);
}
fn set_in_postcond(uint i, &pre_and_post p) -> bool {
// sets the ith bit in p's post
auto was_set = bitv::get(p.postcondition, i);
bitv::set(p.postcondition, i, true);
ret !was_set;
// sets the ith bit in p's post
auto was_set = bitv::get(p.postcondition, i);
bitv::set(p.postcondition, i, true);
ret !was_set;
}
fn set_in_poststate(uint i, &pre_and_post_state s) -> bool {
// sets the ith bit in p's post
auto was_set = bitv::get(s.poststate, i);
bitv::set(s.poststate, i, true);
ret !was_set;
// sets the ith bit in p's post
auto was_set = bitv::get(s.poststate, i);
bitv::set(s.poststate, i, true);
ret !was_set;
}
fn clear_in_poststate(uint i, &pre_and_post_state s) -> bool {
// sets the ith bit in p's post
auto was_set = bitv::get(s.poststate, i);
bitv::set(s.poststate, i, false);
ret was_set;
// sets the ith bit in p's post
auto was_set = bitv::get(s.poststate, i);
bitv::set(s.poststate, i, false);
ret was_set;
}
// Sets all the bits in a's precondition to equal the
// corresponding bit in p's precondition.
fn set_precondition(ts_ann a, &precond p) -> () {
bitv::copy(a.conditions.precondition, p);
fn set_precondition(ts_ann a, &precond p) {
bitv::copy(a.conditions.precondition, p);
}
// Sets all the bits in a's postcondition to equal the
// corresponding bit in p's postcondition.
fn set_postcondition(ts_ann a, &postcond p) -> () {
bitv::copy(a.conditions.postcondition, p);
fn set_postcondition(ts_ann a, &postcond p) {
bitv::copy(a.conditions.postcondition, p);
}
// Sets all the bits in a's prestate to equal the
// corresponding bit in p's prestate.
fn set_prestate(ts_ann a, &prestate p) -> bool {
ret bitv::copy(a.states.prestate, p);
ret bitv::copy(a.states.prestate, p);
}
// Sets all the bits in a's postcondition to equal the
// corresponding bit in p's postcondition.
fn set_poststate(ts_ann a, &poststate p) -> bool {
ret bitv::copy(a.states.poststate, p);
ret bitv::copy(a.states.poststate, p);
}
// Set all the bits in p that are set in new
fn extend_prestate(&prestate p, &poststate new) -> bool {
ret bitv::union(p, new);
ret bitv::union(p, new);
}
// Set all the bits in p that are set in new
fn extend_poststate(&poststate p, &poststate new) -> bool {
ret bitv::union(p, new);
ret bitv::union(p, new);
}
// Clears the given bit in p
fn relax_prestate(uint i, &prestate p) -> bool {
auto was_set = bitv::get(p, i);
@ -162,46 +171,36 @@ fn relax_prestate(uint i, &prestate p) -> bool {
ret was_set;
}
// Clears all the bits in p
fn clear(&precond p) -> () {
bitv::clear(p);
}
fn clear(&precond p) { bitv::clear(p); }
// Sets all the bits in p
fn set(&precond p) -> () {
bitv::set_all(p);
}
fn set(&precond p) { bitv::set_all(p); }
fn ann_precond(&ts_ann a) -> precond {
ret a.conditions.precondition;
}
fn ann_precond(&ts_ann a) -> precond { ret a.conditions.precondition; }
fn ann_prestate(&ts_ann a) -> prestate {
ret a.states.prestate;
}
fn ann_prestate(&ts_ann a) -> prestate { ret a.states.prestate; }
fn ann_poststate(&ts_ann a) -> poststate {
ret a.states.poststate;
}
fn ann_poststate(&ts_ann a) -> poststate { ret a.states.poststate; }
fn pp_clone(&pre_and_post p) -> pre_and_post {
ret @rec(precondition=clone(p.precondition),
postcondition=clone(p.postcondition));
ret @rec(precondition=clone(p.precondition),
postcondition=clone(p.postcondition));
}
fn clone(prestate p) -> prestate {
ret bitv::clone(p);
}
fn clone(prestate p) -> prestate { ret bitv::clone(p); }
// returns true if a implies b
// that is, returns true except if for some bits c and d,
// c = 1 and d = 0
fn implies(bitv::t a, bitv::t b) -> bool {
auto tmp = bitv::clone(b);
bitv::difference(tmp, a);
ret bitv::is_false(tmp);
auto tmp = bitv::clone(b);
bitv::difference(tmp, a);
ret bitv::is_false(tmp);
}
//
// Local Variables:
// mode: rust

View File

@ -1,11 +1,10 @@
import std::vec;
import std::option;
import std::option::some;
import std::option::none;
import front::ast::*;
import middle::ty::expr_ann;
import util::common::uistr;
import util::common::span;
import util::common::new_str_hash;
@ -16,7 +15,6 @@ import util::common::log_stmt_err;
import util::common::log_expr;
import util::common::log_block;
import util::common::log_stmt;
import aux::fn_info;
import aux::fn_info_map;
import aux::num_constraints;
@ -25,75 +23,72 @@ import aux::crate_ctxt;
import aux::add_node;
import middle::tstate::ann::empty_ann;
fn collect_ids_expr(&@expr e, @mutable vec[uint] res) -> () {
vec::push(*res, (expr_ann(e)).id);
fn collect_ids_expr(&@expr e, @mutable vec[uint] res) {
vec::push(*res, expr_ann(e).id);
}
fn collect_ids_block(&block b, @mutable vec[uint] res) -> () {
fn collect_ids_block(&block b, @mutable vec[uint] res) {
vec::push(*res, b.node.a.id);
}
fn collect_ids_stmt(&@stmt s, @mutable vec[uint] res) -> () {
fn collect_ids_stmt(&@stmt s, @mutable vec[uint] res) {
alt (s.node) {
case (stmt_decl(_,?a)) {
log("node_id " + uistr(a.id));
case (stmt_decl(_, ?a)) {
log "node_id " + uistr(a.id);
log_stmt(*s);
vec::push(*res, a.id);
}
case (stmt_expr(_,?a)) {
log("node_id " + uistr(a.id));
case (stmt_expr(_, ?a)) {
log "node_id " + uistr(a.id);
log_stmt(*s);
vec::push(*res, a.id);
}
case (_) {}
case (_) { }
}
}
fn collect_ids_local(&@local l, @mutable vec[uint] res) -> () {
fn collect_ids_local(&@local l, @mutable vec[uint] res) {
vec::push(*res, l.node.ann.id);
}
fn node_ids_in_fn(&_fn f, &span sp, &ident i, &def_id d, &ann a,
@mutable vec[uint] res) -> () {
@mutable vec[uint] res) {
auto collect_ids = walk::default_visitor();
collect_ids = rec(visit_expr_pre = bind collect_ids_expr(_,res),
visit_block_pre = bind collect_ids_block(_,res),
visit_stmt_pre = bind collect_ids_stmt(_,res),
visit_local_pre = bind collect_ids_local(_,res)
with collect_ids);
collect_ids =
rec(visit_expr_pre=bind collect_ids_expr(_, res),
visit_block_pre=bind collect_ids_block(_, res),
visit_stmt_pre=bind collect_ids_stmt(_, res),
visit_local_pre=bind collect_ids_local(_, res) with collect_ids);
walk::walk_fn(collect_ids, f, sp, i, d, a);
}
fn init_vecs(&crate_ctxt ccx, &vec[uint] node_ids, uint len) -> () {
fn init_vecs(&crate_ctxt ccx, &vec[uint] node_ids, uint len) {
for (uint i in node_ids) {
log(uistr(i) + " |-> " + uistr(len));
log uistr(i) + " |-> " + uistr(len);
add_node(ccx, i, empty_ann(len));
}
}
fn visit_fn(&crate_ctxt ccx, uint num_constraints, &_fn f,
&span sp, &ident i, &def_id d, &ann a) -> () {
fn visit_fn(&crate_ctxt ccx, uint num_constraints, &_fn f, &span sp, &ident i,
&def_id d, &ann a) {
let @mutable vec[uint] node_ids = @mutable [];
node_ids_in_fn(f, sp, i, d, a, node_ids);
auto node_id_vec = *node_ids;
init_vecs(ccx, node_id_vec, num_constraints);
}
fn annotate_in_fn(&crate_ctxt ccx, &_fn f, &span sp, &ident i,
&def_id f_id, &ann a)
-> () {
fn annotate_in_fn(&crate_ctxt ccx, &_fn f, &span sp, &ident i, &def_id f_id,
&ann a) {
auto f_info = get_fn_info(ccx, f_id);
visit_fn(ccx, num_constraints(f_info), f, sp, i, f_id, a);
}
fn annotate_crate(&crate_ctxt ccx, &crate crate) -> () {
fn annotate_crate(&crate_ctxt ccx, &crate crate) {
auto do_ann = walk::default_visitor();
do_ann = rec(visit_fn_pre = bind annotate_in_fn(ccx,_,_,_,_,_)
with do_ann);
do_ann =
rec(visit_fn_pre=bind annotate_in_fn(ccx, _, _, _, _, _) with do_ann);
walk::walk_crate(do_ann, crate);
}
//
// Local Variables:
// mode: rust

View File

@ -1,3 +1,4 @@
import std::bitv;
import std::vec;
import std::vec::len;
@ -7,12 +8,9 @@ import std::option;
import std::option::none;
import std::option::some;
import std::option::maybe;
import front::ast;
import front::ast::*;
import middle::ty::expr_ann;
import util::common;
import util::common::span;
import util::common::respan;
@ -23,7 +21,6 @@ import util::common::log_expr_err;
import util::common::uistr;
import util::common::lit_eq;
import pretty::pprust::path_to_str;
import tstate::ann::pre_and_post;
import tstate::ann::pre_and_post_state;
import tstate::ann::empty_ann;
@ -40,37 +37,23 @@ import tstate::ann::extend_poststate;
import tstate::ann::set_precondition;
import tstate::ann::set_postcondition;
import tstate::ann::ts_ann;
import util::common::istr;
import pretty::ppaux::constr_args_to_str;
import pretty::ppaux::lit_to_str;
/* logging funs */
fn def_id_to_str(def_id d) -> str {
ret (istr(d._0) + "," + istr(d._1));
}
/* logging funs */
fn def_id_to_str(def_id d) -> str { ret istr(d._0) + "," + istr(d._1); }
fn comma_str(vec[@constr_arg_use] args) -> str {
auto res = "";
auto comma = false;
for (@constr_arg_use a in args) {
if (comma) {
res += ", ";
}
else {
comma = true;
}
if (comma) { res += ", "; } else { comma = true; }
alt (a.node) {
case (carg_base) {
res += "*";
}
case (carg_ident(?i)) {
res += i;
}
case (carg_lit(?l)) {
res += lit_to_str(l);
}
case (carg_base) { res += "*"; }
case (carg_ident(?i)) { res += i; }
case (carg_lit(?l)) { res += lit_to_str(l); }
}
}
ret res;
@ -82,132 +65,112 @@ fn constraint_to_str(&ty::ctxt tcx, &constr c) -> str {
ret "init(" + i + " [" + tcx.sess.span_str(c.span) + "])";
}
case (npred(?p, ?args)) {
ret path_to_str(p) + "(" + comma_str(args) + ")"
+ "[" + tcx.sess.span_str(c.span) + "]";
ret path_to_str(p) + "(" + comma_str(args) + ")" + "[" +
tcx.sess.span_str(c.span) + "]";
}
}
}
fn bitv_to_str(fn_ctxt fcx, bitv::t v) -> str {
auto s = "";
auto comma = false;
for (norm_constraint p in constraints(fcx)) {
if (bitv::get(v, p.bit_num)) {
s += (if (comma) { ", " } else { comma = true; "" })
+ aux::constraint_to_str(fcx.ccx.tcx, p.c);
}
}
ret s;
auto s = "";
auto comma = false;
for (norm_constraint p in constraints(fcx)) {
if (bitv::get(v, p.bit_num)) {
s +=
if (comma) { ", " } else { comma = true; "" } +
aux::constraint_to_str(fcx.ccx.tcx, p.c);
}
}
ret s;
}
fn log_bitv(&fn_ctxt fcx, &bitv::t v) {
log(bitv_to_str(fcx, v));
}
fn log_bitv(&fn_ctxt fcx, &bitv::t v) { log bitv_to_str(fcx, v); }
fn first_difference_string(&fn_ctxt fcx, &bitv::t expected,
&bitv::t actual) -> str {
fn first_difference_string(&fn_ctxt fcx, &bitv::t expected, &bitv::t actual)
-> str {
let str s = "";
auto done = false;
for (norm_constraint c in constraints(fcx)) {
if (!done) {
if (bitv::get(expected, c.bit_num) &&
!bitv::get(actual, c.bit_num)) {
/*
FIXME
for fun, try either:
* "ret s" after the assignment to s
or
* using break here
*/
!bitv::get(actual, c.bit_num)) {
/*
FIXME
for fun, try either:
* "ret s" after the assignment to s
or
* using break here
*/
s = constraint_to_str(fcx.ccx.tcx, c.c);
done = true;
done = true;
}
}
}
ret s;
}
fn log_bitv_err(fn_ctxt fcx, bitv::t v) {
log_err(bitv_to_str(fcx, v));
fn log_bitv_err(fn_ctxt fcx, bitv::t v) { log_err bitv_to_str(fcx, v); }
fn tos(vec[uint] v) -> str {
auto res = "";
for (uint i in v) { if (i == 0u) { res += "0"; } else { res += "1"; } }
ret res;
}
fn tos (vec[uint] v) -> str {
auto res = "";
for (uint i in v) {
if (i == 0u) {
res += "0";
}
else {
res += "1";
}
}
ret res;
fn log_cond(vec[uint] v) { log tos(v); }
fn log_cond_err(vec[uint] v) { log_err tos(v); }
fn log_pp(&pre_and_post pp) {
auto p1 = bitv::to_vec(pp.precondition);
auto p2 = bitv::to_vec(pp.postcondition);
log "pre:";
log_cond(p1);
log "post:";
log_cond(p2);
}
fn log_cond(vec[uint] v) -> () {
log(tos(v));
}
fn log_cond_err(vec[uint] v) -> () {
log_err(tos(v));
fn log_pp_err(&pre_and_post pp) {
auto p1 = bitv::to_vec(pp.precondition);
auto p2 = bitv::to_vec(pp.postcondition);
log_err "pre:";
log_cond_err(p1);
log_err "post:";
log_cond_err(p2);
}
fn log_pp(&pre_and_post pp) -> () {
auto p1 = bitv::to_vec(pp.precondition);
auto p2 = bitv::to_vec(pp.postcondition);
log("pre:");
log_cond(p1);
log("post:");
log_cond(p2);
fn log_states(&pre_and_post_state pp) {
auto p1 = bitv::to_vec(pp.prestate);
auto p2 = bitv::to_vec(pp.poststate);
log "prestate:";
log_cond(p1);
log "poststate:";
log_cond(p2);
}
fn log_pp_err(&pre_and_post pp) -> () {
auto p1 = bitv::to_vec(pp.precondition);
auto p2 = bitv::to_vec(pp.postcondition);
log_err("pre:");
log_cond_err(p1);
log_err("post:");
log_cond_err(p2);
fn log_states_err(&pre_and_post_state pp) {
auto p1 = bitv::to_vec(pp.prestate);
auto p2 = bitv::to_vec(pp.poststate);
log_err "prestate:";
log_cond_err(p1);
log_err "poststate:";
log_cond_err(p2);
}
fn log_states(&pre_and_post_state pp) -> () {
auto p1 = bitv::to_vec(pp.prestate);
auto p2 = bitv::to_vec(pp.poststate);
log("prestate:");
log_cond(p1);
log("poststate:");
log_cond(p2);
}
fn print_ident(&ident i) { log " " + i + " "; }
fn log_states_err(&pre_and_post_state pp) -> () {
auto p1 = bitv::to_vec(pp.prestate);
auto p2 = bitv::to_vec(pp.poststate);
log_err("prestate:");
log_cond_err(p1);
log_err("poststate:");
log_cond_err(p2);
}
fn print_ident(&ident i) -> () {
log(" " + i + " ");
}
fn print_idents(vec[ident] idents) -> () {
if (len[ident](idents) == 0u) {
ret;
}
else {
log("an ident: " + pop[ident](idents));
print_idents(idents);
}
fn print_idents(vec[ident] idents) {
if (len[ident](idents) == 0u) {
ret;
} else { log "an ident: " + pop[ident](idents); print_idents(idents); }
}
/* data structures */
/**********************************************************************/
/* Two different data structures represent constraints in different
contexts: constraint and norm_constraint.
@ -234,116 +197,108 @@ to represent predicate *arguments* however. This type
Both types store an ident and span, for error-logging purposes.
*/
type pred_desc_ = rec(vec[@constr_arg_use] args, uint bit_num);
type pred_desc_ = rec(vec[@constr_arg_use] args,
uint bit_num);
type pred_desc = spanned[pred_desc_];
tag constraint {
cinit(uint, span, ident);
cpred(path, @mutable vec[pred_desc]);
}
tag constr__ {
ninit(ident);
npred(path, vec[@constr_arg_use]);
}
tag constr__ { ninit(ident); npred(path, vec[@constr_arg_use]); }
type constr_ = rec(def_id id, constr__ c);
type constr = spanned[constr_];
type norm_constraint = rec(uint bit_num,
constr c);
type norm_constraint = rec(uint bit_num, constr c);
type constr_map = @std::map::hashmap[def_id, constraint];
type fn_info = rec(constr_map constrs, uint num_constraints, controlflow cf);
type fn_info = rec(constr_map constrs, uint num_constraints, controlflow cf);
/* mapping from node ID to typestate annotation */
type node_ann_table = @mutable vec[mutable ts_ann];
/* mapping from function name to fn_info map */
type fn_info_map = @std::map::hashmap[def_id, fn_info];
type fn_ctxt = rec(fn_info enclosing,
def_id id,
ident name,
crate_ctxt ccx);
type fn_ctxt = rec(fn_info enclosing, def_id id, ident name, crate_ctxt ccx);
type crate_ctxt = rec(ty::ctxt tcx,
node_ann_table node_anns,
fn_info_map fm);
type crate_ctxt = rec(ty::ctxt tcx, node_ann_table node_anns, fn_info_map fm);
fn get_fn_info(&crate_ctxt ccx, def_id did) -> fn_info {
assert (ccx.fm.contains_key(did));
ret ccx.fm.get(did);
}
fn add_node(&crate_ctxt ccx, uint i, &ts_ann a) -> () {
auto sz = len(*(ccx.node_anns));
if (sz <= i) {
grow(*(ccx.node_anns), (i - sz) + 1u, empty_ann(0u));
}
fn add_node(&crate_ctxt ccx, uint i, &ts_ann a) {
auto sz = len(*ccx.node_anns);
if (sz <= i) { grow(*ccx.node_anns, i - sz + 1u, empty_ann(0u)); }
ccx.node_anns.(i) = a;
}
fn get_ts_ann(&crate_ctxt ccx, uint i) -> option::t[ts_ann] {
if (i < len(*(ccx.node_anns))) {
if (i < len(*ccx.node_anns)) {
ret some[ts_ann](ccx.node_anns.(i));
}
else {
ret none[ts_ann];
}
} else { ret none[ts_ann]; }
}
/********* utils ********/
/********* utils ********/
fn ann_to_ts_ann(&crate_ctxt ccx, &ann a) -> ts_ann {
alt (get_ts_ann(ccx, a.id)) {
case (none) {
log_err ("ann_to_ts_ann: no ts_ann for node_id "
+ uistr(a.id));
case (none) {
log_err "ann_to_ts_ann: no ts_ann for node_id " + uistr(a.id);
fail;
}
case (some(?t)) { ret t; }
case (some(?t)) { ret t; }
}
}
fn ann_to_poststate(&crate_ctxt ccx, ann a) -> poststate {
log "ann_to_poststate";
ret (ann_to_ts_ann(ccx, a)).states.poststate;
ret ann_to_ts_ann(ccx, a).states.poststate;
}
fn stmt_to_ann(&crate_ctxt ccx, &stmt s) -> ts_ann {
log "stmt_to_ann";
alt (s.node) {
case (stmt_decl(_,?a)) {
ret ann_to_ts_ann(ccx, a);
alt (s.node) {
case (stmt_decl(_, ?a)) { ret ann_to_ts_ann(ccx, a); }
case (stmt_expr(_, ?a)) { ret ann_to_ts_ann(ccx, a); }
case (stmt_crate_directive(_)) {
log_err "expecting an annotated statement here";
fail;
}
}
case (stmt_expr(_,?a)) {
ret ann_to_ts_ann(ccx, a);
}
case (stmt_crate_directive(_)) {
log_err "expecting an annotated statement here";
fail;
}
}
}
/* fails if e has no annotation */
fn expr_states(&crate_ctxt ccx, @expr e) -> pre_and_post_state {
log "expr_states";
ret (ann_to_ts_ann(ccx, expr_ann(e)).states);
ret ann_to_ts_ann(ccx, expr_ann(e)).states;
}
/* fails if e has no annotation */
fn expr_pp(&crate_ctxt ccx, @expr e) -> pre_and_post {
log "expr_pp";
ret (ann_to_ts_ann(ccx, expr_ann(e)).conditions);
ret ann_to_ts_ann(ccx, expr_ann(e)).conditions;
}
fn stmt_pp(&crate_ctxt ccx, &stmt s) -> pre_and_post {
ret (stmt_to_ann(ccx, s).conditions);
ret stmt_to_ann(ccx, s).conditions;
}
/* fails if b has no annotation */
fn block_pp(&crate_ctxt ccx, &block b) -> pre_and_post {
log "block_pp";
ret (ann_to_ts_ann(ccx, b.node.a).conditions);
ret ann_to_ts_ann(ccx, b.node.a).conditions;
}
fn clear_pp(pre_and_post pp) {
@ -358,61 +313,61 @@ fn clear_precond(&crate_ctxt ccx, &ann a) {
fn block_states(&crate_ctxt ccx, &block b) -> pre_and_post_state {
log "block_states";
ret (ann_to_ts_ann(ccx, b.node.a).states);
ret ann_to_ts_ann(ccx, b.node.a).states;
}
fn stmt_states(&crate_ctxt ccx, &stmt s) -> pre_and_post_state {
ret (stmt_to_ann(ccx, s)).states;
ret stmt_to_ann(ccx, s).states;
}
fn expr_precond(&crate_ctxt ccx, @expr e) -> precond {
ret (expr_pp(ccx, e)).precondition;
ret expr_pp(ccx, e).precondition;
}
fn expr_postcond(&crate_ctxt ccx, @expr e) -> postcond {
ret (expr_pp(ccx, e)).postcondition;
ret expr_pp(ccx, e).postcondition;
}
fn expr_prestate(&crate_ctxt ccx, @expr e) -> prestate {
ret (expr_states(ccx, e)).prestate;
ret expr_states(ccx, e).prestate;
}
fn expr_poststate(&crate_ctxt ccx, @expr e) -> poststate {
ret (expr_states(ccx, e)).poststate;
ret expr_states(ccx, e).poststate;
}
fn stmt_precond(&crate_ctxt ccx, &stmt s) -> precond {
ret (stmt_pp(ccx, s)).precondition;
ret stmt_pp(ccx, s).precondition;
}
fn stmt_postcond(&crate_ctxt ccx, &stmt s) -> postcond {
ret (stmt_pp(ccx, s)).postcondition;
ret stmt_pp(ccx, s).postcondition;
}
fn states_to_poststate(&pre_and_post_state ss) -> poststate {
ret ss.poststate;
ret ss.poststate;
}
fn stmt_prestate(&crate_ctxt ccx, &stmt s) -> prestate {
ret (stmt_states(ccx, s)).prestate;
ret stmt_states(ccx, s).prestate;
}
fn stmt_poststate(&crate_ctxt ccx, &stmt s) -> poststate {
ret (stmt_states(ccx, s)).poststate;
ret stmt_states(ccx, s).poststate;
}
fn block_postcond(&crate_ctxt ccx, &block b) -> postcond {
ret (block_pp(ccx, b)).postcondition;
ret block_pp(ccx, b).postcondition;
}
fn block_poststate(&crate_ctxt ccx, &block b) -> poststate {
ret (block_states(ccx, b)).poststate;
ret block_states(ccx, b).poststate;
}
/* sets the pre_and_post for an ann */
fn with_pp(&crate_ctxt ccx, &ann a, pre_and_post p) {
add_node(ccx, a.id, @rec(conditions=p,
states=empty_states(pps_len(p))));
add_node(ccx, a.id, @rec(conditions=p, states=empty_states(pps_len(p))));
}
fn set_prestate_ann(&crate_ctxt ccx, &ann a, &prestate pre) -> bool {
@ -420,7 +375,6 @@ fn set_prestate_ann(&crate_ctxt ccx, &ann a, &prestate pre) -> bool {
ret set_prestate(ann_to_ts_ann(ccx, a), pre);
}
fn extend_prestate_ann(&crate_ctxt ccx, &ann a, &prestate pre) -> bool {
log "extend_prestate_ann";
ret extend_prestate(ann_to_ts_ann(ccx, a).states.prestate, pre);
@ -436,15 +390,14 @@ fn extend_poststate_ann(&crate_ctxt ccx, &ann a, &poststate post) -> bool {
ret extend_poststate(ann_to_ts_ann(ccx, a).states.poststate, post);
}
fn set_pre_and_post(&crate_ctxt ccx, &ann a,
&precond pre, &postcond post) -> () {
fn set_pre_and_post(&crate_ctxt ccx, &ann a, &precond pre, &postcond post) {
log "set_pre_and_post";
auto t = ann_to_ts_ann(ccx, a);
set_precondition(t, pre);
set_postcondition(t, post);
}
fn copy_pre_post(&crate_ctxt ccx, &ann a, &@expr sub) -> () {
fn copy_pre_post(&crate_ctxt ccx, &ann a, &@expr sub) {
log "set_pre_and_post";
auto p = expr_pp(ccx, sub);
auto t = ann_to_ts_ann(ccx, a);
@ -460,29 +413,25 @@ fn set_postcond_false(&crate_ctxt ccx, &ann a) {
}
fn pure_exp(&crate_ctxt ccx, &ann a, &prestate p) -> bool {
auto changed = false;
changed = extend_prestate_ann(ccx, a, p) || changed;
changed = extend_poststate_ann(ccx, a, p) || changed;
ret changed;
auto changed = false;
changed = extend_prestate_ann(ccx, a, p) || changed;
changed = extend_poststate_ann(ccx, a, p) || changed;
ret changed;
}
fn fixed_point_states(&fn_ctxt fcx,
fn (&fn_ctxt, &_fn) -> bool f, &_fn start) -> () {
fn fixed_point_states(&fn_ctxt fcx, fn(&fn_ctxt, &_fn) -> bool f,
&_fn start) {
auto changed = f(fcx, start);
if (changed) {
ret fixed_point_states(fcx, f, start);
} else {
// we're done!
auto changed = f(fcx, start);
if (changed) {
ret fixed_point_states(fcx, f, start);
}
else {
// we're done!
ret;
}
ret;
}
}
fn num_constraints(fn_info m) -> uint {
ret m.num_constraints;
}
fn num_constraints(fn_info m) -> uint { ret m.num_constraints; }
fn new_crate_ctxt(ty::ctxt cx) -> crate_ctxt {
let vec[mutable ts_ann] na = vec::empty_mut();
@ -492,40 +441,32 @@ fn new_crate_ctxt(ty::ctxt cx) -> crate_ctxt {
fn controlflow_def_id(&crate_ctxt ccx, &def_id d) -> controlflow {
alt (ccx.fm.find(d)) {
case (some(?fi)) { ret fi.cf; }
case (none) { ret return; }
case (none) { ret return; }
}
}
/* Use e's type to determine whether it returns.
If it has a function type with a ! annotation,
the answer is noreturn. */
fn controlflow_expr(&crate_ctxt ccx, @expr e) -> controlflow {
alt (ty::struct(ccx.tcx, ty::ann_to_type(ccx.tcx,
expr_ann(e)))) {
case (ty::ty_fn(_,_,_,?cf,_)) {
ret cf;
}
case (_) {
ret return;
}
alt (ty::struct(ccx.tcx, ty::ann_to_type(ccx.tcx, expr_ann(e)))) {
case (ty::ty_fn(_, _, _, ?cf, _)) { ret cf; }
case (_) { ret return; }
}
}
fn constraints_expr(&ty::ctxt cx, @expr e) -> vec[@ast::constr] {
alt (ty::struct(cx, ty::ann_to_type(cx, expr_ann(e)))) {
case (ty::ty_fn(_,_,_,_,?cs)) {
ret cs;
}
case (_) {
ret [];
}
case (ty::ty_fn(_, _, _, _, ?cs)) { ret cs; }
case (_) { ret []; }
}
}
fn ann_to_def_strict(&ty::ctxt cx, &ann a) -> def {
alt (cx.def_map.find(a.id)) {
case (none) {
log_err("ann_to_def: node_id " + uistr(a.id) + " has no def");
case (none) {
log_err "ann_to_def: node_id " + uistr(a.id) + " has no def";
fail;
}
case (some(?d)) { ret d; }
@ -544,49 +485,48 @@ fn norm_a_constraint(&def_id id, &constraint c) -> vec[norm_constraint] {
case (cpred(?p, ?descs)) {
let vec[norm_constraint] res = [];
for (pred_desc pd in *descs) {
vec::push(res, rec(bit_num=pd.node.bit_num,
c=respan(pd.span, rec(id=id, c=npred(p, pd.node.args)))));
vec::push(res,
rec(bit_num=pd.node.bit_num,
c=respan(pd.span,
rec(id=id,
c=npred(p, pd.node.args)))));
}
ret res;
}
}
}
// Tried to write this as an iterator, but I got a
// non-exhaustive match in trans.
fn constraints(&fn_ctxt fcx) -> vec[norm_constraint] {
let vec[norm_constraint] res = [];
for each (@tup(def_id, constraint) p in
fcx.enclosing.constrs.items()) {
for each (@tup(def_id, constraint) p in fcx.enclosing.constrs.items()) {
res += norm_a_constraint(p._0, p._1);
}
ret res;
}
// FIXME:
// this probably doesn't handle name shadowing well (or at all)
// variables should really always be id'd by def_id and not ident
fn match_args(&fn_ctxt fcx, vec[pred_desc] occs,
vec[@constr_arg_use] occ) -> uint {
log ("match_args: looking at " +
pretty::ppaux::constr_args_to_str_1(occ));
fn match_args(&fn_ctxt fcx, vec[pred_desc] occs, vec[@constr_arg_use] occ) ->
uint {
log "match_args: looking at " + pretty::ppaux::constr_args_to_str_1(occ);
for (pred_desc pd in occs) {
log ("match_args: candidate " + pred_desc_to_str(pd));
if (ty::args_eq(str::eq, pd.node.args, occ)) {
ret pd.node.bit_num;
}
log "match_args: candidate " + pred_desc_to_str(pd);
if (ty::args_eq(str::eq, pd.node.args, occ)) { ret pd.node.bit_num; }
}
fcx.ccx.tcx.sess.bug("match_args: no match for occurring args");
fcx.ccx.tcx.sess.bug("match_args: no match for occurring args");
}
fn def_id_for_constr(ty::ctxt tcx, uint t) -> def_id {
alt (tcx.def_map.find(t)) {
case (none) {
tcx.sess.bug("def_id_for_constr: bad node_id " + uistr(t));
}
case (some(def_fn(?i))) {
ret i;
}
case (some(def_fn(?i))) { ret i; }
case (_) {
tcx.sess.bug("def_id_for_constr: pred is not a function");
}
@ -598,60 +538,59 @@ fn expr_to_constr_arg(ty::ctxt tcx, &@expr e) -> @constr_arg_use {
case (expr_path(?p, _)) {
if (vec::len(p.node.idents) == 1u) {
ret @respan(p.span, carg_ident[ident](p.node.idents.(0)));
}
else {
tcx.sess.bug("exprs_to_constr_args: non-local variable "
+ "as pred arg");
} else {
tcx.sess.bug("exprs_to_constr_args: non-local variable " +
"as pred arg");
}
}
case (expr_lit(?l, _)) {
ret @respan(e.span, carg_lit(l));
}
case (expr_lit(?l, _)) { ret @respan(e.span, carg_lit(l)); }
case (_) {
tcx.sess.bug("exprs_to_constr_args: ill-formed pred arg");
}
}
}
fn exprs_to_constr_args(ty::ctxt tcx, vec[@expr] args)
-> vec[@constr_arg_use] {
fn exprs_to_constr_args(ty::ctxt tcx, vec[@expr] args) ->
vec[@constr_arg_use] {
auto f = bind expr_to_constr_arg(tcx, _);
ret vec::map(f, args);
ret vec::map(f, args);
}
fn expr_to_constr(ty::ctxt tcx, &@expr e) -> constr {
alt (e.node) {
// FIXME
// change the first pattern to expr_path to test a typechecker bug
case (expr_call(?operator, ?args, _)) {
case (
// FIXME change the first pattern to expr_path to test a
// typechecker bug
expr_call(?operator, ?args, _)) {
alt (operator.node) {
case (expr_path(?p, ?a)) {
ret respan(e.span,
rec(id=def_id_for_constr(tcx, a.id),
c=npred(p,
exprs_to_constr_args(tcx, args))));
rec(id=def_id_for_constr(tcx, a.id),
c=npred(p,
exprs_to_constr_args(tcx, args))));
}
case (_) {
tcx.sess.span_err(operator.span, "Internal error: " +
" ill-formed operator in predicate");
tcx.sess.span_err(operator.span,
"Internal error: " +
" ill-formed operator \
in predicate");
}
}
}
case (_) {
tcx.sess.span_err(e.span, "Internal error: " +
" ill-formed predicate");
tcx.sess.span_err(e.span,
"Internal error: " + " ill-formed predicate");
}
}
}
fn pred_desc_to_str(&pred_desc p) -> str {
ret ("<" + uistr(p.node.bit_num) + ", " +
pretty::ppaux::constr_args_to_str_1(p.node.args) + ">");
ret "<" + uistr(p.node.bit_num) + ", " +
pretty::ppaux::constr_args_to_str_1(p.node.args) + ">";
}
fn substitute_constr_args(&ty::ctxt cx,
&vec[@expr] actuals, &@ast::constr c)
-> constr__ {
fn substitute_constr_args(&ty::ctxt cx, &vec[@expr] actuals, &@ast::constr c)
-> constr__ {
let vec[@constr_arg_use] res = [];
for (@constr_arg a in c.node.args) {
res += [substitute_arg(cx, actuals, a)];
@ -661,31 +600,26 @@ fn substitute_constr_args(&ty::ctxt cx,
type subst = vec[tup(arg, @expr)];
fn substitute_arg(&ty::ctxt cx, &vec[@expr] actuals, @ast::constr_arg a)
-> @constr_arg_use {
fn substitute_arg(&ty::ctxt cx, &vec[@expr] actuals, @ast::constr_arg a) ->
@constr_arg_use {
auto num_actuals = vec::len(actuals);
alt (a.node) {
case (carg_ident(?i)) {
if (i < num_actuals) {
ret expr_to_constr_arg(cx, actuals.(i));
}
else {
} else {
cx.sess.span_err(a.span, "Constraint argument out of bounds");
}
}
case (carg_base) { ret @respan(a.span, carg_base); }
case (carg_lit(?l)) { ret @respan(a.span, carg_lit(l)); }
case (carg_lit(?l)) { ret @respan(a.span, carg_lit(l)); }
}
}
fn path_to_ident(&ty::ctxt cx, &path p) -> ident {
alt (vec::last(p.node.idents)) {
case (none) {
cx.sess.span_err(p.span, "Malformed path");
}
case (some(?i)) {
ret i;
}
case (none) { cx.sess.span_err(p.span, "Malformed path"); }
case (some(?i)) { ret i; }
}
}
//
@ -698,4 +632,3 @@ fn path_to_ident(&ty::ctxt cx, &path p) -> ident {
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
//

View File

@ -1,10 +1,9 @@
import std::bitv;
import std::vec;
import std::vec::len;
import std::vec::slice;
import front::ast::*;
import aux::fn_ctxt;
import aux::fn_info;
import aux::log_bitv;
@ -16,7 +15,6 @@ import aux::npred;
import aux::pred_desc;
import aux::match_args;
import aux::constr_;
import tstate::aux::ann_to_ts_ann;
import tstate::ann::pre_and_post;
import tstate::ann::precond;
@ -34,30 +32,26 @@ import tstate::ann::clone;
import tstate::ann::set_in_postcond;
import tstate::ann::set_in_poststate;
import tstate::ann::clear_in_poststate;
fn bit_num(&fn_ctxt fcx, &constr_ c) -> uint {
assert (fcx.enclosing.constrs.contains_key(c.id));
auto res = fcx.enclosing.constrs.get(c.id);
alt (c.c) {
case (ninit(_)) {
alt (res) {
case (cinit(?n,_,_)) {
ret n;
}
case (cinit(?n, _, _)) { ret n; }
case (_) {
fcx.ccx.tcx.sess.bug("bit_num: asked for init constraint,"
+ " found a pred constraint");
+ " found a pred constraint");
}
}
}
case (npred(_, ?args)) {
alt (res) {
case (cpred(_, ?descs)) {
ret match_args(fcx, *descs, args);
}
case (cpred(_, ?descs)) { ret match_args(fcx, *descs, args); }
case (_) {
fcx.ccx.tcx.sess.bug("bit_num: asked for pred constraint,"
+ " found an init constraint");
+ " found an init constraint");
}
}
}
@ -68,84 +62,75 @@ fn promises(&fn_ctxt fcx, &poststate p, &constr_ c) -> bool {
ret bitv::get(p, bit_num(fcx, c));
}
// Given a list of pres and posts for exprs e0 ... en,
// return the precondition for evaluating each expr in order.
// So, if e0's post is {x} and e1's pre is {x, y, z}, the entire
// precondition shouldn't include x.
fn seq_preconds(fn_ctxt fcx, vec[pre_and_post] pps) -> precond {
let uint sz = len[pre_and_post](pps);
let uint num_vars = num_constraints(fcx.enclosing);
if (sz >= 1u) {
auto first = pps.(0);
assert (pps_len(first) == num_vars);
let precond rest = seq_preconds(fcx,
slice[pre_and_post](pps, 1u, sz));
difference(rest, first.postcondition);
auto res = clone(first.precondition);
union(res, rest);
log("seq_preconds:");
log("first.postcondition =");
log_bitv(fcx, first.postcondition);
log("rest =");
log_bitv(fcx, rest);
log("returning");
log_bitv(fcx, res);
ret res;
}
else {
ret true_precond(num_vars);
}
let uint sz = len[pre_and_post](pps);
let uint num_vars = num_constraints(fcx.enclosing);
if (sz >= 1u) {
auto first = pps.(0);
assert (pps_len(first) == num_vars);
let precond rest =
seq_preconds(fcx, slice[pre_and_post](pps, 1u, sz));
difference(rest, first.postcondition);
auto res = clone(first.precondition);
union(res, rest);
log "seq_preconds:";
log "first.postcondition =";
log_bitv(fcx, first.postcondition);
log "rest =";
log_bitv(fcx, rest);
log "returning";
log_bitv(fcx, res);
ret res;
} else { ret true_precond(num_vars); }
}
/* works on either postconds or preconds
should probably rethink the whole type synonym situation */
fn union_postconds_go(&postcond first, &vec[postcond] rest) -> postcond {
auto sz = vec::len[postcond](rest);
if (sz > 0u) {
auto other = rest.(0);
union(first, other);
union_postconds_go(first, slice[postcond](rest, 1u, len[postcond](rest)));
}
ret first;
auto sz = vec::len[postcond](rest);
if (sz > 0u) {
auto other = rest.(0);
union(first, other);
union_postconds_go(first,
slice[postcond](rest, 1u, len[postcond](rest)));
}
ret first;
}
fn union_postconds(uint nv, &vec[postcond] pcs) -> postcond {
if (len[postcond](pcs) > 0u) {
ret union_postconds_go(bitv::clone(pcs.(0)), pcs);
}
else {
ret empty_prestate(nv);
}
if (len[postcond](pcs) > 0u) {
ret union_postconds_go(bitv::clone(pcs.(0)), pcs);
} else { ret empty_prestate(nv); }
}
/* Gee, maybe we could use foldl or something */
fn intersect_postconds_go(&postcond first, &vec[postcond] rest) -> postcond {
auto sz = vec::len[postcond](rest);
if (sz > 0u) {
auto other = rest.(0);
intersect(first, other);
intersect_postconds_go(first, slice[postcond](rest, 1u,
len[postcond](rest)));
}
ret first;
auto sz = vec::len[postcond](rest);
if (sz > 0u) {
auto other = rest.(0);
intersect(first, other);
intersect_postconds_go(first,
slice[postcond](rest, 1u,
len[postcond](rest)));
}
ret first;
}
fn intersect_postconds(&vec[postcond] pcs) -> postcond {
assert (len[postcond](pcs) > 0u);
ret intersect_postconds_go(bitv::clone(pcs.(0)), pcs);
assert (len[postcond](pcs) > 0u);
ret intersect_postconds_go(bitv::clone(pcs.(0)), pcs);
}
fn gen(&fn_ctxt fcx, &ann a, &constr_ c) -> bool {
ret set_in_postcond(bit_num(fcx, c),
(ann_to_ts_ann(fcx.ccx, a)).conditions);
ret set_in_postcond(bit_num(fcx, c),
ann_to_ts_ann(fcx.ccx, a).conditions);
}
fn declare_var(&fn_ctxt fcx, &constr_ c, prestate pre) -> prestate {
@ -155,17 +140,14 @@ fn declare_var(&fn_ctxt fcx, &constr_ c, prestate pre) -> prestate {
}
fn gen_poststate(&fn_ctxt fcx, &ann a, &constr_ c) -> bool {
log "gen_poststate";
ret set_in_poststate(bit_num(fcx, c),
(ann_to_ts_ann(fcx.ccx, a)).states);
log "gen_poststate";
ret set_in_poststate(bit_num(fcx, c), ann_to_ts_ann(fcx.ccx, a).states);
}
fn kill_poststate(&fn_ctxt fcx, &ann a, &constr_ c) -> bool {
log "kill_poststate";
ret clear_in_poststate(bit_num(fcx, c),
(ann_to_ts_ann(fcx.ccx, a)).states);
log "kill_poststate";
ret clear_in_poststate(bit_num(fcx, c), ann_to_ts_ann(fcx.ccx, a).states);
}
//
// Local Variables:
// mode: rust

View File

@ -1,3 +1,4 @@
import front::ast;
import front::ast::method;
import front::ast::ann;
@ -13,7 +14,6 @@ import front::ast::ty_param;
import front::ast::crate;
import front::ast::return;
import front::ast::noreturn;
import front::ast::expr;
import middle::ty::type_is_nil;
import middle::ty::ret_ty_of_fn;
@ -36,12 +36,10 @@ import std::vec::slice;
import std::vec::unzip;
import std::vec::plus_option;
import std::vec::cat_options;
import std::option;
import std::option::t;
import std::option::some;
import std::option::none;
import aux::fn_ctxt;
import aux::crate_ctxt;
import aux::new_crate_ctxt;
@ -54,39 +52,37 @@ import aux::num_constraints;
import aux::fixed_point_states;
import aux::bitv_to_str;
import aux::first_difference_string;
import pretty::pprust::ty_to_str;
import util::common::log_stmt_err;
import aux::log_bitv_err;
import bitvectors::promises;
import annotate::annotate_crate;
import collect_locals::mk_f_to_fn_info;
import pre_post_conditions::fn_pre_post;
import states::find_pre_post_state_fn;
fn check_states_expr(&fn_ctxt fcx, @expr e) -> () {
let precond prec = expr_precond(fcx.ccx, e);
fn check_states_expr(&fn_ctxt fcx, @expr e) {
let precond prec = expr_precond(fcx.ccx, e);
let prestate pres = expr_prestate(fcx.ccx, e);
if (!implies(pres, prec)) {
auto s = "";
auto diff = first_difference_string(fcx, prec, pres);
s += ("Unsatisfied precondition constraint (for example, "
+ diff + ") for expression:\n");
s +=
"Unsatisfied precondition constraint (for example, " + diff +
") for expression:\n";
s += pretty::pprust::expr_to_str(e);
s += ("\nPrecondition:\n");
s += "\nPrecondition:\n";
s += bitv_to_str(fcx, prec);
s += ("\nPrestate:\n");
s += "\nPrestate:\n";
s += bitv_to_str(fcx, pres);
fcx.ccx.tcx.sess.span_err(e.span, s);
}
}
fn check_states_stmt(&fn_ctxt fcx, &stmt s) -> () {
fn check_states_stmt(&fn_ctxt fcx, &stmt s) {
auto a = stmt_to_ann(fcx.ccx, s);
let precond prec = ann_precond(a);
let prestate pres = ann_prestate(a);
let precond prec = ann_precond(a);
let prestate pres = ann_prestate(a);
/*
log_err("check_states_stmt:");
@ -96,113 +92,109 @@ fn check_states_stmt(&fn_ctxt fcx, &stmt s) -> () {
log_err("pres = ");
log_bitv_err(fcx.enclosing, pres);
*/
if (!implies(pres, prec)) {
auto ss = "";
auto diff = first_difference_string(fcx, prec, pres);
ss += ("Unsatisfied precondition constraint (for example, "
+ diff + ") for statement:\n");
ss +=
"Unsatisfied precondition constraint (for example, " + diff +
") for statement:\n";
ss += pretty::pprust::stmt_to_str(s);
ss += ("\nPrecondition:\n");
ss += "\nPrecondition:\n";
ss += bitv_to_str(fcx, prec);
ss += ("\nPrestate: \n");
ss += "\nPrestate: \n";
ss += bitv_to_str(fcx, pres);
fcx.ccx.tcx.sess.span_err(s.span, ss);
}
}
fn check_states_against_conditions(&fn_ctxt fcx, &_fn f, &ann a) -> () {
fn check_states_against_conditions(&fn_ctxt fcx, &_fn f, &ann a) {
auto enclosing = fcx.enclosing;
auto nv = num_constraints(enclosing);
auto nv = num_constraints(enclosing);
auto post = @mutable empty_poststate(nv);
fn do_one_(fn_ctxt fcx, &@stmt s, @mutable poststate post) -> () {
fn do_one_(fn_ctxt fcx, &@stmt s, @mutable poststate post) {
check_states_stmt(fcx, *s);
*post = stmt_poststate(fcx.ccx, *s);
}
auto do_one = bind do_one_(fcx, _, post);
vec::map[@stmt, ()](do_one, f.body.node.stmts);
fn do_inner_(fn_ctxt fcx, &@expr e, @mutable poststate post) -> () {
fn do_inner_(fn_ctxt fcx, &@expr e, @mutable poststate post) {
check_states_expr(fcx, e);
*post = expr_poststate(fcx.ccx, e);
}
auto do_inner = bind do_inner_(fcx, _, post);
option::map[@expr, ()](do_inner, f.body.node.expr);
auto cf = fcx.enclosing.cf;
/* Finally, check that the return value is initialized */
let aux::constr_ ret_c = rec(id=fcx.id, c=aux::ninit(fcx.name));
if (f.proto == ast::proto_fn
&& ! promises(fcx, {*post}, ret_c)
&& ! type_is_nil(fcx.ccx.tcx,
ret_ty_of_fn(fcx.ccx.tcx, a))
&& cf == return) {
fcx.ccx.tcx.sess.span_note(f.body.span, "In function " + fcx.name +
", not all control paths return a value");
if (f.proto == ast::proto_fn && !promises(fcx, { *post }, ret_c) &&
!type_is_nil(fcx.ccx.tcx, ret_ty_of_fn(fcx.ccx.tcx, a)) &&
cf == return) {
fcx.ccx.tcx.sess.span_note(f.body.span,
"In function " + fcx.name +
", not all control paths \
return a value");
fcx.ccx.tcx.sess.span_err(f.decl.output.span,
"see declared return type of '" + ty_to_str(*f.decl.output) +
"'");
}
else if (cf == noreturn) {
"see declared return type of '" +
ty_to_str(*f.decl.output) + "'");
} else if (cf == noreturn) {
// check that this really always fails
// the fcx.id bit means "returns" for a returning fn,
// "diverges" for a non-returning fn
if (! promises(fcx, {*post}, ret_c)) {
if (!promises(fcx, { *post }, ret_c)) {
fcx.ccx.tcx.sess.span_err(f.body.span,
"In non-returning function " + fcx.name +
", some control paths may return to the caller");
"In non-returning function " + fcx.name
+ ", some control paths may \
return to the caller");
}
}
}
fn check_fn_states(&fn_ctxt fcx, &_fn f, &ann a) -> () {
fn check_fn_states(&fn_ctxt fcx, &_fn f, &ann a) {
/* Compute the pre- and post-states for this function */
auto g = find_pre_post_state_fn;
fixed_point_states(fcx, g, f);
/* Now compare each expr's pre-state to its precondition
and post-state to its postcondition */
check_states_against_conditions(fcx, f, a);
}
fn fn_states(&crate_ctxt ccx, &_fn f, &span sp, &ident i,
&def_id id, &ann a) -> () {
fn fn_states(&crate_ctxt ccx, &_fn f, &span sp, &ident i, &def_id id,
&ann a) {
/* Look up the var-to-bit-num map for this function */
assert (ccx.fm.contains_key(id));
auto f_info = ccx.fm.get(id);
auto fcx = rec(enclosing=f_info, id=id, name=i, ccx=ccx);
check_fn_states(fcx, f, a);
}
fn check_crate(ty::ctxt cx, @crate crate) -> () {
fn check_crate(ty::ctxt cx, @crate crate) {
let crate_ctxt ccx = new_crate_ctxt(cx);
/* Build the global map from function id to var-to-bit-num-map */
mk_f_to_fn_info(ccx, crate);
/* Add a blank ts_ann for every statement (and expression) */
annotate_crate(ccx, *crate);
mk_f_to_fn_info(ccx, crate);
/* Add a blank ts_ann for every statement (and expression) */
annotate_crate(ccx, *crate);
/* Compute the pre and postcondition for every subexpression */
auto do_pre_post = walk::default_visitor();
do_pre_post = rec(visit_fn_pre = bind fn_pre_post(ccx,_,_,_,_,_)
with do_pre_post);
do_pre_post =
rec(visit_fn_pre=bind fn_pre_post(ccx, _, _, _, _, _)
with do_pre_post);
walk::walk_crate(do_pre_post, *crate);
/* Check the pre- and postcondition against the pre- and poststate
for every expression */
auto do_states = walk::default_visitor();
do_states = rec(visit_fn_pre = bind fn_states(ccx,_,_,_,_,_)
with do_states);
do_states =
rec(visit_fn_pre=bind fn_states(ccx, _, _, _, _, _) with do_states);
walk::walk_crate(do_states, *crate);
}
//
// Local Variables:
// mode: rust

View File

@ -1,14 +1,12 @@
import std::vec;
import std::vec::plus_option;
import front::ast;
import front::ast::*;
import option::*;
import middle::walk::walk_crate;
import middle::walk::walk_fn;
import middle::walk::ast_visitor;
import aux::cinit;
import aux::ninit;
import aux::npred;
@ -21,7 +19,6 @@ import aux::constr_map;
import aux::expr_to_constr;
import aux::constraints_expr;
import aux::ann_to_def_strict;
import util::common::new_def_hash;
import util::common::uistr;
import util::common::span;
@ -29,28 +26,31 @@ import util::common::respan;
type ctxt = rec(@mutable vec[aux::constr] cs, ty::ctxt tcx);
fn collect_local(&ctxt cx, &@local loc) -> () {
log("collect_local: pushing " + loc.node.ident);
vec::push(*cx.cs, respan(loc.span,
rec(id=loc.node.id,
c=ninit(loc.node.ident))));
fn collect_local(&ctxt cx, &@local loc) {
log "collect_local: pushing " + loc.node.ident;
vec::push(*cx.cs,
respan(loc.span, rec(id=loc.node.id, c=ninit(loc.node.ident))));
}
fn collect_pred(&ctxt cx, &@expr e) -> () {
fn collect_pred(&ctxt cx, &@expr e) {
alt (e.node) {
case (expr_check(?e, _)) {
vec::push(*cx.cs, expr_to_constr(cx.tcx, e));
}
// If it's a call, generate appropriate instances of the
// call's constraints.
case (expr_call(?operator, ?operands, ?a)) {
case (
// If it's a call, generate appropriate instances of the
// call's constraints.
expr_call(?operator, ?operands, ?a)) {
for (@ast::constr c in constraints_expr(cx.tcx, operator)) {
auto d_id = ann_to_def_strict(cx.tcx, c.node.ann);
alt (d_id) {
case (def_fn(?an_id)) {
let aux::constr ct = respan(c.span,
rec(id=an_id, c=aux::substitute_constr_args(cx.tcx,
operands, c)));
let aux::constr ct =
respan(c.span,
rec(id=an_id,
c=aux::substitute_constr_args(cx.tcx,
operands,
c)));
vec::push(*cx.cs, ct);
}
case (_) {
@ -60,64 +60,64 @@ fn collect_pred(&ctxt cx, &@expr e) -> () {
}
}
// FIXME: constraints on result type
}
case (_) { }
}
}
fn find_locals(&ty::ctxt tcx, &_fn f, &span sp, &ident i, &def_id d, &ann a)
-> ctxt {
-> ctxt {
let ctxt cx = rec(cs=@mutable vec::alloc(0u), tcx=tcx);
auto visitor = walk::default_visitor();
visitor = rec(visit_local_pre=bind collect_local(cx,_),
visit_expr_pre=bind collect_pred(cx,_)
with visitor);
visitor =
rec(visit_local_pre=bind collect_local(cx, _),
visit_expr_pre=bind collect_pred(cx, _) with visitor);
walk_fn(visitor, f, sp, i, d, a);
ret cx;
}
fn add_constraint(&ty::ctxt tcx, aux::constr c, uint next, constr_map tbl)
-> uint {
log(aux::constraint_to_str(tcx, c) + " |-> "
+ util::common::uistr(next));
fn add_constraint(&ty::ctxt tcx, aux::constr c, uint next, constr_map tbl) ->
uint {
log aux::constraint_to_str(tcx, c) + " |-> " + util::common::uistr(next);
alt (c.node.c) {
case (ninit(?i)) {
tbl.insert(c.node.id, cinit(next, c.span, i));
}
case (ninit(?i)) { tbl.insert(c.node.id, cinit(next, c.span, i)); }
case (npred(?p, ?args)) {
alt (tbl.find(c.node.id)) {
case (some(?ct)) {
alt (ct) {
case (cinit(_,_,_)) {
tcx.sess.bug("add_constraint: same def_id used"
+ " as a variable and a pred");
case (cinit(_, _, _)) {
tcx.sess.bug("add_constraint: same def_id used" +
" as a variable and a pred");
}
case (cpred(_, ?pds)) {
vec::push(*pds, respan(c.span,
rec(args=args, bit_num=next)));
vec::push(*pds,
respan(c.span,
rec(args=args, bit_num=next)));
}
}
}
case (none) {
tbl.insert(c.node.id, cpred(p,
@mutable [respan(c.span, rec(args=args,
bit_num=next))]));
tbl.insert(c.node.id,
cpred(p,
@mutable [respan(c.span,
rec(args=args,
bit_num=next))]));
}
}
}
}
ret (next + 1u);
ret next + 1u;
}
/* builds a table mapping each local var defined in f
to a bit number in the precondition/postcondition vectors */
fn mk_fn_info(&crate_ctxt ccx, &_fn f, &span f_sp,
&ident f_name, &def_id f_id, &ann a)
-> () {
fn mk_fn_info(&crate_ctxt ccx, &_fn f, &span f_sp, &ident f_name,
&def_id f_id, &ann a) {
auto res_map = @new_def_hash[constraint]();
let uint next = 0u;
let vec[arg] f_args = f.decl.inputs;
/* ignore args, which we know are initialized;
just collect locally declared vars */
@ -125,35 +125,33 @@ fn mk_fn_info(&crate_ctxt ccx, &_fn f, &span f_sp,
/* now we have to add bit nums for both the constraints
and the variables... */
for (aux::constr c in {*cx.cs}) {
for (aux::constr c in { *cx.cs }) {
next = add_constraint(cx.tcx, c, next, res_map);
}
/* add a pseudo-entry for the function's return value
we can safely use the function's name itself for this purpose */
add_constraint(cx.tcx, respan(f_sp, rec(id=f_id, c=ninit(f_name))), next,
res_map);
auto res = rec(constrs=res_map,
num_constraints=vec::len(*cx.cs) + 1u,
cf=f.decl.cf);
auto res =
rec(constrs=res_map,
num_constraints=vec::len(*cx.cs) + 1u,
cf=f.decl.cf);
ccx.fm.insert(f_id, res);
log(f_name + " has " + uistr(num_constraints(res)) + " constraints");
log f_name + " has " + uistr(num_constraints(res)) + " constraints";
}
/* initializes the global fn_info_map (mapping each function ID, including
nested locally defined functions, onto a mapping from local variable name
to bit number) */
fn mk_f_to_fn_info(&crate_ctxt ccx, @crate c) -> () {
let ast_visitor vars_visitor = walk::default_visitor();
vars_visitor = rec(visit_fn_pre=bind mk_fn_info(ccx,_,_,_,_,_)
with vars_visitor);
walk_crate(vars_visitor, *c);
fn mk_f_to_fn_info(&crate_ctxt ccx, @crate c) {
let ast_visitor vars_visitor = walk::default_visitor();
vars_visitor =
rec(visit_fn_pre=bind mk_fn_info(ccx, _, _, _, _, _)
with vars_visitor);
walk_crate(vars_visitor, *c);
}
//
// Local Variables:
// mode: rust
@ -164,4 +162,3 @@ fn mk_f_to_fn_info(&crate_ctxt ccx, @crate c) -> () {
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
//

View File

@ -1,3 +1,4 @@
import std::vec;
import std::vec::plus_option;
import std::option;
@ -44,24 +45,21 @@ import aux::ann_to_ts_ann;
import aux::set_postcond_false;
import aux::controlflow_expr;
import aux::expr_to_constr;
//import aux::constr_to_constr_occ;
import aux::constraints_expr;
import aux::substitute_constr_args;
import aux::ninit;
import aux::npred;
import aux::path_to_ident;
import bitvectors::seq_preconds;
import bitvectors::union_postconds;
import bitvectors::intersect_postconds;
import bitvectors::declare_var;
import bitvectors::bit_num;
import bitvectors::gen;
import front::ast::*;
import middle::ty::expr_ann;
import util::common::new_def_hash;
import util::common::decl_lhs;
import util::common::uistr;
@ -77,180 +75,174 @@ import util::common::log_block;
import util::common::span;
fn find_pre_post_mod(&_mod m) -> _mod {
log("implement find_pre_post_mod!");
log "implement find_pre_post_mod!";
fail;
}
fn find_pre_post_native_mod(&native_mod m) -> native_mod {
log("implement find_pre_post_native_mod");
log "implement find_pre_post_native_mod";
fail;
}
fn find_pre_post_obj(&crate_ctxt ccx, _obj o) -> () {
fn do_a_method(crate_ctxt ccx, &@method m) -> () {
fn find_pre_post_obj(&crate_ctxt ccx, _obj o) {
fn do_a_method(crate_ctxt ccx, &@method m) {
assert (ccx.fm.contains_key(m.node.id));
let fn_ctxt fcx = rec(enclosing=ccx.fm.get(m.node.id),
id=m.node.id, name=m.node.ident, ccx=ccx);
let fn_ctxt fcx =
rec(enclosing=ccx.fm.get(m.node.id),
id=m.node.id,
name=m.node.ident,
ccx=ccx);
find_pre_post_fn(fcx, m.node.meth);
}
auto f = bind do_a_method(ccx,_);
auto f = bind do_a_method(ccx, _);
vec::map[@method, ()](f, o.methods);
option::map[@method, ()](f, o.dtor);
}
fn find_pre_post_item(&crate_ctxt ccx, &item i) -> () {
fn find_pre_post_item(&crate_ctxt ccx, &item i) {
alt (i.node) {
case (item_const(?id, ?t, ?e, _, ?di, ?a)) {
// make a fake fcx
auto fake_fcx = rec(enclosing=
rec(constrs=@new_def_hash[constraint](),
num_constraints=0u,
cf=return),
id=tup(0,0),
name="",
ccx=ccx);
auto fake_fcx =
rec(enclosing=rec(constrs=@new_def_hash[constraint](),
num_constraints=0u,
cf=return),
id=tup(0, 0),
name="",
ccx=ccx);
find_pre_post_expr(fake_fcx, e);
}
case (item_fn(?id, ?f, ?ps, _, ?di, ?a)) {
assert (ccx.fm.contains_key(di));
auto fcx = rec(enclosing=ccx.fm.get(di),
id=di, name=id, ccx=ccx);
auto fcx = rec(enclosing=ccx.fm.get(di), id=di, name=id, ccx=ccx);
find_pre_post_fn(fcx, f);
}
case (item_mod(?id, ?m, _, ?di)) {
find_pre_post_mod(m);
}
case (item_mod(?id, ?m, _, ?di)) { find_pre_post_mod(m); }
case (item_native_mod(?id, ?nm, _, ?di)) {
find_pre_post_native_mod(nm);
}
case (item_ty(_,_,_,_,_,_)) {
ret;
}
case (item_tag(_,_,_,_,_,_)) {
ret;
}
case (item_ty(_, _, _, _, _, _)) { ret; }
case (item_tag(_, _, _, _, _, _)) { ret; }
case (item_obj(?id, ?o, ?ps, _, ?di, ?a)) {
find_pre_post_obj(ccx, o);
}
}
}
/* Finds the pre and postcondition for each expr in <args>;
sets the precondition in a to be the result of combining
the preconditions for <args>, and the postcondition in a to
be the union of all postconditions for <args> */
fn find_pre_post_exprs(&fn_ctxt fcx, &vec[@expr] args, ann a) {
if (vec::len[@expr](args) > 0u) {
log ("find_pre_post_exprs: oper =");
log_expr(*(args.(0)));
log "find_pre_post_exprs: oper =";
log_expr(*args.(0));
}
auto enclosing = fcx.enclosing;
auto fm = fcx.ccx.fm;
auto nv = num_constraints(enclosing);
fn do_one(fn_ctxt fcx, &@expr e) -> () {
find_pre_post_expr(fcx, e);
}
auto fm = fcx.ccx.fm;
auto nv = num_constraints(enclosing);
fn do_one(fn_ctxt fcx, &@expr e) { find_pre_post_expr(fcx, e); }
auto f = bind do_one(fcx, _);
vec::map[@expr, ()](f, args);
fn get_pp(crate_ctxt ccx, &@expr e) -> pre_and_post {
ret expr_pp(ccx, e);
}
auto g = bind get_pp(fcx.ccx, _);
auto pps = vec::map[@expr, pre_and_post](g, args);
auto h = get_post;
set_pre_and_post(fcx.ccx, a, seq_preconds(fcx, pps),
union_postconds
(nv, (vec::map[pre_and_post, postcond](h, pps))));
union_postconds(nv,
vec::map[pre_and_post,
postcond](h, pps)));
}
fn find_pre_post_loop(&fn_ctxt fcx, &@local l, &@expr index,
&block body, &ann a) -> () {
fn find_pre_post_loop(&fn_ctxt fcx, &@local l, &@expr index, &block body,
&ann a) {
find_pre_post_expr(fcx, index);
find_pre_post_block(fcx, body);
auto loop_precond = declare_var(fcx, rec(id=l.node.id,
c=ninit(l.node.ident)),
seq_preconds(fcx, [expr_pp(fcx.ccx, index), block_pp(fcx.ccx, body)]));
auto loop_postcond = intersect_postconds
([expr_postcond(fcx.ccx, index), block_postcond(fcx.ccx, body)]);
auto loop_precond =
declare_var(fcx, rec(id=l.node.id, c=ninit(l.node.ident)),
seq_preconds(fcx,
[expr_pp(fcx.ccx, index),
block_pp(fcx.ccx, body)]));
auto loop_postcond =
intersect_postconds([expr_postcond(fcx.ccx, index),
block_postcond(fcx.ccx, body)]);
set_pre_and_post(fcx.ccx, a, loop_precond, loop_postcond);
}
fn gen_if_local(&fn_ctxt fcx, @expr lhs, @expr rhs,
&ann larger_ann, &ann new_var, &path pth) -> () {
alt (ann_to_def(fcx.ccx, new_var)) {
case (some(?d)) {
alt (d) {
case (def_local(?d_id)) {
find_pre_post_expr(fcx, rhs);
auto p = expr_pp(fcx.ccx, rhs);
set_pre_and_post(fcx.ccx, larger_ann,
p.precondition, p.postcondition);
gen(fcx, larger_ann, rec(id=d_id,
c=ninit(path_to_ident(fcx.ccx.tcx, pth))));
}
case (_) { find_pre_post_exprs(fcx, [lhs, rhs], larger_ann); }
}
}
case (_) { find_pre_post_exprs(fcx, [lhs, rhs], larger_ann); }
}
fn gen_if_local(&fn_ctxt fcx, @expr lhs, @expr rhs, &ann larger_ann,
&ann new_var, &path pth) {
alt (ann_to_def(fcx.ccx, new_var)) {
case (some(?d)) {
alt (d) {
case (def_local(?d_id)) {
find_pre_post_expr(fcx, rhs);
auto p = expr_pp(fcx.ccx, rhs);
set_pre_and_post(fcx.ccx, larger_ann, p.precondition,
p.postcondition);
gen(fcx, larger_ann,
rec(id=d_id,
c=ninit(path_to_ident(fcx.ccx.tcx, pth))));
}
case (_) { find_pre_post_exprs(fcx, [lhs, rhs], larger_ann); }
}
}
case (_) { find_pre_post_exprs(fcx, [lhs, rhs], larger_ann); }
}
}
/* Fills in annotations as a side effect. Does not rebuild the expr */
fn find_pre_post_expr(&fn_ctxt fcx, @expr e) -> () {
auto enclosing = fcx.enclosing;
fn find_pre_post_expr(&fn_ctxt fcx, @expr e) {
auto enclosing = fcx.enclosing;
auto num_local_vars = num_constraints(enclosing);
fn do_rand_(fn_ctxt fcx, &@expr e) -> () {
find_pre_post_expr(fcx, e);
}
log("find_pre_post_expr (num_constraints =" +
uistr(num_local_vars) + "):");
fn do_rand_(fn_ctxt fcx, &@expr e) { find_pre_post_expr(fcx, e); }
log "find_pre_post_expr (num_constraints =" + uistr(num_local_vars) +
"):";
log_expr(*e);
alt (e.node) {
case (expr_call(?operator, ?operands, ?a)) {
auto args = vec::clone[@expr](operands);
vec::push[@expr](args, operator);
find_pre_post_exprs(fcx, args, a);
/* should test higher-order constrained functions */
/* FIXME */
/* see if the call has any constraints on its in type */
log("a function: " );
log "a function: ";
log_expr(*operator);
auto pp = expr_pp(fcx.ccx, e);
for (@constr c in constraints_expr(fcx.ccx.tcx, operator)) {
auto id = ann_to_def(fcx.ccx, c.node.ann);
alt (id) {
case (some(def_fn(?d_id))) {
auto i = bit_num(fcx, rec(id=d_id,
c=substitute_constr_args(fcx.ccx.tcx,
operands, c)));
auto i =
bit_num(fcx,
rec(id=d_id,
c=substitute_constr_args(fcx.ccx.tcx,
operands,
c)));
require(i, pp);
}
case (_) {
fcx.ccx.tcx.sess.span_err(c.span, "Unbound pred "
+ " or pred that's not bound to a function");
fcx.ccx.tcx.sess.span_err(c.span,
"Unbound pred " +
" or pred that's not \
bound to a function");
}
}
}
// FIXME: constraints on result type
/* if this is a failing call, its postcondition sets everything */
alt (controlflow_expr(fcx.ccx, operator)) {
case (noreturn) {
set_postcond_false(fcx.ccx, a);
}
case (noreturn) { set_postcond_false(fcx.ccx, a); }
case (_) { }
}
}
@ -268,21 +260,20 @@ fn find_pre_post_expr(&fn_ctxt fcx, @expr e) -> () {
case (expr_path(?p, ?a)) {
auto res = expr_pp(fcx.ccx, e);
clear_pp(res);
auto df = ann_to_def_strict(fcx.ccx.tcx, a);
alt (df) {
case (def_local(?d_id)) {
auto i = bit_num(fcx, rec(id=d_id,
c=ninit(path_to_ident(fcx.ccx.tcx, p))));
auto i =
bit_num(fcx,
rec(id=d_id,
c=ninit(path_to_ident(fcx.ccx.tcx, p))));
require_and_preserve(i, res);
}
case (_) { /* nothing to check */ }
case (_) {/* nothing to check */ }
}
}
case (expr_self_method(?v, ?a)) {
clear_pp(expr_pp(fcx.ccx, e));
}
case(expr_log(_, ?arg, ?a)) {
case (expr_self_method(?v, ?a)) { clear_pp(expr_pp(fcx.ccx, e)); }
case (expr_log(_, ?arg, ?a)) {
find_pre_post_expr(fcx, arg);
copy_pre_post(fcx.ccx, a, arg);
}
@ -290,19 +281,18 @@ fn find_pre_post_expr(&fn_ctxt fcx, @expr e) -> () {
find_pre_post_expr(fcx, arg);
copy_pre_post(fcx.ccx, a, arg);
}
case(expr_put(?opt, ?a)) {
case (expr_put(?opt, ?a)) {
alt (opt) {
case (some(?arg)) {
find_pre_post_expr(fcx, arg);
copy_pre_post(fcx.ccx, a, arg);
}
case (none) {
clear_pp(expr_pp(fcx.ccx, e));
}
case (none) { clear_pp(expr_pp(fcx.ccx, e)); }
}
}
// FIXME this was just put in here as a placeholder
case (expr_fn(?f, ?a)) {
case (
// FIXME this was just put in here as a placeholder
expr_fn(?f, ?a)) {
clear_pp(expr_pp(fcx.ccx, e));
}
case (expr_block(?b, ?a)) {
@ -310,20 +300,19 @@ fn find_pre_post_expr(&fn_ctxt fcx, @expr e) -> () {
auto p = block_pp(fcx.ccx, b);
set_pre_and_post(fcx.ccx, a, p.precondition, p.postcondition);
}
case (expr_rec(?fields,?maybe_base,?a)) {
case (expr_rec(?fields, ?maybe_base, ?a)) {
auto es = field_exprs(fields);
vec::plus_option[@expr](es, maybe_base);
find_pre_post_exprs(fcx, es, a);
}
case (expr_move(?lhs, ?rhs, ?a)) {
// FIXME: this needs to deinitialize the rhs
alt (lhs.node) {
case (expr_path(?p, ?a_lhs)) {
gen_if_local(fcx, lhs, rhs, a, a_lhs, p);
}
case (_) {
find_pre_post_exprs(fcx, [lhs, rhs], a);
}
case (_) { find_pre_post_exprs(fcx, [lhs, rhs], a); }
}
}
case (expr_assign(?lhs, ?rhs, ?a)) {
@ -331,9 +320,7 @@ fn find_pre_post_expr(&fn_ctxt fcx, @expr e) -> () {
case (expr_path(?p, ?a_lhs)) {
gen_if_local(fcx, lhs, rhs, a, a_lhs, p);
}
case (_) {
find_pre_post_exprs(fcx, [lhs, rhs], a);
}
case (_) { find_pre_post_exprs(fcx, [lhs, rhs], a); }
}
}
case (expr_recv(?lhs, ?rhs, ?a)) {
@ -344,6 +331,7 @@ fn find_pre_post_expr(&fn_ctxt fcx, @expr e) -> () {
case (_) {
// doesn't check that lhs is an lval, but
// that's probably ok
find_pre_post_exprs(fcx, [lhs, rhs], a);
}
}
@ -351,11 +339,10 @@ fn find_pre_post_expr(&fn_ctxt fcx, @expr e) -> () {
case (expr_assign_op(_, ?lhs, ?rhs, ?a)) {
/* Different from expr_assign in that the lhs *must*
already be initialized */
find_pre_post_exprs(fcx, [lhs, rhs], a);
}
case (expr_lit(_,?a)) {
clear_pp(expr_pp(fcx.ccx, e));
}
case (expr_lit(_, ?a)) { clear_pp(expr_pp(fcx.ccx, e)); }
case (expr_ret(?maybe_val, ?a)) {
alt (maybe_val) {
case (none) {
@ -372,9 +359,8 @@ fn find_pre_post_expr(&fn_ctxt fcx, @expr e) -> () {
}
case (expr_be(?e, ?a)) {
find_pre_post_expr(fcx, e);
set_pre_and_post(fcx.ccx, a,
expr_prestate(fcx.ccx, e),
false_postcond(num_local_vars));
set_pre_and_post(fcx.ccx, a, expr_prestate(fcx.ccx, e),
false_postcond(num_local_vars));
}
case (expr_if(?antec, ?conseq, ?maybe_alt, ?a)) {
find_pre_post_expr(fcx, antec);
@ -382,9 +368,10 @@ fn find_pre_post_expr(&fn_ctxt fcx, @expr e) -> () {
alt (maybe_alt) {
case (none) {
log "333";
auto precond_res = seq_preconds(fcx,
[expr_pp(fcx.ccx, antec),
block_pp(fcx.ccx, conseq)]);
auto precond_res =
seq_preconds(fcx,
[expr_pp(fcx.ccx, antec),
block_pp(fcx.ccx, conseq)]);
set_pre_and_post(fcx.ccx, a, precond_res,
expr_poststate(fcx.ccx, antec));
}
@ -392,38 +379,41 @@ fn find_pre_post_expr(&fn_ctxt fcx, @expr e) -> () {
find_pre_post_expr(fcx, altern);
log "444";
auto precond_true_case =
seq_preconds(fcx, [expr_pp(fcx.ccx, antec),
block_pp(fcx.ccx, conseq)]);
auto postcond_true_case = union_postconds
(num_local_vars,
[expr_postcond(fcx.ccx, antec),
block_postcond(fcx.ccx, conseq)]);
seq_preconds(fcx,
[expr_pp(fcx.ccx, antec),
block_pp(fcx.ccx, conseq)]);
auto postcond_true_case =
union_postconds(num_local_vars,
[expr_postcond(fcx.ccx, antec),
block_postcond(fcx.ccx, conseq)]);
log "555";
auto precond_false_case = seq_preconds
(fcx, [expr_pp(fcx.ccx, antec),
expr_pp(fcx.ccx, altern)]);
auto postcond_false_case = union_postconds
(num_local_vars,
[expr_postcond(fcx.ccx, antec),
expr_postcond(fcx.ccx, altern)]);
auto precond_res = union_postconds
(num_local_vars,
[precond_true_case, precond_false_case]);
auto postcond_res = intersect_postconds
([postcond_true_case, postcond_false_case]);
auto precond_false_case =
seq_preconds(fcx,
[expr_pp(fcx.ccx, antec),
expr_pp(fcx.ccx, altern)]);
auto postcond_false_case =
union_postconds(num_local_vars,
[expr_postcond(fcx.ccx, antec),
expr_postcond(fcx.ccx, altern)]);
auto precond_res =
union_postconds(num_local_vars,
[precond_true_case,
precond_false_case]);
auto postcond_res =
intersect_postconds([postcond_true_case,
postcond_false_case]);
set_pre_and_post(fcx.ccx, a, precond_res, postcond_res);
}
}
}
case (expr_binary(?bop,?l,?r,?a)) {
case (expr_binary(?bop, ?l, ?r, ?a)) {
/* *unless* bop is lazy (e.g. and, or)?
FIXME */
find_pre_post_exprs(fcx, [l, r], a);
}
case (expr_send(?l, ?r, ?a)) {
find_pre_post_exprs(fcx, [l, r], a);
}
case (expr_unary(_,?operand,?a)) {
case (expr_send(?l, ?r, ?a)) { find_pre_post_exprs(fcx, [l, r], a); }
case (expr_unary(_, ?operand, ?a)) {
find_pre_post_expr(fcx, operand);
copy_pre_post(fcx.ccx, a, operand);
}
@ -437,26 +427,28 @@ fn find_pre_post_expr(&fn_ctxt fcx, @expr e) -> () {
log "666";
set_pre_and_post(fcx.ccx, a,
seq_preconds(fcx,
[expr_pp(fcx.ccx, test),
block_pp(fcx.ccx, body)]),
intersect_postconds([expr_postcond(fcx.ccx, test),
block_postcond(fcx.ccx, body)]));
[expr_pp(fcx.ccx, test),
block_pp(fcx.ccx, body)]),
intersect_postconds([expr_postcond(fcx.ccx,
test),
block_postcond(fcx.ccx,
body)]));
}
case (expr_do_while(?body, ?test, ?a)) {
find_pre_post_block(fcx, body);
find_pre_post_expr(fcx, test);
auto loop_postcond = union_postconds(num_local_vars,
[block_postcond(fcx.ccx, body),
expr_postcond(fcx.ccx, test)]);
auto loop_postcond =
union_postconds(num_local_vars,
[block_postcond(fcx.ccx, body),
expr_postcond(fcx.ccx, test)]);
/* conservative approximination: if the body
could break or cont, the test may never be executed */
if (has_nonlocal_exits(body)) {
loop_postcond = empty_poststate(num_local_vars);
}
set_pre_and_post(fcx.ccx, a, seq_preconds(fcx,
set_pre_and_post(fcx.ccx, a,
seq_preconds(fcx,
[block_pp(fcx.ccx, body),
expr_pp(fcx.ccx, test)]),
loop_postcond);
@ -485,14 +477,13 @@ fn find_pre_post_expr(&fn_ctxt fcx, @expr e) -> () {
intersect(pp.postcondition, next.postcondition);
ret pp;
}
auto antec_pp = pp_clone(expr_pp(fcx.ccx, ex));
auto e_pp = @rec(precondition=empty_prestate(num_local_vars),
postcondition=false_postcond(num_local_vars));
auto antec_pp = pp_clone(expr_pp(fcx.ccx, ex));
auto e_pp =
@rec(precondition=empty_prestate(num_local_vars),
postcondition=false_postcond(num_local_vars));
auto g = bind combine_pp(antec_pp, fcx, _, _);
auto alts_overall_pp = vec::foldl[pre_and_post, pre_and_post]
(g, e_pp, alt_pps);
auto alts_overall_pp =
vec::foldl[pre_and_post, pre_and_post](g, e_pp, alt_pps);
set_pre_and_post(fcx.ccx, a, alts_overall_pp.precondition,
alts_overall_pp.postcondition);
}
@ -504,8 +495,8 @@ fn find_pre_post_expr(&fn_ctxt fcx, @expr e) -> () {
set_pre_and_post(fcx.ccx, a,
/* if execution continues after fail,
then everything is true! */
empty_prestate(num_local_vars),
false_postcond(num_local_vars));
empty_prestate(num_local_vars),
false_postcond(num_local_vars));
}
case (expr_assert(?p, ?a)) {
find_pre_post_expr(fcx, p);
@ -514,26 +505,23 @@ fn find_pre_post_expr(&fn_ctxt fcx, @expr e) -> () {
case (expr_check(?p, ?a)) {
/* FIXME: Can we bypass this by having a
node-id-to-constr_occ table? */
find_pre_post_expr(fcx, p);
copy_pre_post(fcx.ccx, a, p);
/* predicate p holds after this expression executes */
let aux::constr c = expr_to_constr(fcx.ccx.tcx, p);
gen(fcx, a, c.node);
}
case(expr_bind(?operator, ?maybe_args, ?a)) {
case (expr_bind(?operator, ?maybe_args, ?a)) {
auto args = vec::cat_options[@expr](maybe_args);
vec::push[@expr](args, operator); /* ??? order of eval? */
find_pre_post_exprs(fcx, args, a);
}
case (expr_break(?a)) {
clear_pp(expr_pp(fcx.ccx, e));
}
case (expr_cont(?a)) {
clear_pp(expr_pp(fcx.ccx, e));
}
case (expr_port(?a)) {
clear_pp(expr_pp(fcx.ccx, e));
}
case (expr_break(?a)) { clear_pp(expr_pp(fcx.ccx, e)); }
case (expr_cont(?a)) { clear_pp(expr_pp(fcx.ccx, e)); }
case (expr_port(?a)) { clear_pp(expr_pp(fcx.ccx, e)); }
case (expr_ext(_, _, _, ?expanded, ?a)) {
find_pre_post_expr(fcx, expanded);
copy_pre_post(fcx.ccx, a, expanded);
@ -544,58 +532,53 @@ fn find_pre_post_expr(&fn_ctxt fcx, @expr e) -> () {
find_pre_post_expr(fcx, ex);
copy_pre_post(fcx.ccx, a, ex);
}
case (none) {
clear_pp(expr_pp(fcx.ccx, e));
}
case (none) { clear_pp(expr_pp(fcx.ccx, e)); }
}
}
}
}
fn find_pre_post_stmt(&fn_ctxt fcx, &stmt s)
-> () {
log("stmt =");
fn find_pre_post_stmt(&fn_ctxt fcx, &stmt s) {
log "stmt =";
log_stmt(s);
auto enclosing = fcx.enclosing;
auto enclosing = fcx.enclosing;
auto num_local_vars = num_constraints(enclosing);
alt(s.node) {
case(stmt_decl(?adecl, ?a)) {
alt(adecl.node) {
case(decl_local(?alocal)) {
alt(alocal.init) {
case(some(?an_init)) {
alt (s.node) {
case (stmt_decl(?adecl, ?a)) {
alt (adecl.node) {
case (decl_local(?alocal)) {
alt (alocal.init) {
case (some(?an_init)) {
find_pre_post_expr(fcx, an_init.expr);
copy_pre_post(fcx.ccx, alocal.ann, an_init.expr);
/* Inherit ann from initializer, and add var being
initialized to the postcondition */
copy_pre_post(fcx.ccx, a, an_init.expr);
gen(fcx, a, rec(id=alocal.id,
c=ninit(alocal.ident)));
gen(fcx, a,
rec(id=alocal.id, c=ninit(alocal.ident)));
}
case(none) {
case (none) {
clear_pp(ann_to_ts_ann(fcx.ccx,
alocal.ann).conditions);
clear_pp(ann_to_ts_ann(fcx.ccx, a).conditions);
}
}
}
case(decl_item(?anitem)) {
case (decl_item(?anitem)) {
clear_pp(ann_to_ts_ann(fcx.ccx, a).conditions);
find_pre_post_item(fcx.ccx, *anitem);
}
}
}
case(stmt_expr(?e,?a)) {
case (stmt_expr(?e, ?a)) {
find_pre_post_expr(fcx, e);
copy_pre_post(fcx.ccx, a, e);
}
}
}
}
fn find_pre_post_block(&fn_ctxt fcx, block b) -> () {
fn find_pre_post_block(&fn_ctxt fcx, block b) {
/* Want to say that if there is a break or cont in this
block, then that invalidates the poststate upheld by
any of the stmts after it.
@ -609,57 +592,53 @@ fn find_pre_post_block(&fn_ctxt fcx, block b) -> () {
This will mean that:
x = 0;
break;
won't have a postcondition that says x is initialized, but that's ok.
*/
auto nv = num_constraints(fcx.enclosing);
fn do_one_(fn_ctxt fcx, &@stmt s) -> () {
auto nv = num_constraints(fcx.enclosing);
fn do_one_(fn_ctxt fcx, &@stmt s) {
find_pre_post_stmt(fcx, *s);
log("pre_post for stmt:");
log "pre_post for stmt:";
log_stmt(*s);
log("is:");
log "is:";
log_pp(stmt_pp(fcx.ccx, *s));
}
auto do_one = bind do_one_(fcx, _);
vec::map[@stmt, ()](do_one, b.node.stmts);
fn do_inner_(fn_ctxt fcx, &@expr e) -> () {
find_pre_post_expr(fcx, e);
}
fn do_inner_(fn_ctxt fcx, &@expr e) { find_pre_post_expr(fcx, e); }
auto do_inner = bind do_inner_(fcx, _);
option::map[@expr, ()](do_inner, b.node.expr);
let vec[pre_and_post] pps = [];
fn get_pp_stmt(crate_ctxt ccx, &@stmt s) -> pre_and_post {
ret stmt_pp(ccx, *s);
}
auto f = bind get_pp_stmt(fcx.ccx,_);
auto f = bind get_pp_stmt(fcx.ccx, _);
pps += vec::map[@stmt, pre_and_post](f, b.node.stmts);
fn get_pp_expr(crate_ctxt ccx, &@expr e) -> pre_and_post {
ret expr_pp(ccx, e);
}
auto g = bind get_pp_expr(fcx.ccx, _);
plus_option[pre_and_post](pps,
option::map[@expr, pre_and_post](g, b.node.expr));
auto block_precond = seq_preconds(fcx, pps);
option::map[@expr,
pre_and_post](g, b.node.expr));
auto block_precond = seq_preconds(fcx, pps);
auto h = get_post;
auto postconds = vec::map[pre_and_post, postcond](h, pps);
auto postconds = vec::map[pre_and_post, postcond](h, pps);
/* A block may be empty, so this next line ensures that the postconds
vector is non-empty. */
vec::push[postcond](postconds, block_precond);
auto block_postcond = empty_poststate(nv);
/* conservative approximation */
if (! has_nonlocal_exits(b)) {
if (!has_nonlocal_exits(b)) {
block_postcond = union_postconds(nv, postconds);
}
set_pre_and_post(fcx.ccx, b.node.a, block_precond, block_postcond);
}
fn find_pre_post_fn(&fn_ctxt fcx, &_fn f) -> () {
fn find_pre_post_fn(&fn_ctxt fcx, &_fn f) {
find_pre_post_block(fcx, f.body);
// Treat the tail expression as a return statement
@ -668,18 +647,16 @@ fn find_pre_post_fn(&fn_ctxt fcx, &_fn f) -> () {
auto tailann = expr_ann(tailexpr);
set_postcond_false(fcx.ccx, tailann);
}
case (none) { /* fallthrough */ }
case (none) {/* fallthrough */ }
}
}
fn fn_pre_post(crate_ctxt ccx, &_fn f, &span sp, &ident i, &def_id id,
&ann a) -> () {
&ann a) {
assert (ccx.fm.contains_key(id));
auto fcx = rec(enclosing=ccx.fm.get(id),
id=id, name=i, ccx=ccx);
find_pre_post_fn(fcx, f);
auto fcx = rec(enclosing=ccx.fm.get(id), id=id, name=i, ccx=ccx);
find_pre_post_fn(fcx, f);
}
//
// Local Variables:
// mode: rust

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +1,4 @@
import front::ast::*;
import std::option;
import std::option::some;
@ -5,6 +6,7 @@ import std::option::none;
import util::common::span;
import util::common::respan;
// Context-passing AST walker. Each overridden visit method has full control
// over what happens with its node, it can do its own traversal of the node's
// children (potentially passing in different contexts to each), call
@ -15,42 +17,41 @@ import util::common::respan;
// circular types, so the visitor record can not hold functions that take
// visitors. A vt tag is used to break the cycle.
tag vt[E] { vtor(visitor[E]); }
fn vt[E](&vt[E] x) -> visitor[E] {
alt (x) { case (vtor(?v)) { ret v; } }
}
fn vt[E](&vt[E] x) -> visitor[E] { alt (x) { case (vtor(?v)) { ret v; } } }
type visitor[E] =
@rec(fn(&_mod m, &span sp, &E e, &vt[E] v) visit_mod,
fn(&@view_item v, &E e, &vt[E] v) visit_view_item,
fn(&@native_item i, &E e, &vt[E] v) visit_native_item,
fn(&@item i, &E e, &vt[E] v) visit_item,
fn(&@local l, &E e, &vt[E] v) visit_local,
fn(&block b, &E e, &vt[E] v) visit_block,
fn(&@stmt s, &E e, &vt[E] v) visit_stmt,
fn(&arm a, &E e, &vt[E] v) visit_arm,
fn(&@pat p, &E e, &vt[E] v) visit_pat,
fn(&@decl d, &E e, &vt[E] v) visit_decl,
fn(&@expr ex, &E e, &vt[E] v) visit_expr,
fn(&@ty t, &E e, &vt[E] v) visit_ty,
fn(&@constr c, &E e, &vt[E] v) visit_constr,
fn(&_fn f, &vec[ty_param] tp, &span sp, &ident name, &def_id d_id,
&ann a, &E e, &vt[E] v) visit_fn);
@rec(fn(&_mod, &span, &E, &vt[E]) visit_mod,
fn(&@view_item, &E, &vt[E]) visit_view_item,
fn(&@native_item, &E, &vt[E]) visit_native_item,
fn(&@item, &E, &vt[E]) visit_item,
fn(&@local, &E, &vt[E]) visit_local,
fn(&block, &E, &vt[E]) visit_block,
fn(&@stmt, &E, &vt[E]) visit_stmt,
fn(&arm, &E, &vt[E]) visit_arm,
fn(&@pat, &E, &vt[E]) visit_pat,
fn(&@decl, &E, &vt[E]) visit_decl,
fn(&@expr, &E, &vt[E]) visit_expr,
fn(&@ty, &E, &vt[E]) visit_ty,
fn(&@constr, &E, &vt[E]) visit_constr,
fn(&_fn, &vec[ty_param], &span, &ident, &def_id, &ann, &E, &vt[E])
visit_fn);
fn default_visitor[E]() -> visitor[E] {
ret @rec(visit_mod = bind visit_mod[E](_, _, _, _),
visit_view_item = bind visit_view_item[E](_, _, _),
visit_native_item = bind visit_native_item[E](_, _, _),
visit_item = bind visit_item[E](_, _, _),
visit_local = bind visit_local[E](_, _, _),
visit_block = bind visit_block[E](_, _, _),
visit_stmt = bind visit_stmt[E](_, _, _),
visit_arm = bind visit_arm[E](_, _, _),
visit_pat = bind visit_pat[E](_, _, _),
visit_decl = bind visit_decl[E](_, _, _),
visit_expr = bind visit_expr[E](_, _, _),
visit_ty = bind visit_ty[E](_, _, _),
visit_constr = bind visit_constr[E](_, _, _),
visit_fn = bind visit_fn[E](_, _, _, _, _, _, _, _));
ret @rec(visit_mod=bind visit_mod[E](_, _, _, _),
visit_view_item=bind visit_view_item[E](_, _, _),
visit_native_item=bind visit_native_item[E](_, _, _),
visit_item=bind visit_item[E](_, _, _),
visit_local=bind visit_local[E](_, _, _),
visit_block=bind visit_block[E](_, _, _),
visit_stmt=bind visit_stmt[E](_, _, _),
visit_arm=bind visit_arm[E](_, _, _),
visit_pat=bind visit_pat[E](_, _, _),
visit_decl=bind visit_decl[E](_, _, _),
visit_expr=bind visit_expr[E](_, _, _),
visit_ty=bind visit_ty[E](_, _, _),
visit_constr=bind visit_constr[E](_, _, _),
visit_fn=bind visit_fn[E](_, _, _, _, _, _, _, _));
}
fn visit_crate[E](&crate c, &E e, &vt[E] v) {
@ -65,39 +66,33 @@ fn visit_crate_directive[E](&@crate_directive cd, &E e, &vt[E] v) {
visit_crate_directive(cdir, e, v);
}
}
case (cdir_src_mod(_, _)) {}
case (cdir_src_mod(_, _)) { }
case (cdir_dir_mod(_, _, ?cdirs)) {
for (@crate_directive cdir in cdirs) {
visit_crate_directive(cdir, e, v);
}
}
case (cdir_view_item(?vi)) {
vt(v).visit_view_item(vi, e, v);
}
case (cdir_meta(_,_)) {}
case (cdir_syntax(_)) {}
case (cdir_auth(_, _)) {}
case (cdir_view_item(?vi)) { vt(v).visit_view_item(vi, e, v); }
case (cdir_meta(_, _)) { }
case (cdir_syntax(_)) { }
case (cdir_auth(_, _)) { }
}
}
fn visit_mod[E](&_mod m, &span sp, &E e, &vt[E] v) {
for (@view_item vi in m.view_items) {
vt(v).visit_view_item(vi, e, v);
}
for (@item i in m.items) {
vt(v).visit_item(i, e, v);
}
for (@view_item vi in m.view_items) { vt(v).visit_view_item(vi, e, v); }
for (@item i in m.items) { vt(v).visit_item(i, e, v); }
}
fn visit_view_item[E](&@view_item vi, &E e, &vt[E] v) {}
fn visit_view_item[E](&@view_item vi, &E e, &vt[E] v) { }
fn visit_local[E](&@local loc, &E e, &vt[E] v) {
alt (loc.node.ty) {
case (none) {}
case (none) { }
case (some(?t)) { vt(v).visit_ty(t, e, v); }
}
alt (loc.node.init) {
case (none) {}
case (none) { }
case (some(?i)) { vt(v).visit_expr(i.expr, e, v); }
}
}
@ -111,9 +106,7 @@ fn visit_item[E](&@item i, &E e, &vt[E] v) {
case (item_fn(?nm, ?f, ?tp, _, ?d, ?a)) {
vt(v).visit_fn(f, tp, i.span, nm, d, a, e, v);
}
case (item_mod(_, ?m, _, _)) {
vt(v).visit_mod(m, i.span, e, v);
}
case (item_mod(_, ?m, _, _)) { vt(v).visit_mod(m, i.span, e, v); }
case (item_native_mod(_, ?nm, _, _)) {
for (@view_item vi in nm.view_items) {
vt(v).visit_view_item(vi, e, v);
@ -122,9 +115,7 @@ fn visit_item[E](&@item i, &E e, &vt[E] v) {
vt(v).visit_native_item(ni, e, v);
}
}
case (item_ty(_, ?t, _, _, _, _)) {
vt(v).visit_ty(t, e, v);
}
case (item_ty(_, ?t, _, _, _, _)) { vt(v).visit_ty(t, e, v); }
case (item_tag(_, ?variants, _, _, _, _)) {
for (variant vr in variants) {
for (variant_arg va in vr.node.args) {
@ -133,22 +124,19 @@ fn visit_item[E](&@item i, &E e, &vt[E] v) {
}
}
case (item_obj(_, ?ob, _, _, _, _)) {
for (obj_field f in ob.fields) {
vt(v).visit_ty(f.ty, e, v);
}
for (obj_field f in ob.fields) { vt(v).visit_ty(f.ty, e, v); }
for (@method m in ob.methods) {
vt(v).visit_fn(m.node.meth, [], m.span, m.node.ident,
m.node.id, m.node.ann, e, v);
}
alt (ob.dtor) {
case (none) {}
case (none) { }
case (some(?m)) {
vt(v).visit_fn(m.node.meth, [], m.span, m.node.ident,
m.node.id, m.node.ann, e, v);
}
}
}
}
}
@ -160,22 +148,14 @@ fn visit_ty[E](&@ty t, &E e, &vt[E] v) {
case (ty_port(?t)) { vt(v).visit_ty(t, e, v); }
case (ty_chan(?t)) { vt(v).visit_ty(t, e, v); }
case (ty_tup(?mts)) {
for (mt mt in mts) {
vt(v).visit_ty(mt.ty, e, v);
}
for (mt mt in mts) { vt(v).visit_ty(mt.ty, e, v); }
}
case (ty_rec(?flds)) {
for (ty_field f in flds) {
vt(v).visit_ty(f.node.mt.ty, e, v);
}
for (ty_field f in flds) { vt(v).visit_ty(f.node.mt.ty, e, v); }
}
case (ty_fn(_, ?args, ?out, _, ?constrs)) {
for (ty_arg a in args) {
vt(v).visit_ty(a.node.ty, e, v);
}
for (@constr c in constrs) {
vt(v).visit_constr(c, e, v);
}
for (ty_arg a in args) { vt(v).visit_ty(a.node.ty, e, v); }
for (@constr c in constrs) { vt(v).visit_constr(c, e, v); }
vt(v).visit_ty(out, e, v);
}
case (ty_obj(?tmeths)) {
@ -187,17 +167,16 @@ fn visit_ty[E](&@ty t, &E e, &vt[E] v) {
}
}
case (ty_path(?p, _)) {
for (@ty tp in p.node.types) {
vt(v).visit_ty(tp, e, v);
}
for (@ty tp in p.node.types) { vt(v).visit_ty(tp, e, v); }
}
case (ty_constr(?t, _)) { vt(v).visit_ty(t, e, v); }
case (_) {}
case (_) { }
}
}
fn visit_constr[E](&@constr c, &E e, &vt[E] v) {
// default
}
fn visit_pat[E](&@pat p, &E e, &vt[E] v) {
@ -206,26 +185,20 @@ fn visit_pat[E](&@pat p, &E e, &vt[E] v) {
for (@ty tp in path.node.types) { vt(v).visit_ty(tp, e, v); }
for (@pat child in children) { vt(v).visit_pat(child, e, v); }
}
case (_) {}
case (_) { }
}
}
fn visit_native_item[E](&@native_item ni, &E e, &vt[E] v) {
alt (ni.node) {
case (native_item_fn(_, _, ?fd, _, _, _)) {
visit_fn_decl(fd, e, v);
}
case (native_item_ty(_, _)) {}
case (native_item_fn(_, _, ?fd, _, _, _)) { visit_fn_decl(fd, e, v); }
case (native_item_ty(_, _)) { }
}
}
fn visit_fn_decl[E](&fn_decl fd, &E e, &vt[E] v) {
for (arg a in fd.inputs) {
vt(v).visit_ty(a.ty, e, v);
}
for (@constr c in fd.constraints) {
vt(v).visit_constr(c, e, v);
}
for (arg a in fd.inputs) { vt(v).visit_ty(a.ty, e, v); }
for (@constr c in fd.constraints) { vt(v).visit_constr(c, e, v); }
vt(v).visit_ty(fd.output, e, v);
}
@ -259,9 +232,8 @@ fn visit_decl[E](&@decl d, &E e, &vt[E] v) {
fn visit_expr_opt[E](option::t[@expr] eo, &E e, &vt[E] v) {
alt (eo) {
case (none) {}
case (some(?ex)) { vt(v).visit_expr(ex, e, v);
}
case (none) { }
case (some(?ex)) { vt(v).visit_expr(ex, e, v); }
}
}
@ -271,9 +243,7 @@ fn visit_exprs[E](vec[@expr] exprs, &E e, &vt[E] v) {
fn visit_expr[E](&@expr ex, &E e, &vt[E] v) {
alt (ex.node) {
case (expr_vec(?es, _, _, _)) {
visit_exprs(es, e, v);
}
case (expr_vec(?es, _, _, _)) { visit_exprs(es, e, v); }
case (expr_tup(?elts, _)) {
for (elt el in elts) { vt(v).visit_expr(el.expr, e, v); }
}
@ -298,9 +268,7 @@ fn visit_expr[E](&@expr ex, &E e, &vt[E] v) {
vt(v).visit_expr(a, e, v);
vt(v).visit_expr(b, e, v);
}
case (expr_unary(_, ?a, _)) {
vt(v).visit_expr(a, e, v);
}
case (expr_unary(_, ?a, _)) { vt(v).visit_expr(a, e, v); }
case (expr_lit(_, _)) { }
case (expr_cast(?x, ?t, _)) {
vt(v).visit_expr(x, e, v);
@ -331,17 +299,13 @@ fn visit_expr[E](&@expr ex, &E e, &vt[E] v) {
}
case (expr_alt(?x, ?arms, _)) {
vt(v).visit_expr(x, e, v);
for (arm a in arms) {
vt(v).visit_arm(a, e, v);
}
for (arm a in arms) { vt(v).visit_arm(a, e, v); }
}
case (expr_fn(?f, _)) {
visit_fn_decl(f.decl, e, v);
vt(v).visit_block(f.body, e, v);
}
case (expr_block(?b, _)) {
vt(v).visit_block(b, e, v);
}
case (expr_block(?b, _)) { vt(v).visit_block(b, e, v); }
case (expr_assign(?a, ?b, _)) {
vt(v).visit_expr(b, e, v);
vt(v).visit_expr(a, e, v);
@ -362,17 +326,13 @@ fn visit_expr[E](&@expr ex, &E e, &vt[E] v) {
vt(v).visit_expr(a, e, v);
vt(v).visit_expr(b, e, v);
}
case (expr_field(?x, _, _)) {
vt(v).visit_expr(x, e, v);
}
case (expr_field(?x, _, _)) { vt(v).visit_expr(x, e, v); }
case (expr_index(?a, ?b, _)) {
vt(v).visit_expr(a, e, v);
vt(v).visit_expr(b, e, v);
}
case (expr_path(?p, _)) {
for (@ty tp in p.node.types) {
vt(v).visit_ty(tp, e, v);
}
for (@ty tp in p.node.types) { vt(v).visit_ty(tp, e, v); }
}
case (expr_ext(_, _, _, ?expansion, _)) {
vt(v).visit_expr(expansion, e, v);
@ -380,30 +340,15 @@ fn visit_expr[E](&@expr ex, &E e, &vt[E] v) {
case (expr_fail(_, _)) { }
case (expr_break(_)) { }
case (expr_cont(_)) { }
case (expr_ret(?eo, _)) {
visit_expr_opt(eo, e, v);
}
case (expr_put(?eo, _)) {
visit_expr_opt(eo, e, v);
}
case (expr_be(?x, _)) {
vt(v).visit_expr(x, e, v);
}
case (expr_log(_,?x, _)) {
vt(v).visit_expr(x, e, v);
}
case (expr_check(?x, _)) {
vt(v).visit_expr(x, e, v);
}
case (expr_assert(?x, _)) {
vt(v).visit_expr(x, e, v);
}
case (expr_ret(?eo, _)) { visit_expr_opt(eo, e, v); }
case (expr_put(?eo, _)) { visit_expr_opt(eo, e, v); }
case (expr_be(?x, _)) { vt(v).visit_expr(x, e, v); }
case (expr_log(_, ?x, _)) { vt(v).visit_expr(x, e, v); }
case (expr_check(?x, _)) { vt(v).visit_expr(x, e, v); }
case (expr_assert(?x, _)) { vt(v).visit_expr(x, e, v); }
case (expr_port(_)) { }
case (expr_chan(?x, _)) {
vt(v).visit_expr(x, e, v);
}
case (expr_anon_obj(?anon_obj,_,_,_)) {
case (expr_chan(?x, _)) { vt(v).visit_expr(x, e, v); }
case (expr_anon_obj(?anon_obj, _, _, _)) {
alt (anon_obj.fields) {
case (none) { }
case (some(?fields)) {
@ -414,12 +359,10 @@ fn visit_expr[E](&@expr ex, &E e, &vt[E] v) {
}
alt (anon_obj.with_obj) {
case (none) { }
case (some(?ex)) {
vt(v).visit_expr(ex, e, v);
}
case (some(?ex)) { vt(v).visit_expr(ex, e, v); }
}
for (@method m in anon_obj.methods) {
vt(v).visit_fn(m.node.meth, [], m.span, m.node.ident,
vt(v).visit_fn(m.node.meth, [], m.span, m.node.ident,
m.node.id, m.node.ann, e, v);
}
}
@ -430,7 +373,6 @@ fn visit_arm[E](&arm a, &E e, &vt[E] v) {
vt(v).visit_pat(a.pat, e, v);
vt(v).visit_block(a.block, e, v);
}
// Local Variables:
// mode: rust
// fill-column: 78;

View File

@ -1,49 +1,49 @@
import front::ast;
import front::ast;
import std::option;
import std::option::some;
import std::option::none;
import util::common::span;
import util::common::respan;
// FIXME: Should visit patterns as well.
type ast_visitor =
rec(fn () -> bool keep_going,
fn () -> bool want_crate_directives,
fn (&ast::crate c) visit_crate_pre,
fn (&ast::crate c) visit_crate_post,
fn (&@ast::crate_directive cd) visit_crate_directive_pre,
fn (&@ast::crate_directive cd) visit_crate_directive_post,
fn (&@ast::view_item i) visit_view_item_pre,
fn (&@ast::view_item i) visit_view_item_post,
fn (&@ast::native_item i) visit_native_item_pre,
fn (&@ast::native_item i) visit_native_item_post,
fn (&@ast::item i) visit_item_pre,
fn (&@ast::item i) visit_item_post,
fn (&@ast::method m) visit_method_pre,
fn (&@ast::method m) visit_method_post,
fn (&ast::block b) visit_block_pre,
fn (&ast::block b) visit_block_post,
fn (&@ast::stmt s) visit_stmt_pre,
fn (&@ast::stmt s) visit_stmt_post,
fn (&ast::arm a) visit_arm_pre,
fn (&ast::arm a) visit_arm_post,
fn (&@ast::pat p) visit_pat_pre,
fn (&@ast::pat p) visit_pat_post,
fn (&@ast::decl d) visit_decl_pre,
fn (&@ast::decl d) visit_decl_post,
fn (&@ast::local l) visit_local_pre,
fn (&@ast::local l) visit_local_post,
fn (&@ast::expr e) visit_expr_pre,
fn (&@ast::expr e) visit_expr_post,
fn (&@ast::ty t) visit_ty_pre,
fn (&@ast::ty t) visit_ty_post,
fn (&@ast::constr c) visit_constr,
fn (&ast::_fn f, &span sp, &ast::ident name,
&ast::def_id d_id, &ast::ann a) visit_fn_pre,
fn (&ast::_fn f, &span sp, &ast::ident name,
&ast::def_id d_id, &ast::ann a) visit_fn_post);
rec(fn() -> bool keep_going,
fn() -> bool want_crate_directives,
fn(&ast::crate) visit_crate_pre,
fn(&ast::crate) visit_crate_post,
fn(&@ast::crate_directive) visit_crate_directive_pre,
fn(&@ast::crate_directive) visit_crate_directive_post,
fn(&@ast::view_item) visit_view_item_pre,
fn(&@ast::view_item) visit_view_item_post,
fn(&@ast::native_item) visit_native_item_pre,
fn(&@ast::native_item) visit_native_item_post,
fn(&@ast::item) visit_item_pre,
fn(&@ast::item) visit_item_post,
fn(&@ast::method) visit_method_pre,
fn(&@ast::method) visit_method_post,
fn(&ast::block) visit_block_pre,
fn(&ast::block) visit_block_post,
fn(&@ast::stmt) visit_stmt_pre,
fn(&@ast::stmt) visit_stmt_post,
fn(&ast::arm) visit_arm_pre,
fn(&ast::arm) visit_arm_post,
fn(&@ast::pat) visit_pat_pre,
fn(&@ast::pat) visit_pat_post,
fn(&@ast::decl) visit_decl_pre,
fn(&@ast::decl) visit_decl_post,
fn(&@ast::local) visit_local_pre,
fn(&@ast::local) visit_local_post,
fn(&@ast::expr) visit_expr_pre,
fn(&@ast::expr) visit_expr_post,
fn(&@ast::ty) visit_ty_pre,
fn(&@ast::ty) visit_ty_post,
fn(&@ast::constr) visit_constr,
fn(&ast::_fn, &span, &ast::ident, &ast::def_id, &ast::ann)
visit_fn_pre,
fn(&ast::_fn, &span, &ast::ident, &ast::def_id, &ast::ann)
visit_fn_post);
fn walk_crate(&ast_visitor v, &ast::crate c) {
if (!v.keep_going()) { ret; }
@ -63,30 +63,24 @@ fn walk_crate_directive(&ast_visitor v, @ast::crate_directive cd) {
walk_crate_directive(v, cdir);
}
}
case (ast::cdir_src_mod(_, _)) {}
case (ast::cdir_src_mod(_, _)) { }
case (ast::cdir_dir_mod(_, _, ?cdirs)) {
for (@ast::crate_directive cdir in cdirs) {
walk_crate_directive(v, cdir);
}
}
case (ast::cdir_view_item(?vi)) {
walk_view_item(v, vi);
}
case (ast::cdir_meta(_,_)) {}
case (ast::cdir_syntax(_)) {}
case (ast::cdir_auth(_, _)) {}
case (ast::cdir_view_item(?vi)) { walk_view_item(v, vi); }
case (ast::cdir_meta(_, _)) { }
case (ast::cdir_syntax(_)) { }
case (ast::cdir_auth(_, _)) { }
}
v.visit_crate_directive_post(cd);
}
fn walk_mod(&ast_visitor v, &ast::_mod m) {
if (!v.keep_going()) { ret; }
for (@ast::view_item vi in m.view_items) {
walk_view_item(v, vi);
}
for (@ast::item i in m.items) {
walk_item(v, i);
}
for (@ast::view_item vi in m.view_items) { walk_view_item(v, vi); }
for (@ast::item i in m.items) { walk_item(v, i); }
}
fn walk_view_item(&ast_visitor v, @ast::view_item vi) {
@ -97,15 +91,10 @@ fn walk_view_item(&ast_visitor v, @ast::view_item vi) {
fn walk_local(&ast_visitor v, @ast::local loc) {
v.visit_local_pre(loc);
alt (loc.node.ty) {
case (none) {}
case (some(?t)) { walk_ty(v, t); }
}
alt (loc.node.ty) { case (none) { } case (some(?t)) { walk_ty(v, t); } }
alt (loc.node.init) {
case (none) {}
case (some(?i)) {
walk_expr(v, i.expr);
}
case (none) { }
case (some(?i)) { walk_expr(v, i.expr); }
}
v.visit_local_post(loc);
}
@ -121,15 +110,9 @@ fn walk_item(&ast_visitor v, @ast::item i) {
case (ast::item_fn(?nm, ?f, _, _, ?d, ?a)) {
walk_fn(v, f, i.span, nm, d, a);
}
case (ast::item_mod(_, ?m, _, _)) {
walk_mod(v, m);
}
case (ast::item_native_mod(_, ?nm, _, _)) {
walk_native_mod(v, nm);
}
case (ast::item_ty(_, ?t, _, _, _, _)) {
walk_ty(v, t);
}
case (ast::item_mod(_, ?m, _, _)) { walk_mod(v, m); }
case (ast::item_native_mod(_, ?nm, _, _)) { walk_native_mod(v, nm); }
case (ast::item_ty(_, ?t, _, _, _, _)) { walk_ty(v, t); }
case (ast::item_tag(_, ?variants, _, _, _, _)) {
for (ast::variant vr in variants) {
for (ast::variant_arg va in vr.node.args) {
@ -138,24 +121,21 @@ fn walk_item(&ast_visitor v, @ast::item i) {
}
}
case (ast::item_obj(_, ?ob, _, _, _, _)) {
for (ast::obj_field f in ob.fields) {
walk_ty(v, f.ty);
}
for (ast::obj_field f in ob.fields) { walk_ty(v, f.ty); }
for (@ast::method m in ob.methods) {
v.visit_method_pre(m);
walk_fn(v, m.node.meth, m.span,
m.node.ident, m.node.id, m.node.ann);
walk_fn(v, m.node.meth, m.span, m.node.ident, m.node.id,
m.node.ann);
v.visit_method_post(m);
}
alt (ob.dtor) {
case (none) {}
case (none) { }
case (some(?m)) {
walk_fn(v, m.node.meth, m.span, m.node.ident, m.node.id,
m.node.ann);
}
}
}
}
v.visit_item_post(i);
}
@ -164,40 +144,32 @@ fn walk_ty(&ast_visitor v, @ast::ty t) {
if (!v.keep_going()) { ret; }
v.visit_ty_pre(t);
alt (t.node) {
case (ast::ty_nil) {}
case (ast::ty_bot) {}
case (ast::ty_bool) {}
case (ast::ty_int) {}
case (ast::ty_uint) {}
case (ast::ty_float) {}
case (ast::ty_machine(_)) {}
case (ast::ty_char) {}
case (ast::ty_str) {}
case (ast::ty_istr) {}
case (ast::ty_nil) { }
case (ast::ty_bot) { }
case (ast::ty_bool) { }
case (ast::ty_int) { }
case (ast::ty_uint) { }
case (ast::ty_float) { }
case (ast::ty_machine(_)) { }
case (ast::ty_char) { }
case (ast::ty_str) { }
case (ast::ty_istr) { }
case (ast::ty_box(?mt)) { walk_ty(v, mt.ty); }
case (ast::ty_vec(?mt)) { walk_ty(v, mt.ty); }
case (ast::ty_ivec(?mt)) { walk_ty(v, mt.ty); }
case (ast::ty_ptr(?mt)) { walk_ty(v, mt.ty); }
case (ast::ty_task) {}
case (ast::ty_task) { }
case (ast::ty_port(?t)) { walk_ty(v, t); }
case (ast::ty_chan(?t)) { walk_ty(v, t); }
case (ast::ty_tup(?mts)) {
for (ast::mt mt in mts) {
walk_ty(v, mt.ty);
}
for (ast::mt mt in mts) { walk_ty(v, mt.ty); }
}
case (ast::ty_rec(?flds)) {
for (ast::ty_field f in flds) {
walk_ty(v, f.node.mt.ty);
}
for (ast::ty_field f in flds) { walk_ty(v, f.node.mt.ty); }
}
case (ast::ty_fn(_, ?args, ?out, _, ?constrs)) {
for (ast::ty_arg a in args) {
walk_ty(v, a.node.ty);
}
for (@ast::constr c in constrs) {
v.visit_constr(c);
}
for (ast::ty_arg a in args) { walk_ty(v, a.node.ty); }
for (@ast::constr c in constrs) { v.visit_constr(c); }
walk_ty(v, out);
}
case (ast::ty_obj(?tmeths)) {
@ -209,11 +181,9 @@ fn walk_ty(&ast_visitor v, @ast::ty t) {
}
}
case (ast::ty_path(?p, _)) {
for (@ast::ty tp in p.node.types) {
walk_ty(v, tp);
}
for (@ast::ty tp in p.node.types) { walk_ty(v, tp); }
}
case (ast::ty_type) {}
case (ast::ty_type) { }
case (ast::ty_constr(?t, _)) { walk_ty(v, t); }
}
v.visit_ty_post(t);
@ -223,26 +193,18 @@ fn walk_pat(&ast_visitor v, &@ast::pat p) {
v.visit_pat_pre(p);
alt (p.node) {
case (ast::pat_tag(?path, ?children, _)) {
for (@ast::ty tp in path.node.types) {
walk_ty(v, tp);
}
for (@ast::pat child in children) {
walk_pat(v, child);
}
for (@ast::ty tp in path.node.types) { walk_ty(v, tp); }
for (@ast::pat child in children) { walk_pat(v, child); }
}
case (_) {}
case (_) { }
}
v.visit_pat_post(p);
}
fn walk_native_mod(&ast_visitor v, &ast::native_mod nm) {
if (!v.keep_going()) { ret; }
for (@ast::view_item vi in nm.view_items) {
walk_view_item(v, vi);
}
for (@ast::native_item ni in nm.items) {
walk_native_item(v, ni);
}
for (@ast::view_item vi in nm.view_items) { walk_view_item(v, vi); }
for (@ast::native_item ni in nm.items) { walk_native_item(v, ni); }
}
fn walk_native_item(&ast_visitor v, @ast::native_item ni) {
@ -252,19 +214,14 @@ fn walk_native_item(&ast_visitor v, @ast::native_item ni) {
case (ast::native_item_fn(_, _, ?fd, _, _, _)) {
walk_fn_decl(v, fd);
}
case (ast::native_item_ty(_, _)) {
}
case (ast::native_item_ty(_, _)) { }
}
v.visit_native_item_post(ni);
}
fn walk_fn_decl(&ast_visitor v, &ast::fn_decl fd) {
for (ast::arg a in fd.inputs) {
walk_ty(v, a.ty);
}
for (@ast::constr c in fd.constraints) {
v.visit_constr(c);
}
for (ast::arg a in fd.inputs) { walk_ty(v, a.ty); }
for (@ast::constr c in fd.constraints) { v.visit_constr(c); }
walk_ty(v, fd.output);
}
@ -280,9 +237,7 @@ fn walk_fn(&ast_visitor v, &ast::_fn f, &span sp, &ast::ident i,
fn walk_block(&ast_visitor v, &ast::block b) {
if (!v.keep_going()) { ret; }
v.visit_block_pre(b);
for (@ast::stmt s in b.node.stmts) {
walk_stmt(v, s);
}
for (@ast::stmt s in b.node.stmts) { walk_stmt(v, s); }
walk_expr_opt(v, b.node.expr);
v.visit_block_post(b);
}
@ -291,12 +246,8 @@ fn walk_stmt(&ast_visitor v, @ast::stmt s) {
if (!v.keep_going()) { ret; }
v.visit_stmt_pre(s);
alt (s.node) {
case (ast::stmt_decl(?d, _)) {
walk_decl(v, d);
}
case (ast::stmt_expr(?e, _)) {
walk_expr(v, e);
}
case (ast::stmt_decl(?d, _)) { walk_decl(v, d); }
case (ast::stmt_expr(?e, _)) { walk_expr(v, e); }
case (ast::stmt_crate_directive(?cdir)) {
walk_crate_directive(v, cdir);
}
@ -308,47 +259,30 @@ fn walk_decl(&ast_visitor v, @ast::decl d) {
if (!v.keep_going()) { ret; }
v.visit_decl_pre(d);
alt (d.node) {
case (ast::decl_local(?loc)) {
walk_local(v, @respan(d.span, loc));
}
case (ast::decl_item(?it)) {
walk_item(v, it);
}
case (ast::decl_local(?loc)) { walk_local(v, @respan(d.span, loc)); }
case (ast::decl_item(?it)) { walk_item(v, it); }
}
v.visit_decl_post(d);
}
fn walk_expr_opt(&ast_visitor v, option::t[@ast::expr] eo) {
alt (eo) {
case (none) {}
case (some(?e)) {
walk_expr(v, e);
}
}
alt (eo) { case (none) { } case (some(?e)) { walk_expr(v, e); } }
}
fn walk_exprs(&ast_visitor v, vec[@ast::expr] exprs) {
for (@ast::expr e in exprs) {
walk_expr(v, e);
}
for (@ast::expr e in exprs) { walk_expr(v, e); }
}
fn walk_expr(&ast_visitor v, @ast::expr e) {
if (!v.keep_going()) { ret; }
v.visit_expr_pre(e);
alt (e.node) {
case (ast::expr_vec(?es, _, _, _)) {
walk_exprs(v, es);
}
case (ast::expr_vec(?es, _, _, _)) { walk_exprs(v, es); }
case (ast::expr_tup(?elts, _)) {
for (ast::elt e in elts) {
walk_expr(v, e.expr);
}
for (ast::elt e in elts) { walk_expr(v, e.expr); }
}
case (ast::expr_rec(?flds, ?base, _)) {
for (ast::field f in flds) {
walk_expr(v, f.node.expr);
}
for (ast::field f in flds) { walk_expr(v, f.node.expr); }
walk_expr_opt(v, base);
}
case (ast::expr_call(?callee, ?args, _)) {
@ -358,9 +292,7 @@ fn walk_expr(&ast_visitor v, @ast::expr e) {
case (ast::expr_self_method(_, _)) { }
case (ast::expr_bind(?callee, ?args, _)) {
walk_expr(v, callee);
for (option::t[@ast::expr] eo in args) {
walk_expr_opt(v, eo);
}
for (option::t[@ast::expr] eo in args) { walk_expr_opt(v, eo); }
}
case (ast::expr_spawn(_, _, ?callee, ?args, _)) {
walk_expr(v, callee);
@ -370,14 +302,9 @@ fn walk_expr(&ast_visitor v, @ast::expr e) {
walk_expr(v, a);
walk_expr(v, b);
}
case (ast::expr_unary(_, ?a, _)) {
walk_expr(v, a);
}
case (ast::expr_unary(_, ?a, _)) { walk_expr(v, a); }
case (ast::expr_lit(_, _)) { }
case (ast::expr_cast(?x, ?t, _)) {
walk_expr(v, x);
walk_ty(v, t);
}
case (ast::expr_cast(?x, ?t, _)) { walk_expr(v, x); walk_ty(v, t); }
case (ast::expr_if(?x, ?b, ?eo, _)) {
walk_expr(v, x);
walk_block(v, b);
@ -414,102 +341,67 @@ fn walk_expr(&ast_visitor v, @ast::expr e) {
walk_fn_decl(v, f.decl);
walk_block(v, f.body);
}
case (ast::expr_block(?b, _)) {
walk_block(v, b);
}
case (ast::expr_block(?b, _)) { walk_block(v, b); }
case (ast::expr_assign(?a, ?b, _)) {
walk_expr(v, a);
walk_expr(v, b);
}
case (ast::expr_move(?a, ?b, _)) {
walk_expr(v, a);
walk_expr(v, b);
}
case (ast::expr_move(?a, ?b, _)) { walk_expr(v, a); walk_expr(v, b); }
case (ast::expr_assign_op(_, ?a, ?b, _)) {
walk_expr(v, a);
walk_expr(v, b);
}
case (ast::expr_send(?a, ?b, _)) {
walk_expr(v, a);
walk_expr(v, b);
}
case (ast::expr_recv(?a, ?b, _)) {
walk_expr(v, a);
walk_expr(v, b);
}
case (ast::expr_field(?x, _, _)) {
walk_expr(v, x);
}
case (ast::expr_send(?a, ?b, _)) { walk_expr(v, a); walk_expr(v, b); }
case (ast::expr_recv(?a, ?b, _)) { walk_expr(v, a); walk_expr(v, b); }
case (ast::expr_field(?x, _, _)) { walk_expr(v, x); }
case (ast::expr_index(?a, ?b, _)) {
walk_expr(v, a);
walk_expr(v, b);
}
case (ast::expr_path(?p, _)) {
for (@ast::ty tp in p.node.types) {
walk_ty(v, tp);
}
for (@ast::ty tp in p.node.types) { walk_ty(v, tp); }
}
case (ast::expr_ext(_, ?args, ?body, ?expansion, _)) {
// Only walk expansion, not args/body.
walk_expr(v, expansion);
}
case (ast::expr_fail(_, _)) { }
case (ast::expr_break(_)) { }
case (ast::expr_cont(_)) { }
case (ast::expr_ret(?eo, _)) {
walk_expr_opt(v, eo);
}
case (ast::expr_put(?eo, _)) {
walk_expr_opt(v, eo);
}
case (ast::expr_be(?x, _)) {
walk_expr(v, x);
}
case (ast::expr_log(_,?x, _)) {
walk_expr(v, x);
}
case (ast::expr_check(?x, _)) {
walk_expr(v, x);
}
case (ast::expr_assert(?x, _)) {
walk_expr(v, x);
}
case (ast::expr_ret(?eo, _)) { walk_expr_opt(v, eo); }
case (ast::expr_put(?eo, _)) { walk_expr_opt(v, eo); }
case (ast::expr_be(?x, _)) { walk_expr(v, x); }
case (ast::expr_log(_, ?x, _)) { walk_expr(v, x); }
case (ast::expr_check(?x, _)) { walk_expr(v, x); }
case (ast::expr_assert(?x, _)) { walk_expr(v, x); }
case (ast::expr_port(_)) { }
case (ast::expr_chan(?x, _)) {
walk_expr(v, x);
}
case (ast::expr_anon_obj(?anon_obj,_,_,_)) {
case (ast::expr_chan(?x, _)) { walk_expr(v, x); }
case (ast::expr_anon_obj(?anon_obj, _, _, _)) {
// Fields
let option::t[vec[ast::obj_field]] fields
= none[vec[ast::obj_field]];
let option::t[vec[ast::obj_field]] fields =
none[vec[ast::obj_field]];
alt (anon_obj.fields) {
case (none) { }
case (some(?fields)) {
for (ast::obj_field f in fields) {
walk_ty(v, f.ty);
}
for (ast::obj_field f in fields) { walk_ty(v, f.ty); }
}
}
// with_obj
let option::t[@ast::expr] with_obj = none[@ast::expr];
alt (anon_obj.with_obj) {
case (none) { }
case (some(?e)) {
walk_expr(v, e);
}
case (some(?e)) { walk_expr(v, e); }
}
// Methods
for (@ast::method m in anon_obj.methods) {
v.visit_method_pre(m);
walk_fn(v, m.node.meth, m.span, m.node.ident,
m.node.id, m.node.ann);
walk_fn(v, m.node.meth, m.span, m.node.ident, m.node.id,
m.node.ann);
v.visit_method_post(m);
}
}
}
@ -517,24 +409,42 @@ fn walk_expr(&ast_visitor v, @ast::expr e) {
}
fn def_keep_going() -> bool { ret true; }
fn def_want_crate_directives() -> bool { ret false; }
fn def_visit_crate(&ast::crate c) { }
fn def_visit_crate_directive(&@ast::crate_directive c) { }
fn def_visit_view_item(&@ast::view_item vi) { }
fn def_visit_native_item(&@ast::native_item ni) { }
fn def_visit_item(&@ast::item i) { }
fn def_visit_method(&@ast::method m) { }
fn def_visit_block(&ast::block b) { }
fn def_visit_stmt(&@ast::stmt s) { }
fn def_visit_arm(&ast::arm a) { }
fn def_visit_pat(&@ast::pat p) { }
fn def_visit_decl(&@ast::decl d) { }
fn def_visit_local(&@ast::local l) { }
fn def_visit_expr(&@ast::expr e) { }
fn def_visit_ty(&@ast::ty t) { }
fn def_visit_constr(&@ast::constr c) { }
fn def_visit_fn(&ast::_fn f, &span sp, &ast::ident i, &ast::def_id d,
&ast::ann a) { }
&ast::ann a) {
}
fn default_visitor() -> ast_visitor {
ret rec(keep_going=def_keep_going,
@ -571,7 +481,6 @@ fn default_visitor() -> ast_visitor {
visit_fn_pre=def_visit_fn,
visit_fn_post=def_visit_fn);
}
//
// Local Variables:
// mode: rust

View File

@ -1,7 +1,9 @@
import std::io;
import std::vec;
import std::str;
/*
* This pretty-printer is a direct reimplementation of Philip Karlton's
* Mesa pretty-printer, as described in appendix A of
@ -54,19 +56,13 @@ import std::str;
* line (which it can't) and so naturally place the content on its own line to
* avoid combining it with other lines and making matters even worse.
*/
tag breaks { consistent; inconsistent; }
type break_t = rec(int offset, int blank_space);
type begin_t = rec(int offset, breaks breaks);
tag token {
STRING(str,int);
BREAK(break_t);
BEGIN(begin_t);
END;
EOF;
}
tag token { STRING(str, int); BREAK(break_t); BEGIN(begin_t); END; EOF; }
fn tok_str(token t) -> str {
alt (t) {
@ -78,18 +74,16 @@ fn tok_str(token t) -> str {
}
}
fn buf_str(vec[mutable token] toks, vec[mutable int] szs,
uint left, uint right, uint lim) -> str {
fn buf_str(vec[mutable token] toks, vec[mutable int] szs, uint left,
uint right, uint lim) -> str {
auto n = vec::len(toks);
assert n == vec::len(szs);
assert (n == vec::len(szs));
auto i = left;
auto L = lim;
auto s = "[";
while (i != right && L != 0u) {
L -= 1u;
if (i != left) {
s += ", ";
}
if (i != left) { s += ", "; }
s += #fmt("%d=%s", szs.(i), tok_str(toks.(i)));
i += 1u;
i %= n;
@ -98,43 +92,35 @@ fn buf_str(vec[mutable token] toks, vec[mutable int] szs,
ret s;
}
tag print_stack_break { fits; broken(breaks); }
type print_stack_elt = rec(int offset, print_stack_break pbreak);
const int size_infinity = 0xffff;
fn mk_printer(io::writer out, uint linewidth) -> printer {
// Yes 3, it makes the ring buffers big enough to never
// fall behind.
let uint n = 3u * linewidth;
log #fmt("mk_printer %u", linewidth);
let vec[mutable token] token = vec::init_elt_mut(EOF, n);
let vec[mutable int] size = vec::init_elt_mut(0, n);
let vec[mutable uint] scan_stack = vec::init_elt_mut(0u, n);
let vec[print_stack_elt] print_stack = [];
ret printer(out,
n,
linewidth as int, // margin
linewidth as int, // space
0u, // left
0u, // right
token,
size,
0, // left_total
0, // right_total
scan_stack,
true, // scan_stack_empty
0u, // top
0u, // bottom
print_stack,
0);
ret printer(out, n, linewidth as int, // margin
linewidth as int, // space
0u, // left
0u, // right
token, size, 0, // left_total
0, // right_total
scan_stack, true, // scan_stack_empty
0u, // top
0u, // bottom
print_stack, 0);
}
/*
* In case you do not have the paper, here is an explanation of what's going
* on.
@ -212,43 +198,46 @@ fn mk_printer(io::writer out, uint linewidth) -> printer {
* the method called 'pretty_print', and the 'PRINT' process is the method
* called 'print'.
*/
obj printer(io::writer out,
uint buf_len,
mutable int margin, // width of lines we're constrained to
mutable int space, // number of spaces left on line
mutable int margin, // width of lines we're constrained to
mutable uint left, // index of left side of input stream
mutable uint right, // index of right side of input stream
mutable vec[mutable token] token,// ring-buffr stream goes through
mutable vec[mutable int] size, // ring-buffer of calculated sizes
mutable int left_total, // running size of stream "...left"
mutable int right_total, // running size of stream "...right"
mutable int space, // number of spaces left on line
// pseudo-stack, really a ring too. Holds the primary-ring-buffers
// index of the BEGIN that started the current block, possibly
// with the most recent BREAK after that BEGIN (if there is any)
// on top of it. Stuff is flushed off the bottom as it becomes
// irrelevant due to the primary ring-buffer advancing.
mutable uint left, // index of left side of input stream
mutable vec[mutable uint] scan_stack,
mutable uint right, // index of right side of input stream
mutable vec[mutable token]
token, // ring-buffr stream goes through
mutable vec[mutable int] size, // ring-buffer of calculated sizes
mutable int left_total, // running size of stream "...left"
mutable int right_total, // running size of stream "...right"
// pseudo-stack, really a ring too. Holds the
// primary-ring-buffers index of the BEGIN that started the
// current block, possibly with the most recent BREAK after that
// BEGIN (if there is any) on top of it. Stuff is flushed off the
// bottom as it becomes irrelevant due to the primary ring-buffer
// advancing.
mutable vec[mutable uint] scan_stack,
mutable bool scan_stack_empty, // top==bottom disambiguator
mutable uint top, // index of top of scan_stack
mutable uint bottom, // index of bottom of scan_stack
// stack of blocks-in-progress being flushed by print
mutable uint top, // index of top of scan_stack
mutable uint bottom, // index of bottom of scan_stack
// stack of blocks-in-progress being flushed by print
mutable vec[print_stack_elt] print_stack,
// buffered indentation to avoid writing trailing whitespace
mutable int pending_indentation
) {
mutable int pending_indentation) {
fn pretty_print(token t) {
log #fmt("pp [%u,%u]", left, right);
alt (t) {
case (EOF) {
if (!scan_stack_empty) {
self.check_stack(0);
@ -256,22 +245,18 @@ obj printer(io::writer out,
}
self.indent(0);
}
case (BEGIN(?b)) {
if (scan_stack_empty) {
left_total = 1;
right_total = 1;
left = 0u;
right = 0u;
} else {
self.advance_right();
}
} else { self.advance_right(); }
log #fmt("pp BEGIN/buffer [%u,%u]", left, right);
token.(right) = t;
size.(right) = -right_total;
self.scan_push(right);
}
case (END) {
if (scan_stack_empty) {
log #fmt("pp END/print [%u,%u]", left, right);
@ -284,16 +269,13 @@ obj printer(io::writer out,
self.scan_push(right);
}
}
case (BREAK(?b)) {
if (scan_stack_empty) {
left_total = 1;
right_total = 1;
left = 0u;
right = 0u;
} else {
self.advance_right();
}
} else { self.advance_right(); }
log #fmt("pp BREAK/buffer [%u,%u]", left, right);
self.check_stack(0);
self.scan_push(right);
@ -301,7 +283,6 @@ obj printer(io::writer out,
size.(right) = -right_total;
right_total += b.blank_space;
}
case (STRING(?s, ?len)) {
if (scan_stack_empty) {
log #fmt("pp STRING/print [%u,%u]", left, right);
@ -317,13 +298,12 @@ obj printer(io::writer out,
}
}
}
fn check_stream() {
log #fmt("check_stream [%u, %u] with left_total=%d, right_total=%d",
left, right, left_total, right_total);;
left, right, left_total, right_total);
if (right_total - left_total > space) {
log #fmt("scan window is %d, longer than space on line (%d)",
right_total - left_total, space);
right_total - left_total, space);
if (!scan_stack_empty) {
if (left == scan_stack.(bottom)) {
log #fmt("setting %u to infinity and popping", left);
@ -331,72 +311,52 @@ obj printer(io::writer out,
}
}
self.advance_left(token.(left), size.(left));
if (left != right) {
self.check_stream();
}
if (left != right) { self.check_stream(); }
}
}
fn scan_push(uint x) {
log #fmt("scan_push %u", x);
if (scan_stack_empty) {
scan_stack_empty = false;
} else {
top += 1u;
top %= buf_len;
assert top != bottom;
}
} else { top += 1u; top %= buf_len; assert (top != bottom); }
scan_stack.(top) = x;
}
fn scan_pop() -> uint {
assert !scan_stack_empty;
assert (!scan_stack_empty);
auto x = scan_stack.(top);
if (top == bottom) {
scan_stack_empty = true;
} else {
top += (buf_len - 1u);
top %= buf_len;
}
} else { top += buf_len - 1u; top %= buf_len; }
ret x;
}
fn scan_top() -> uint {
assert !scan_stack_empty;
assert (!scan_stack_empty);
ret scan_stack.(top);
}
fn scan_pop_bottom() -> uint {
assert !scan_stack_empty;
assert (!scan_stack_empty);
auto x = scan_stack.(bottom);
if (top == bottom) {
scan_stack_empty = true;
} else {
bottom += 1u;
bottom %= buf_len;
}
} else { bottom += 1u; bottom %= buf_len; }
ret x;
}
fn advance_right() {
right += 1u;
right %= buf_len;
assert right != left;
assert (right != left);
}
fn advance_left(token x, int L) {
log #fmt("advnce_left [%u,%u], sizeof(%u)=%d", left, right, left, L);
if (L >= 0) {
self.print(x, L);
alt (x) {
case (BREAK(?b)) {
left_total += b.blank_space;
}
case (BREAK(?b)) { left_total += b.blank_space; }
case (STRING(_, ?len)) {
assert len == L;
assert (len == L);
left_total += len;
}
case (_) {}
case (_) { }
}
if (left != right) {
left += 1u;
@ -405,7 +365,6 @@ obj printer(io::writer out,
}
}
}
fn check_stack(int k) {
if (!scan_stack_empty) {
auto x = self.scan_top();
@ -418,41 +377,33 @@ obj printer(io::writer out,
}
case (END) {
// paper says + not =, but that makes no sense.
size.(self.scan_pop()) = 1;
self.check_stack(k + 1);
}
case (_) {
size.(self.scan_pop()) = size.(x) + right_total;
if (k > 0) {
self.check_stack(k);
}
if (k > 0) { self.check_stack(k); }
}
}
}
}
fn print_newline(int amount) {
log #fmt("NEWLINE %d", amount);
out.write_str("\n");
pending_indentation = 0;
self.indent(amount);
}
fn indent(int amount) {
log #fmt("INDENT %d", amount);
pending_indentation += amount;
}
fn top() -> print_stack_elt {
auto n = vec::len(print_stack);
let print_stack_elt top =
rec(offset=0, pbreak=broken(inconsistent));;
if (n != 0u) {
top = print_stack.(n - 1u);
}
let print_stack_elt top = rec(offset=0, pbreak=broken(inconsistent));
if (n != 0u) { top = print_stack.(n - 1u); }
ret top;
}
fn write_str(str s) {
while (pending_indentation > 0) {
out.write_str(" ");
@ -460,51 +411,41 @@ obj printer(io::writer out,
}
out.write_str(s);
}
fn print(token x, int L) {
log #fmt("print %s %d (remaining line space=%d)",
tok_str(x), L, space);
log #fmt("print %s %d (remaining line space=%d)", tok_str(x), L,
space);
log buf_str(token, size, left, right, 6u);
alt (x) {
case (BEGIN(?b)) {
if (L > space) {
auto col = (margin - space) + b.offset;
auto col = margin - space + b.offset;
log #fmt("print BEGIN -> push broken block at col %d",
col);
vec::push(print_stack,
rec(offset = col,
pbreak = broken(b.breaks)));
rec(offset=col, pbreak=broken(b.breaks)));
} else {
log "print BEGIN -> push fitting block";
vec::push(print_stack,
rec(offset = 0,
pbreak = fits));
vec::push(print_stack, rec(offset=0, pbreak=fits));
}
}
case (END) {
log "print END -> pop END";
assert vec::len(print_stack) != 0u;
assert (vec::len(print_stack) != 0u);
vec::pop(print_stack);
}
case (BREAK(?b)) {
auto top = self.top();
alt (top.pbreak) {
case (fits) {
log "print BREAK in fitting block";
space -= b.blank_space;
self.indent(b.blank_space);
}
case (broken(consistent)) {
log "print BREAK in consistent block";
self.print_newline(top.offset + b.offset);
space = margin - (top.offset + b.offset);
}
case (broken(inconsistent)) {
if (L > space) {
log "print BREAK w/ newline in inconsistent";
@ -518,17 +459,17 @@ obj printer(io::writer out,
}
}
}
case (STRING(?s, ?len)) {
log "print STRING";
assert L == len;
assert (L == len);
// assert L <= space;
space -= len;
self.write_str(s);
}
case (EOF) {
// EOF should never get here.
fail;
}
}
@ -537,45 +478,37 @@ obj printer(io::writer out,
// Convenience functions to talk to the printer.
fn box(printer p, uint indent, breaks b) {
p.pretty_print(BEGIN(rec(offset = indent as int,
breaks = b)));
p.pretty_print(BEGIN(rec(offset=indent as int, breaks=b)));
}
fn ibox(printer p, uint indent) { box(p, indent, inconsistent); }
fn ibox(printer p, uint indent) {
box(p, indent, inconsistent);
}
fn cbox(printer p, uint indent) {
box(p, indent, consistent);
}
fn cbox(printer p, uint indent) { box(p, indent, consistent); }
fn break_offset(printer p, uint n, int off) {
p.pretty_print(BREAK(rec(offset = off,
blank_space = n as int)));
p.pretty_print(BREAK(rec(offset=off, blank_space=n as int)));
}
fn end(printer p) { p.pretty_print(END); }
fn eof(printer p) { p.pretty_print(EOF); }
fn word(printer p, str wrd) {
p.pretty_print(STRING(wrd, str::char_len(wrd) as int));
}
fn huge_word(printer p, str wrd) {
p.pretty_print(STRING(wrd, 0xffff));
}
fn zero_word(printer p, str wrd) {
p.pretty_print(STRING(wrd, 0));
}
fn huge_word(printer p, str wrd) { p.pretty_print(STRING(wrd, 0xffff)); }
fn zero_word(printer p, str wrd) { p.pretty_print(STRING(wrd, 0)); }
fn spaces(printer p, uint n) { break_offset(p, n, 0); }
fn zerobreak(printer p) { spaces(p, 0u); }
fn space(printer p) { spaces(p, 1u); }
fn hardbreak(printer p) { spaces(p, 0xffffu); }
//
// Local Variables:
// mode: rust

View File

@ -1,3 +1,4 @@
import std::io;
import middle::ty::*;
import front::ast::constr_arg;
@ -10,169 +11,122 @@ import front::codemap;
import front::codemap::codemap;
fn ty_to_str(&ctxt cx, &t typ) -> str {
fn fn_input_to_str(&ctxt cx,
&rec(middle::ty::mode mode, t ty) input) -> str {
auto s = alt (input.mode) {
case (mo_val) { "" }
case (mo_alias(false)) { "&" }
case (mo_alias(true)) { "&mutable " }
};
fn fn_input_to_str(&ctxt cx, &rec(middle::ty::mode mode, t ty) input) ->
str {
auto s =
alt (input.mode) {
case (mo_val) { "" }
case (mo_alias(false)) { "&" }
case (mo_alias(true)) { "&mutable " }
};
ret s + ty_to_str(cx, input.ty);
}
fn fn_to_str(&ctxt cx,
ast::proto proto,
option::t[ast::ident] ident,
fn fn_to_str(&ctxt cx, ast::proto proto, option::t[ast::ident] ident,
vec[arg] inputs, t output, ast::controlflow cf,
&vec[@ast::constr] constrs) -> str {
auto f = bind fn_input_to_str(cx, _);
auto s;
alt (proto) {
case (ast::proto_iter) {
s = "iter";
}
case (ast::proto_fn) {
s = "fn";
}
auto f = bind fn_input_to_str(cx, _);
auto s;
alt (proto) {
case (ast::proto_iter) { s = "iter"; }
case (ast::proto_fn) { s = "fn"; }
}
alt (ident) { case (some(?i)) { s += " "; s += i; } case (_) { } }
s += "(";
s += str::connect(vec::map[arg, str](f, inputs), ", ");
s += ")";
if (struct(cx, output) != ty_nil) {
alt (cf) {
case (ast::noreturn) { s += " -> !"; }
case (ast::return) { s += " -> " + ty_to_str(cx, output); }
}
alt (ident) {
case (some(?i)) {
s += " ";
s += i;
}
case (_) { }
}
s += "(";
s += str::connect(vec::map[arg,str](f, inputs), ", ");
s += ")";
if (struct(cx, output) != ty_nil) {
alt (cf) {
case (ast::noreturn) {
s += " -> !";
}
case (ast::return) {
s += " -> " + ty_to_str(cx, output);
}
}
}
s += constrs_str(constrs);
ret s;
}
s += constrs_str(constrs);
ret s;
}
fn method_to_str(&ctxt cx, &method m) -> str {
ret fn_to_str(cx, m.proto, some[ast::ident](m.ident),
m.inputs, m.output, m.cf, m.constrs) + ";";
ret fn_to_str(cx, m.proto, some[ast::ident](m.ident), m.inputs,
m.output, m.cf, m.constrs) + ";";
}
fn field_to_str(&ctxt cx, &field f) -> str {
ret mt_to_str(cx, f.mt) + " " + f.ident;
}
fn mt_to_str(&ctxt cx, &mt m) -> str {
auto mstr;
alt (m.mut) {
case (ast::mut) { mstr = "mutable "; }
case (ast::imm) { mstr = ""; }
case (ast::mut) { mstr = "mutable "; }
case (ast::imm) { mstr = ""; }
case (ast::maybe_mut) { mstr = "mutable? "; }
}
ret mstr + ty_to_str(cx, m.ty);
}
alt (cname(cx, typ)) {
case (some(?cs)) {
ret cs;
}
case (_) { }
}
alt (cname(cx, typ)) { case (some(?cs)) { ret cs; } case (_) { } }
auto s = "";
alt (struct(cx, typ)) {
case (ty_native) { s += "native"; }
case (ty_nil) { s += "()"; }
case (ty_bot) { s += "_|_"; }
case (ty_bool) { s += "bool"; }
case (ty_int) { s += "int"; }
case (ty_float) { s += "float"; }
case (ty_uint) { s += "uint"; }
case (ty_machine(?tm)) { s += common::ty_mach_to_str(tm); }
case (ty_char) { s += "char"; }
case (ty_str) { s += "str"; }
case (ty_istr) { s += "istr"; }
case (ty_box(?tm)) { s += "@" + mt_to_str(cx, tm); }
case (ty_vec(?tm)) { s += "vec[" + mt_to_str(cx, tm) + "]"; }
case (ty_ivec(?tm)) { s += "ivec[" + mt_to_str(cx, tm) + "]"; }
case (ty_port(?t)) { s += "port[" + ty_to_str(cx, t) + "]"; }
case (ty_chan(?t)) { s += "chan[" + ty_to_str(cx, t) + "]"; }
case (ty_type) { s += "type"; }
case (ty_task) { s += "task"; }
case (ty_native) { s += "native"; }
case (ty_nil) { s += "()"; }
case (ty_bot) { s += "_|_"; }
case (ty_bool) { s += "bool"; }
case (ty_int) { s += "int"; }
case (ty_float) { s += "float"; }
case (ty_uint) { s += "uint"; }
case (ty_machine(?tm)) { s += common::ty_mach_to_str(tm); }
case (ty_char) { s += "char"; }
case (ty_str) { s += "str"; }
case (ty_istr) { s += "istr"; }
case (ty_box(?tm)) { s += "@" + mt_to_str(cx, tm); }
case (ty_vec(?tm)) { s += "vec[" + mt_to_str(cx, tm) + "]"; }
case (ty_ivec(?tm)) { s += "ivec[" + mt_to_str(cx, tm) + "]"; }
case (ty_port(?t)) { s += "port[" + ty_to_str(cx, t) + "]"; }
case (ty_chan(?t)) { s += "chan[" + ty_to_str(cx, t) + "]"; }
case (ty_type) { s += "type"; }
case (ty_task) { s += "task"; }
case (ty_tup(?elems)) {
auto f = bind mt_to_str(cx, _);
auto strs = vec::map[mt,str](f, elems);
auto strs = vec::map[mt, str](f, elems);
s += "tup(" + str::connect(strs, ",") + ")";
}
case (ty_rec(?elems)) {
auto f = bind field_to_str(cx, _);
auto strs = vec::map[field,str](f, elems);
auto strs = vec::map[field, str](f, elems);
s += "rec(" + str::connect(strs, ",") + ")";
}
case (ty_tag(?id, ?tps)) {
// The user should never see this if the cname is set properly!
s += "<tag#" + util::common::istr(id._0) + ":" +
util::common::istr(id._1) + ">";
s +=
"<tag#" + util::common::istr(id._0) + ":" +
util::common::istr(id._1) + ">";
if (vec::len[t](tps) > 0u) {
auto f = bind ty_to_str(cx, _);
auto strs = vec::map[t,str](f, tps);
auto strs = vec::map[t, str](f, tps);
s += "[" + str::connect(strs, ",") + "]";
}
}
case (ty_fn(?proto, ?inputs, ?output, ?cf, ?constrs)) {
s += fn_to_str(cx, proto, none[ast::ident], inputs, output, cf,
constrs);
s +=
fn_to_str(cx, proto, none[ast::ident], inputs, output, cf,
constrs);
}
case (ty_native_fn(_, ?inputs, ?output)) {
let vec[@ast::constr] constrs = [];
s += fn_to_str(cx, ast::proto_fn, none[ast::ident],
inputs, output, ast::return, constrs);
let vec[@ast::constr] constrs = [];
s +=
fn_to_str(cx, ast::proto_fn, none[ast::ident], inputs, output,
ast::return, constrs);
}
case (ty_obj(?meths)) {
auto f = bind method_to_str(cx, _);
auto m = vec::map[method,str](f, meths);
auto m = vec::map[method, str](f, meths);
s += "obj {\n\t" + str::connect(m, "\n\t") + "\n}";
}
case (ty_var(?v)) {
s += "<T" + util::common::istr(v) + ">";
}
case (ty_var(?v)) { s += "<T" + util::common::istr(v) + ">"; }
case (ty_param(?id)) {
s += "'" + str::unsafe_from_bytes([('a' as u8) + (id as u8)]);
}
case (_) {
s += ty_to_short_str(cx, typ);
}
case (_) { s += ty_to_short_str(cx, typ); }
}
ret s;
}
fn ty_to_short_str(&ctxt cx, t typ) -> str {
auto f = def_to_str;
auto ecx = @rec(ds=f, tcx=cx, abbrevs=metadata::ac_no_abbrevs);
@ -181,46 +135,29 @@ fn ty_to_short_str(&ctxt cx, t typ) -> str {
ret s;
}
fn constr_arg_to_str[T](fn (&T) -> str f,
&ast::constr_arg_general_[T] c) -> str {
fn constr_arg_to_str[T](fn(&T) -> str f, &ast::constr_arg_general_[T] c) ->
str {
alt (c) {
case (ast::carg_base) {
ret "*";
}
case (ast::carg_ident(?i)) {
ret f(i);
}
case (ast::carg_lit(?l)) {
ret lit_to_str(l);
}
case (ast::carg_base) { ret "*"; }
case (ast::carg_ident(?i)) { ret f(i); }
case (ast::carg_lit(?l)) { ret lit_to_str(l); }
}
}
fn constr_arg_to_str_1(&ast::constr_arg_general_[str] c) -> str {
alt (c) {
case (ast::carg_base) {
ret "*";
}
case (ast::carg_ident(?i)) {
ret i;
}
case (ast::carg_lit(?l)) {
ret lit_to_str(l);
}
case (ast::carg_base) { ret "*"; }
case (ast::carg_ident(?i)) { ret i; }
case (ast::carg_lit(?l)) { ret lit_to_str(l); }
}
}
fn constr_args_to_str[T](fn (&T) -> str f,
fn constr_args_to_str[T](fn(&T) -> str f,
&vec[@ast::constr_arg_general[T]] args) -> str {
auto comma = false;
auto s = "(";
auto s = "(";
for (@ast::constr_arg_general[T] a in args) {
if (comma) {
s += ", ";
}
else {
comma = true;
}
if (comma) { s += ", "; } else { comma = true; }
s += constr_arg_to_str[T](f, a.node);
}
s += ")";
@ -229,14 +166,9 @@ fn constr_args_to_str[T](fn (&T) -> str f,
fn constr_args_to_str_1(&vec[@ast::constr_arg_use] args) -> str {
auto comma = false;
auto s = "(";
auto s = "(";
for (@ast::constr_arg_use a in args) {
if (comma) {
s += ", ";
}
else {
comma = true;
}
if (comma) { s += ", "; } else { comma = true; }
s += constr_arg_to_str_1(a.node);
}
s += ")";
@ -245,7 +177,6 @@ fn constr_args_to_str_1(&vec[@ast::constr_arg_use] args) -> str {
fn print_literal(&ps s, &@ast::lit lit) {
maybe_print_comment(s, lit.span.lo);
alt (next_lit(s)) {
case (some(?lt)) {
if (lt.pos == lit.span.lo) {
@ -254,39 +185,33 @@ fn print_literal(&ps s, &@ast::lit lit) {
ret;
}
}
case (_) {}
case (_) { }
}
alt (lit.node) {
case (ast::lit_str(?st,?kind)) {
case (ast::lit_str(?st, ?kind)) {
if (kind == ast::sk_unique) { word(s.s, "~"); }
print_string(s, st);
}
case (ast::lit_char(?ch)) {
word(s.s, "'" + escape_str(str::from_bytes([ch as u8]), '\'')
+ "'");
word(s.s,
"'" + escape_str(str::from_bytes([ch as u8]), '\'') + "'");
}
case (ast::lit_int(?val)) {
word(s.s, common::istr(val));
}
case (ast::lit_uint(?val)) {
word(s.s, common::uistr(val) + "u");
}
case (ast::lit_float(?fstr)) {
word(s.s, fstr);
}
case (ast::lit_mach_int(?mach,?val)) {
case (ast::lit_int(?val)) { word(s.s, common::istr(val)); }
case (ast::lit_uint(?val)) { word(s.s, common::uistr(val) + "u"); }
case (ast::lit_float(?fstr)) { word(s.s, fstr); }
case (ast::lit_mach_int(?mach, ?val)) {
word(s.s, common::istr(val as int));
word(s.s, common::ty_mach_to_str(mach));
}
case (ast::lit_mach_float(?mach,?val)) {
case (ast::lit_mach_float(?mach, ?val)) {
// val is already a str
word(s.s, val);
word(s.s, common::ty_mach_to_str(mach));
}
case (ast::lit_nil) {word(s.s, "()");}
case (ast::lit_nil) { word(s.s, "()"); }
case (ast::lit_bool(?val)) {
if (val) {word(s.s, "true");} else {word(s.s, "false");}
if (val) { word(s.s, "true"); } else { word(s.s, "false"); }
}
}
}
@ -298,9 +223,9 @@ fn next_lit(&ps s) -> option::t[lexer::lit] {
case (some(?lits)) {
if (s.cur_lit < vec::len(lits)) {
ret some(lits.(s.cur_lit));
} else {ret none[lexer::lit];}
} else { ret none[lexer::lit]; }
}
case (_) {ret none[lexer::lit];}
case (_) { ret none[lexer::lit]; }
}
}
@ -313,31 +238,25 @@ fn maybe_print_comment(&ps s, uint pos) {
s.cur_cmnt += 1u;
} else { break; }
}
case (_) {break;}
case (_) { break; }
}
}
}
fn print_comment(&ps s, lexer::cmnt cmnt) {
alt (cmnt.style) {
case (lexer::mixed) {
assert vec::len(cmnt.lines) == 1u;
assert (vec::len(cmnt.lines) == 1u);
zerobreak(s.s);
word(s.s, cmnt.lines.(0));
zerobreak(s.s);
}
case (lexer::isolated) {
hardbreak(s.s);
ibox(s, 0u);
for (str line in cmnt.lines) {
word(s.s, line);
hardbreak(s.s);
}
for (str line in cmnt.lines) { word(s.s, line); hardbreak(s.s); }
end(s);
}
case (lexer::trailing) {
word(s.s, " ");
if (vec::len(cmnt.lines) == 1u) {
@ -356,23 +275,25 @@ fn print_comment(&ps s, lexer::cmnt cmnt) {
}
fn print_string(&ps s, &str st) {
word(s.s, "\""); word(s.s, escape_str(st, '"')); word(s.s, "\"");
word(s.s, "\"");
word(s.s, escape_str(st, '"'));
word(s.s, "\"");
}
fn escape_str(str st, char to_escape) -> str {
let str out = "";
auto len = str::byte_len(st);
auto i = 0u;
while (i < len) {
alt (st.(i) as char) {
case ('\n') {out += "\\n";}
case ('\t') {out += "\\t";}
case ('\r') {out += "\\r";}
case ('\\') {out += "\\\\";}
case ('\n') { out += "\\n"; }
case ('\t') { out += "\\t"; }
case ('\r') { out += "\\r"; }
case ('\\') { out += "\\\\"; }
case (?cur) {
if (cur == to_escape) {out += "\\";}
if (cur == to_escape) { out += "\\"; }
// FIXME some (or all?) non-ascii things should be escaped
str::push_char(out, cur);
}
}
@ -381,7 +302,7 @@ fn escape_str(str st, char to_escape) -> str {
ret out;
}
fn to_str[T](&T t, fn(&ps s, &T s) f) -> str {
fn to_str[T](&T t, fn(&ps, &T) f) -> str {
auto writer = io::string_writer();
auto s = rust_printer(writer.get_writer());
f(s, t);
@ -389,42 +310,35 @@ fn to_str[T](&T t, fn(&ps s, &T s) f) -> str {
ret writer.get_str();
}
fn next_comment(&ps s) -> option::t[lexer::cmnt] {
alt (s.comments) {
case (some(?cmnts)) {
if (s.cur_cmnt < vec::len(cmnts)) {
ret some(cmnts.(s.cur_cmnt));
} else {ret none[lexer::cmnt];}
} else { ret none[lexer::cmnt]; }
}
case (_) {ret none[lexer::cmnt];}
case (_) { ret none[lexer::cmnt]; }
}
}
type ps = @rec(pp::printer s,
option::t[codemap] cm,
option::t[vec[lexer::cmnt]] comments,
option::t[vec[lexer::lit]] literals,
mutable uint cur_cmnt,
mutable uint cur_lit,
mutable vec[pp::breaks] boxes,
mode mode);
type ps =
@rec(pp::printer s,
option::t[codemap] cm,
option::t[vec[lexer::cmnt]] comments,
option::t[vec[lexer::lit]] literals,
mutable uint cur_cmnt,
mutable uint cur_lit,
mutable vec[pp::breaks] boxes,
mode mode);
fn ibox(&ps s, uint u) {
vec::push(s.boxes, pp::inconsistent);
pp::ibox(s.s, u);
}
fn end(&ps s) {
vec::pop(s.boxes);
pp::end(s.s);
}
fn end(&ps s) { vec::pop(s.boxes); pp::end(s.s); }
tag mode {
mo_untyped;
mo_typed(ctxt);
mo_identified;
}
tag mode { mo_untyped; mo_typed(ctxt); mo_identified; }
fn rust_printer(io::writer writer) -> ps {
let vec[pp::breaks] boxes = [];
@ -439,36 +353,29 @@ fn rust_printer(io::writer writer) -> ps {
}
const uint indent_unit = 4u;
const uint default_columns = 78u;
// needed b/c constr_args_to_str needs
// something that takes an alias
// (argh)
fn uint_to_str(&uint i) -> str {
ret util::common::uistr(i);
}
fn uint_to_str(&uint i) -> str { ret util::common::uistr(i); }
fn constr_to_str(&@ast::constr c) -> str {
ret path_to_str(c.node.path)
+ constr_args_to_str(uint_to_str, c.node.args);
ret path_to_str(c.node.path) +
constr_args_to_str(uint_to_str, c.node.args);
}
fn constrs_str(&vec[@ast::constr] constrs) -> str {
auto s = "";
auto colon = true;
for (@ast::constr c in constrs) {
if (colon) {
s += " : ";
colon = false;
auto s = "";
auto colon = true;
for (@ast::constr c in constrs) {
if (colon) { s += " : "; colon = false; } else { s += ", "; }
s += constr_to_str(c);
}
else {
s += ", ";
}
s += constr_to_str(c);
}
ret s;
ret s;
}
//
// Local Variables:
// mode: rust

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +1,4 @@
import std::map;
import std::map::hashmap;
import std::uint;
@ -12,7 +13,6 @@ import front::codemap::codemap;
import front::ast::lit;
import front::ast::path;
import middle::walk;
import std::io::stdout;
import std::io::str_writer;
import std::io::string_writer;
@ -28,8 +28,11 @@ import pretty::ppaux::mo_untyped;
import pretty::pp::mk_printer;
type filename = str;
type span = rec(uint lo, uint hi);
type spanned[T] = rec(T node, span span);
type flag = hashmap[str, ()];
tag ty_mach {
@ -37,20 +40,15 @@ tag ty_mach {
ty_i16;
ty_i32;
ty_i64;
ty_u8;
ty_u16;
ty_u32;
ty_u64;
ty_f32;
ty_f64;
}
tag ty_or_bang[T] {
a_ty(T);
a_bang;
}
tag ty_or_bang[T] { a_ty(T); a_bang; }
fn ty_mach_to_str(ty_mach tm) -> str {
alt (tm) {
@ -58,21 +56,19 @@ fn ty_mach_to_str(ty_mach tm) -> str {
case (ty_u16) { ret "u16"; }
case (ty_u32) { ret "u32"; }
case (ty_u64) { ret "u64"; }
case (ty_i8) { ret "i8"; }
case (ty_i16) { ret "i16"; }
case (ty_i32) { ret "i32"; }
case (ty_i64) { ret "i64"; }
case (ty_f32) { ret "f32"; }
case (ty_f64) { ret "f64"; }
}
}
fn new_str_hash[V]() -> std::map::hashmap[str,V] {
fn new_str_hash[V]() -> std::map::hashmap[str, V] {
let std::map::hashfn[str] hasher = std::str::hash;
let std::map::eqfn[str] eqer = std::str::eq;
ret std::map::mk_hashmap[str,V](hasher, eqer);
ret std::map::mk_hashmap[str, V](hasher, eqer);
}
fn def_eq(&ast::def_id a, &ast::def_id b) -> bool {
@ -81,40 +77,36 @@ fn def_eq(&ast::def_id a, &ast::def_id b) -> bool {
fn hash_def(&ast::def_id d) -> uint {
auto h = 5381u;
h = ((h << 5u) + h) ^ (d._0 as uint);
h = ((h << 5u) + h) ^ (d._1 as uint);
h = (h << 5u) + h ^ (d._0 as uint);
h = (h << 5u) + h ^ (d._1 as uint);
ret h;
}
fn new_def_hash[V]() -> std::map::hashmap[ast::def_id,V] {
fn new_def_hash[V]() -> std::map::hashmap[ast::def_id, V] {
let std::map::hashfn[ast::def_id] hasher = hash_def;
let std::map::eqfn[ast::def_id] eqer = def_eq;
ret std::map::mk_hashmap[ast::def_id,V](hasher, eqer);
ret std::map::mk_hashmap[ast::def_id, V](hasher, eqer);
}
fn new_int_hash[V]() -> std::map::hashmap[int,V] {
fn new_int_hash[V]() -> std::map::hashmap[int, V] {
fn hash_int(&int x) -> uint { ret x as uint; }
fn eq_int(&int a, &int b) -> bool { ret a == b; }
auto hasher = hash_int;
auto eqer = eq_int;
ret std::map::mk_hashmap[int,V](hasher, eqer);
ret std::map::mk_hashmap[int, V](hasher, eqer);
}
fn new_uint_hash[V]() -> std::map::hashmap[uint,V] {
fn new_uint_hash[V]() -> std::map::hashmap[uint, V] {
fn hash_uint(&uint x) -> uint { ret x; }
fn eq_uint(&uint a, &uint b) -> bool { ret a == b; }
auto hasher = hash_uint;
auto eqer = eq_uint;
ret std::map::mk_hashmap[uint,V](hasher, eqer);
ret std::map::mk_hashmap[uint, V](hasher, eqer);
}
fn istr(int i) -> str {
ret int::to_str(i, 10u);
}
fn istr(int i) -> str { ret int::to_str(i, 10u); }
fn uistr(uint i) -> str {
ret uint::to_str(i, 10u);
}
fn uistr(uint i) -> str { ret uint::to_str(i, 10u); }
fn elt_expr(&ast::elt e) -> @ast::expr { ret e.expr; }
@ -125,82 +117,51 @@ fn elt_exprs(&vec[ast::elt] elts) -> vec[@ast::expr] {
fn field_expr(&ast::field f) -> @ast::expr { ret f.node.expr; }
fn field_exprs(vec[ast::field] fields) -> vec [@ast::expr] {
fn field_exprs(vec[ast::field] fields) -> vec[@ast::expr] {
auto f = field_expr;
ret vec::map[ast::field, @ast::expr](f, fields);
}
fn log_expr(&ast::expr e) -> () {
log(pretty::pprust::expr_to_str(@e));
fn log_expr(&ast::expr e) { log pretty::pprust::expr_to_str(@e); }
fn log_expr_err(&ast::expr e) { log_err pretty::pprust::expr_to_str(@e); }
fn log_ty_err(&ty t) { log_err pretty::pprust::ty_to_str(t); }
fn log_pat_err(&@pat p) { log_err pretty::pprust::pat_to_str(p); }
fn log_block(&ast::block b) { log pretty::pprust::block_to_str(b); }
fn log_block_err(&ast::block b) { log_err pretty::pprust::block_to_str(b); }
fn log_item_err(&@ast::item i) { log_err pretty::pprust::item_to_str(i); }
fn log_fn(&ast::_fn f, str name, vec[ast::ty_param] params) {
log pretty::pprust::fun_to_str(f, name, params);
}
fn log_expr_err(&ast::expr e) -> () {
log_err(pretty::pprust::expr_to_str(@e));
fn log_fn_err(&ast::_fn f, str name, vec[ast::ty_param] params) {
log_err pretty::pprust::fun_to_str(f, name, params);
}
fn log_ty_err(&ty t) -> () {
log_err(pretty::pprust::ty_to_str(t));
}
fn log_stmt(&ast::stmt st) { log pretty::pprust::stmt_to_str(st); }
fn log_pat_err(&@pat p) -> () {
log_err(pretty::pprust::pat_to_str(p));
}
fn log_block(&ast::block b) -> () {
log(pretty::pprust::block_to_str(b));
}
fn log_block_err(&ast::block b) -> () {
log_err(pretty::pprust::block_to_str(b));
}
fn log_item_err(&@ast::item i) -> () {
log_err(pretty::pprust::item_to_str(i));
}
fn log_fn(&ast::_fn f, str name, vec[ast::ty_param] params) -> () {
log(pretty::pprust::fun_to_str(f, name, params));
}
fn log_fn_err(&ast::_fn f, str name, vec[ast::ty_param] params) -> () {
log_err(pretty::pprust::fun_to_str(f, name, params));
}
fn log_stmt(&ast::stmt st) -> () {
log(pretty::pprust::stmt_to_str(st));
}
fn log_stmt_err(&ast::stmt st) -> () {
log_err(pretty::pprust::stmt_to_str(st));
}
fn log_stmt_err(&ast::stmt st) { log_err pretty::pprust::stmt_to_str(st); }
fn decl_lhs(@ast::decl d) -> ast::def_id {
alt (d.node) {
case (ast::decl_local(?l)) {
ret l.id;
}
case (ast::decl_local(?l)) { ret l.id; }
case (ast::decl_item(?an_item)) {
alt (an_item.node) {
case (ast::item_const(_,_,_,_,?d,_)) {
ret d;
}
case (ast::item_fn(_,_,_,_,?d,_)) {
ret d;
}
case (ast::item_mod(_,_,_,?d)) {
ret d;
}
case (ast::item_native_mod(_,_,_,?d)) {
ret d;
}
case (ast::item_ty(_,_,_,_,?d,_)) {
ret d;
}
case (ast::item_tag(_,_,_,_,?d,_)) {
ret d;
}
case (ast::item_obj(_,_,_,_,?d,_)) {
case (ast::item_const(_, _, _, _, ?d, _)) { ret d; }
case (ast::item_fn(_, _, _, _, ?d, _)) { ret d; }
case (ast::item_mod(_, _, _, ?d)) { ret d; }
case (ast::item_native_mod(_, _, _, ?d)) { ret d; }
case (ast::item_ty(_, _, _, _, ?d, _)) { ret d; }
case (ast::item_tag(_, _, _, _, ?d, _)) { ret d; }
case (ast::item_obj(_, _, _, _, ?d, _)) {
ret d.ctor; /* This doesn't really make sense */
}
}
}
@ -208,18 +169,17 @@ fn decl_lhs(@ast::decl d) -> ast::def_id {
}
fn has_nonlocal_exits(&ast::block b) -> bool {
auto has_exits = @mutable false;
fn visit_expr(@mutable bool flag, &@ast::expr e) {
alt (e.node) {
case (ast::expr_break(_)) { *flag = true; }
case (ast::expr_cont(_)) { *flag = true; }
case (_) { }
}
}
auto v = rec(visit_expr_pre=bind visit_expr(has_exits, _)
with walk::default_visitor());
auto has_exits = @mutable false;
fn visit_expr(@mutable bool flag, &@ast::expr e) {
alt (e.node) {
case (ast::expr_break(_)) { *flag = true; }
case (ast::expr_cont(_)) { *flag = true; }
case (_) { }
}
}
auto v =
rec(visit_expr_pre=bind visit_expr(has_exits, _)
with walk::default_visitor());
walk::walk_block(v, b);
ret *has_exits;
}
@ -233,100 +193,85 @@ fn local_rhs_span(&@ast::local_ l, &span def) -> span {
fn lit_eq(&@ast::lit l, &@ast::lit m) -> bool {
alt (l.node) {
case (ast::lit_str(?s,?kind_s)) {
case (ast::lit_str(?s, ?kind_s)) {
alt (m.node) {
case (ast::lit_str(?t,?kind_t)) {
case (ast::lit_str(?t, ?kind_t)) {
ret s == t && kind_s == kind_t;
}
case (_) { ret false; }
case (_) { ret false; }
}
}
case (ast::lit_char(?c)) {
alt (m.node) {
case (ast::lit_char(?d)) { ret c == d; }
case (_) { ret false; }
case (_) { ret false; }
}
}
case (ast::lit_int(?i)) {
alt (m.node) {
case (ast::lit_int(?j)) { ret i == j; }
case (_) { ret false; }
case (_) { ret false; }
}
}
case (ast::lit_uint(?i)) {
alt (m.node) {
case (ast::lit_uint(?j)) { ret i == j; }
case (_) { ret false; }
case (_) { ret false; }
}
}
case (ast::lit_mach_int(_, ?i)) {
alt (m.node) {
case (ast::lit_mach_int(_, ?j)) { ret i == j; }
case (_) { ret false; }
case (_) { ret false; }
}
}
case (ast::lit_float(?s)) {
alt (m.node) {
case (ast::lit_float(?t)) { ret s == t; }
case (_) { ret false; }
case (_) { ret false; }
}
}
case (ast::lit_mach_float(_,?s)) {
case (ast::lit_mach_float(_, ?s)) {
alt (m.node) {
case (ast::lit_mach_float(_,?t)) { ret s == t; }
case (_) { ret false; }
case (ast::lit_mach_float(_, ?t)) { ret s == t; }
case (_) { ret false; }
}
}
case (ast::lit_nil) {
alt (m.node) {
case (ast::lit_nil) { ret true; }
case (_) { ret false; }
case (_) { ret false; }
}
}
case (ast::lit_bool(?b)) {
alt (m.node) {
case (ast::lit_bool(?c)) { ret b == c; }
case (_) { ret false; }
case (_) { ret false; }
}
}
}
}
fn respan[T](&span sp, &T t) -> spanned[T] {
ret rec(node=t, span=sp);
}
fn respan[T](&span sp, &T t) -> spanned[T] { ret rec(node=t, span=sp); }
fn may_begin_ident(char c) -> bool {
ret (is_alpha(c) || c == '_');
}
fn may_begin_ident(char c) -> bool { ret is_alpha(c) || c == '_'; }
fn in_range(char c, char lo, char hi) -> bool {
ret lo <= c && c <= hi;
}
fn in_range(char c, char lo, char hi) -> bool { ret lo <= c && c <= hi; }
fn is_alpha(char c) -> bool {
ret in_range(c, 'a', 'z') ||
in_range(c, 'A', 'Z');
ret in_range(c, 'a', 'z') || in_range(c, 'A', 'Z');
}
fn is_dec_digit(char c) -> bool {
ret in_range(c, '0', '9');
}
fn is_dec_digit(char c) -> bool { ret in_range(c, '0', '9'); }
fn is_alnum(char c) -> bool {
ret is_alpha(c) || is_dec_digit(c);
}
fn is_alnum(char c) -> bool { ret is_alpha(c) || is_dec_digit(c); }
fn is_hex_digit(char c) -> bool {
ret in_range(c, '0', '9') ||
in_range(c, 'a', 'f') ||
in_range(c, 'A', 'F');
}
fn is_bin_digit(char c) -> bool {
ret c == '0' || c == '1';
ret in_range(c, '0', '9') || in_range(c, 'a', 'f') ||
in_range(c, 'A', 'F');
}
fn is_bin_digit(char c) -> bool { ret c == '0' || c == '1'; }
//
// Local Variables:
// mode: rust

View File

@ -1,7 +1,8 @@
// An "interner" is a data structure that associates values with uint tags and
// allows bidirectional lookup; i.e. given a value, one can easily find the
// type, and vice versa.
import std::vec;
import std::map;
import std::map::hashmap;
@ -12,19 +13,17 @@ import std::option::none;
import std::option::some;
mod interner {
type interner[T] = rec(
hashmap[T,uint] map,
mutable vec[T] vect,
hashfn[T] hasher,
eqfn[T] eqer
);
type interner[T] =
rec(hashmap[T, uint] map,
mutable vec[T] vect,
hashfn[T] hasher,
eqfn[T] eqer);
fn mk[T](hashfn[T] hasher, eqfn[T] eqer) -> interner[T] {
auto m = map::mk_hashmap[T,uint](hasher, eqer);
auto m = map::mk_hashmap[T, uint](hasher, eqer);
let vec[T] vect = [];
ret rec(map=m, mutable vect=vect, hasher=hasher, eqer=eqer);
}
fn intern[T](&interner[T] itr, &T val) -> uint {
alt (itr.map.find(val)) {
case (some(?idx)) { ret idx; }
@ -36,9 +35,5 @@ mod interner {
}
}
}
fn get[T](&interner[T] itr, uint idx) -> T {
ret itr.vect.(idx);
}
}
fn get[T](&interner[T] itr, uint idx) -> T { ret itr.vect.(idx); }
}

View File

@ -1,3 +1,4 @@
export t;
export create;
export union;
@ -17,6 +18,7 @@ export to_vec;
export to_str;
export eq_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
@ -24,98 +26,71 @@ export eq_vec;
// FIXME: Almost all the functions in this module should be state fns, but the
// effect system isn't currently working correctly.
state type t = rec(vec[mutable uint] storage, uint nbits);
type t = rec(vec[mutable uint] storage, uint nbits);
// FIXME: this should be a constant once they work
fn uint_bits() -> uint {
ret 32u + ((1u << 32u) >> 27u);
}
fn uint_bits() -> uint { ret 32u + (1u << 32u >> 27u); }
fn create(uint nbits, bool init) -> t {
auto elt = if (init) { !0u } else { 0u };
auto storage = vec::init_elt_mut[uint](elt, nbits / uint_bits() + 1u);
ret rec(storage = storage, nbits = nbits);
ret rec(storage=storage, nbits=nbits);
}
fn process(&fn(uint, uint) -> uint op, &t v0, &t v1) -> bool {
fn process(&fn(uint, uint) -> uint op, &t v0, &t v1) -> bool {
auto len = vec::len(v1.storage);
assert (vec::len(v0.storage) == len);
assert (v0.nbits == v1.nbits);
auto changed = false;
for each (uint i in uint::range(0u, len)) {
auto w0 = v0.storage.(i);
auto w1 = v1.storage.(i);
auto w = op(w0, w1);
if (w0 != w) {
changed = true;
v0.storage.(i) = w;
}
if (w0 != w) { changed = true; v0.storage.(i) = w; }
}
ret changed;
}
fn lor(uint w0, uint w1) -> uint {
ret w0 | w1;
}
fn lor(uint w0, uint w1) -> uint { ret w0 | w1; }
fn union(&t v0, &t v1) -> bool {
auto sub = lor;
ret process(sub, v0, v1);
}
fn union(&t v0, &t v1) -> bool { auto sub = lor; ret process(sub, v0, v1); }
fn land(uint w0, uint w1) -> uint {
ret w0 & w1;
}
fn land(uint w0, uint w1) -> uint { ret w0 & w1; }
fn intersect(&t v0, &t v1) -> bool {
auto sub = land;
ret process(sub, v0, v1);
}
fn right(uint w0, uint w1) -> uint {
ret w1;
}
fn right(uint w0, uint w1) -> uint { ret w1; }
fn copy(&t v0, t v1) -> bool {
auto sub = right;
ret process(sub, v0, v1);
}
fn copy(&t v0, t v1) -> bool { auto sub = right; ret process(sub, v0, v1); }
fn clone(t v) -> t {
auto storage = vec::init_elt_mut[uint](0u, v.nbits / uint_bits() + 1u);
auto len = vec::len(v.storage);
for each (uint i in uint::range(0u, len)) {
storage.(i) = v.storage.(i);
}
ret rec(storage = storage, nbits = v.nbits);
for each (uint i in uint::range(0u, len)) { storage.(i) = v.storage.(i); }
ret rec(storage=storage, nbits=v.nbits);
}
fn get(&t v, uint i) -> bool {
assert (i < v.nbits);
auto bits = uint_bits();
auto w = i / bits;
auto b = i % bits;
auto x = 1u & (v.storage.(w) >> b);
auto x = 1u & v.storage.(w) >> b;
ret x == 1u;
}
fn equal(&t v0, &t v1) -> bool {
// FIXME: when we can break or return from inside an iterator loop,
// we can eliminate this painful while-loop
auto len = vec::len(v1.storage);
auto i = 0u;
while (i < len) {
if (v0.storage.(i) != v1.storage.(i)) {
ret false;
}
if (v0.storage.(i) != v1.storage.(i)) { ret false; }
i = i + 1u;
}
ret true;
@ -128,9 +103,7 @@ fn clear(&t v) {
}
fn set_all(&t v) {
for each (uint i in uint::range(0u, v.nbits)) {
set(v, i, true);
}
for each (uint i in uint::range(0u, v.nbits)) { set(v, i, true); }
}
fn invert(&t v) {
@ -139,6 +112,7 @@ fn invert(&t v) {
}
}
/* v0 = v0 - v1 */
fn difference(&t v0, &t v1) -> bool {
invert(v1);
@ -149,49 +123,30 @@ fn difference(&t v0, &t v1) -> bool {
fn set(&t v, uint i, bool x) {
assert (i < v.nbits);
auto bits = uint_bits();
auto w = i / bits;
auto b = i % bits;
auto w0 = v.storage.(w);
auto flag = 1u << b;
v.storage.(w) = if (x) {
v.storage.(w) | flag
} else {
v.storage.(w) & !flag
};
v.storage.(w) =
if (x) { v.storage.(w) | flag } else { v.storage.(w) & !flag };
}
/* true if all bits are 1 */
fn is_true(&t v) -> bool {
for (uint i in to_vec(v)) {
if (i != 1u) {
ret false;
}
}
for (uint i in to_vec(v)) { if (i != 1u) { ret false; } }
ret true;
}
/* true if all bits are non-1 */
fn is_false(&t v) -> bool {
for (uint i in to_vec(v)) {
if (i == 1u) {
ret false;
}
}
for (uint i in to_vec(v)) { if (i == 1u) { ret false; } }
ret true;
}
fn init_to_vec(t v, uint i) -> uint {
ret if (get(v, i)) {
1u
} else {
0u
};
}
fn init_to_vec(t v, uint i) -> uint { ret if (get(v, i)) { 1u } else { 0u }; }
fn to_vec(&t v) -> vec[uint] {
auto sub = bind init_to_vec(v, _);
@ -200,19 +155,13 @@ fn to_vec(&t v) -> vec[uint] {
fn to_str(&t v) -> str {
auto res = "";
for (uint i in bitv::to_vec(v)) {
if (i == 1u) {
res += "1";
}
else {
res += "0";
}
if (i == 1u) { res += "1"; } else { res += "0"; }
}
ret res;
}
// FIXME: can we just use structural equality on to_vec?
fn eq_vec(&t v0, &vec[uint] v1) -> bool {
assert (v0.nbits == vec::len[uint](v1));
@ -221,14 +170,11 @@ fn eq_vec(&t v0, &vec[uint] v1) -> bool {
while (i < len) {
auto w0 = get(v0, i);
auto w1 = v1.(i);
if ((!w0 && w1 != 0u) || (w0 && w1 == 0u)) {
ret false;
}
if (!w0 && w1 != 0u || w0 && w1 == 0u) { ret false; }
i = i + 1u;
}
ret true;
}
//
// Local Variables:
// mode: rust

View File

@ -1,8 +1,8 @@
export ptr_eq;
native "rust" mod rustrt {
fn rust_ptr_eq[T](@T a, @T b) -> int;
}
fn ptr_eq[T](@T a, @T b) -> bool { ret rustrt::rust_ptr_eq[T](a, b) != 0; }
fn ptr_eq[T](@T a, @T b) -> bool { ret rustrt::rust_ptr_eq[T](a, b) != 0; }

View File

@ -1,3 +1,6 @@
/**
* Unsafe debugging functions for inspecting values.
*
@ -19,25 +22,16 @@ native "rust" mod rustrt {
fn debug_trap(str msg);
}
fn debug_vec[T](vec[T] v) {
vec::print_debug_info[T](v);
}
fn debug_vec[T](vec[T] v) { vec::print_debug_info[T](v); }
fn debug_tydesc[T]() {
rustrt::debug_tydesc[T]();
}
fn debug_tydesc[T]() { rustrt::debug_tydesc[T](); }
fn debug_opaque[T](&T x) {
rustrt::debug_opaque[T](x);
}
fn debug_opaque[T](&T x) { rustrt::debug_opaque[T](x); }
fn debug_box[T](@T x) {
rustrt::debug_box[T](x);
}
fn debug_box[T](@T x) { rustrt::debug_box[T](x); }
fn debug_tag[T](&T x) { rustrt::debug_tag[T](x); }
fn debug_tag[T](&T x) {
rustrt::debug_tag[T](x);
}
/**
* `nmethods` is the number of methods we expect the object to have. The
@ -52,18 +46,11 @@ fn debug_obj[T](&T x, uint nmethods, uint nbytes) {
rustrt::debug_obj[T](x, nmethods, nbytes);
}
fn debug_fn[T](&T x) {
rustrt::debug_fn[T](x);
}
fn debug_fn[T](&T x) { rustrt::debug_fn[T](x); }
fn ptr_cast[T, U](@T x) -> @U {
ret rustrt::debug_ptrcast[T, U](x);
}
fn trap(str s) {
rustrt::debug_trap(s);
}
fn ptr_cast[T, U](@T x) -> @U { ret rustrt::debug_ptrcast[T, U](x); }
fn trap(str s) { rustrt::debug_trap(s); }
// Local Variables:
// mode: rust;
// fill-column: 78;

View File

@ -1,142 +1,112 @@
/**
* A deque, for fun. Untested as of yet. Likely buggy.
*/
type t[T] = obj {
fn size() -> uint;
fn add_front(&T t);
fn add_back(&T t);
fn pop_front() -> T;
fn pop_back() -> T;
fn peek_front() -> T;
fn peek_back() -> T;
fn get(int i) -> T;
};
type t[T] =
obj {
fn size() -> uint ;
fn add_front(&T) ;
fn add_back(&T) ;
fn pop_front() -> T ;
fn pop_back() -> T ;
fn peek_front() -> T ;
fn peek_back() -> T ;
fn get(int) -> T ;
};
fn create[T]() -> t[T] {
type cell[T] = option::t[T];
let uint initial_capacity = 32u; // 2^5
/**
* Grow is only called on full elts, so nelts is also len(elts), unlike
* elsewhere.
*/
/**
* Grow is only called on full elts, so nelts is also len(elts), unlike
* elsewhere.
*/
fn grow[T](uint nelts, uint lo, vec[mutable cell[T]] elts)
-> vec[mutable cell[T]] {
fn grow[T](uint nelts, uint lo, vec[mutable cell[T]] elts) ->
vec[mutable cell[T]] {
assert (nelts == vec::len(elts));
// FIXME: Making the vector argument an alias is a workaround for
// issue #375
fn fill[T](uint i, uint nelts, uint lo,
&vec[mutable cell[T]] old) -> cell[T] {
ret if (i < nelts) {
old.((lo + i) % nelts)
} else {
option::none
};
}
fn fill[T](uint i, uint nelts, uint lo, &vec[mutable cell[T]] old) ->
cell[T] {
ret if (i < nelts) {
old.((lo + i) % nelts)
} else { option::none };
}
let uint nalloc = uint::next_power_of_two(nelts + 1u);
let vec::init_op[cell[T]] copy_op = bind fill[T](_, nelts, lo, elts);
ret vec::init_fn_mut[cell[T]](copy_op, nalloc);
}
fn get[T](vec[mutable cell[T]] elts, uint i) -> T {
ret alt (elts.(i)) {
case (option::some(?t)) { t }
case (_) { fail }
};
case (option::some(?t)) { t }
case (_) { fail }
};
}
obj deque[T](mutable uint nelts,
mutable uint lo,
mutable uint hi,
mutable vec[mutable cell[T]] elts)
{
fn size() -> uint { ret nelts; }
fn add_front(&T t) {
let uint oldlo = lo;
if (lo == 0u) {
lo = vec::len[cell[T]](elts) - 1u;
} else {
lo -= 1u;
}
if (lo == hi) {
elts = grow[T](nelts, oldlo, elts);
lo = vec::len[cell[T]](elts) - 1u;
hi = nelts;
}
elts.(lo) = option::some[T](t);
nelts += 1u;
mutable vec[mutable cell[T]] elts) {
fn size() -> uint { ret nelts; }
fn add_front(&T t) {
let uint oldlo = lo;
if (lo == 0u) {
lo = vec::len[cell[T]](elts) - 1u;
} else { lo -= 1u; }
if (lo == hi) {
elts = grow[T](nelts, oldlo, elts);
lo = vec::len[cell[T]](elts) - 1u;
hi = nelts;
}
fn add_back(&T t) {
if (lo == hi && nelts != 0u) {
elts = grow[T](nelts, lo, elts);
lo = 0u;
hi = nelts;
}
elts.(hi) = option::some[T](t);
hi = (hi + 1u) % vec::len[cell[T]](elts);
nelts += 1u;
}
/**
* We actually release (turn to none()) the T we're popping so
* that we don't keep anyone's refcount up unexpectedly.
*/
fn pop_front() -> T {
let T t = get[T](elts, lo);
elts.(lo) = option::none[T];
lo = (lo + 1u) % vec::len[cell[T]](elts);
nelts -= 1u;
ret t;
}
fn pop_back() -> T {
if (hi == 0u) {
hi = vec::len[cell[T]](elts) - 1u;
} else {
hi -= 1u;
}
let T t = get[T](elts, hi);
elts.(hi) = option::none[T];
nelts -= 1u;
ret t;
}
fn peek_front() -> T {
ret get[T](elts, lo);
}
fn peek_back() -> T {
ret get[T](elts, hi - 1u);
}
fn get(int i) -> T {
let uint idx = (lo + (i as uint)) % vec::len[cell[T]](elts);
ret get[T](elts, idx);
}
elts.(lo) = option::some[T](t);
nelts += 1u;
}
fn add_back(&T t) {
if (lo == hi && nelts != 0u) {
elts = grow[T](nelts, lo, elts);
lo = 0u;
hi = nelts;
}
elts.(hi) = option::some[T](t);
hi = (hi + 1u) % vec::len[cell[T]](elts);
nelts += 1u;
}
let vec[mutable cell[T]] v = vec::init_elt_mut(option::none,
initial_capacity);
/**
* We actually release (turn to none()) the T we're popping so
* that we don't keep anyone's refcount up unexpectedly.
*/
fn pop_front() -> T {
let T t = get[T](elts, lo);
elts.(lo) = option::none[T];
lo = (lo + 1u) % vec::len[cell[T]](elts);
nelts -= 1u;
ret t;
}
fn pop_back() -> T {
if (hi == 0u) {
hi = vec::len[cell[T]](elts) - 1u;
} else { hi -= 1u; }
let T t = get[T](elts, hi);
elts.(hi) = option::none[T];
nelts -= 1u;
ret t;
}
fn peek_front() -> T { ret get[T](elts, lo); }
fn peek_back() -> T { ret get[T](elts, hi - 1u); }
fn get(int i) -> T {
let uint idx = (lo + (i as uint)) % vec::len[cell[T]](elts);
ret get[T](elts, idx);
}
}
let vec[mutable cell[T]] v =
vec::init_elt_mut(option::none, initial_capacity);
ret deque[T](0u, 0u, 0u, v);
}
// Local Variables:
// mode: rust;
// fill-column: 78;

View File

@ -1,40 +1,38 @@
// Simple Extensible Binary Markup Language (ebml) reader and writer on a
// cursor model. See the specification here:
// http://www.matroska.org/technical/specs/rfc/index.html
import option::none;
import option::some;
type ebml_tag = rec(uint id, uint size);
type ebml_state = rec(ebml_tag ebml_tag, uint tag_pos, uint data_pos);
// TODO: When we have module renaming, make "reader" and "writer" separate
// modules within this file.
// ebml reading
type doc = rec(vec[u8] data,
uint start,
uint end);
type doc = rec(vec[u8] data, uint start, uint end);
fn vint_at(vec[u8] data, uint start) -> tup(uint, uint) {
auto a = data.(start);
if (a & 0x80u8 != 0u8) { ret tup((a & 0x7fu8) as uint, start + 1u); }
if (a & 0x80u8 != 0u8) { ret tup(a & 0x7fu8 as uint, start + 1u); }
if (a & 0x40u8 != 0u8) {
ret tup((((a & 0x3fu8) as uint) << 8u) | (data.(start + 1u) as uint),
ret tup((a & 0x3fu8 as uint) << 8u | (data.(start + 1u) as uint),
start + 2u);
} else if (a & 0x20u8 != 0u8) {
ret tup((((a & 0x1fu8) as uint) << 16u) |
((data.(start + 1u) as uint) << 8u) |
(data.(start + 2u) as uint), start + 3u);
ret tup((a & 0x1fu8 as uint) << 16u |
(data.(start + 1u) as uint) << 8u |
(data.(start + 2u) as uint), start + 3u);
} else if (a & 0x10u8 != 0u8) {
ret tup((((a & 0x0fu8) as uint) << 24u) |
((data.(start + 1u) as uint) << 16u) |
((data.(start + 2u) as uint) << 8u) |
(data.(start + 3u) as uint), start + 4u);
} else {
log_err "vint too big"; fail;
}
ret tup((a & 0x0fu8 as uint) << 24u |
(data.(start + 1u) as uint) << 16u |
(data.(start + 2u) as uint) << 8u |
(data.(start + 3u) as uint), start + 4u);
} else { log_err "vint too big"; fail; }
}
fn new_doc(vec[u8] data) -> doc {
@ -63,7 +61,7 @@ fn maybe_get_doc(doc d, uint tg) -> option::t[doc] {
fn get_doc(doc d, uint tg) -> doc {
alt (maybe_get_doc(d, tg)) {
case (some(?d)) {ret d;}
case (some(?d)) { ret d; }
case (none) {
log_err "failed to find block with tag " + uint::to_str(tg, 10u);
fail;
@ -93,9 +91,7 @@ iter tagged_docs(doc d, uint tg) -> doc {
}
}
fn doc_data(doc d) -> vec[u8] {
ret vec::slice[u8](d.data, d.start, d.end);
}
fn doc_data(doc d) -> vec[u8] { ret vec::slice[u8](d.data, d.start, d.end); }
fn be_uint_from_bytes(vec[u8] data, uint start, uint size) -> uint {
auto sz = size;
@ -104,7 +100,7 @@ fn be_uint_from_bytes(vec[u8] data, uint start, uint size) -> uint {
auto pos = start;
while (sz > 0u) {
sz -= 1u;
val += (data.(pos) as uint) << (sz * 8u);
val += (data.(pos) as uint) << sz * 8u;
pos += 1u;
}
ret val;
@ -114,45 +110,35 @@ fn doc_as_uint(doc d) -> uint {
ret be_uint_from_bytes(d.data, d.start, d.end - d.start);
}
// ebml writing
// ebml writing
type writer = rec(io::buf_writer writer, mutable vec[uint] size_positions);
fn write_sized_vint(&io::buf_writer w, uint n, uint size) {
let vec[u8] buf;
alt (size) {
case (1u) {
buf = [0x80u8 | (n as u8)];
}
case (2u) {
buf = [0x40u8 | ((n >> 8u) as u8),
(n & 0xffu) as u8];
}
case (1u) { buf = [0x80u8 | (n as u8)]; }
case (2u) { buf = [0x40u8 | (n >> 8u as u8), n & 0xffu as u8]; }
case (3u) {
buf = [0x20u8 | ((n >> 16u) as u8),
((n >> 8u) & 0xffu) as u8,
(n & 0xffu) as u8];
buf =
[0x20u8 | (n >> 16u as u8), n >> 8u & 0xffu as u8,
n & 0xffu as u8];
}
case (4u) {
buf = [0x10u8 | ((n >> 24u) as u8),
((n >> 16u) & 0xffu) as u8,
((n >> 8u) & 0xffu) as u8,
(n & 0xffu) as u8];
}
case (_) {
log_err "vint to write too big";
fail;
buf =
[0x10u8 | (n >> 24u as u8), n >> 16u & 0xffu as u8,
n >> 8u & 0xffu as u8, n & 0xffu as u8];
}
case (_) { log_err "vint to write too big"; fail; }
}
w.write(buf);
}
fn write_vint(&io::buf_writer w, uint n) {
if (n < 0x7fu) { write_sized_vint(w, n, 1u); ret; }
if (n < 0x4000u) { write_sized_vint(w, n, 2u); ret; }
if (n < 0x200000u) { write_sized_vint(w, n, 3u); ret; }
if (n < 0x10000000u) { write_sized_vint(w, n, 4u); ret; }
if (n < 0x7fu) { write_sized_vint(w, n, 1u); ret; }
if (n < 0x4000u) { write_sized_vint(w, n, 2u); ret; }
if (n < 0x200000u) { write_sized_vint(w, n, 3u); ret; }
if (n < 0x10000000u) { write_sized_vint(w, n, 4u); ret; }
log_err "vint to write too big";
fail;
}
@ -162,13 +148,14 @@ fn create_writer(&io::buf_writer w) -> writer {
ret rec(writer=w, mutable size_positions=size_positions);
}
// TODO: Provide a function to write the standard ebml header.
// TODO: Provide a function to write the standard ebml header.
fn start_tag(&writer w, uint tag_id) {
// Write the tag ID:
write_vint(w.writer, tag_id);
write_vint(w.writer, tag_id);
// Write a placeholder four-byte size.
w.size_positions += [w.writer.tell()];
let vec[u8] zeroes = [0u8, 0u8, 0u8, 0u8];
w.writer.write(zeroes);
@ -181,6 +168,5 @@ fn end_tag(&writer w) {
write_sized_vint(w.writer, cur_pos - last_size_pos - 4u, 4u);
w.writer.seek(cur_pos as int, io::seek_set);
}
// TODO: optionally perform "relaxations" on end_tag to more efficiently
// encode sizes; this is a fixed point iteration

View File

@ -1,3 +1,5 @@
/* The 'fmt' extension is modeled on the posix printf system.
*
* A posix conversion ostensibly looks like this:
@ -12,10 +14,10 @@
* we also only support translating-to-rust a tiny subset of the possible
* combinations at the moment.
*/
import option::none;
import option::some;
/*
* We have a 'ct' (compile-time) module that parses format strings into a
* sequence of conversions. From those conversions AST fragments are built
@ -29,16 +31,8 @@ import option::some;
// Functions used by the fmt extension at compile time
mod ct {
tag signedness {
signed;
unsigned;
}
tag caseness {
case_upper;
case_lower;
}
tag signedness { signed; unsigned; }
tag caseness { case_upper; case_lower; }
tag ty {
ty_bool;
ty_str;
@ -48,8 +42,8 @@ mod ct {
ty_hex(caseness);
ty_octal;
// FIXME: More types
}
}
tag flag {
flag_left_justify;
flag_left_zero_pad;
@ -57,7 +51,6 @@ mod ct {
flag_sign_always;
flag_alternate;
}
tag count {
count_is(int);
count_is_param(int);
@ -66,25 +59,22 @@ mod ct {
}
// A formatted conversion from an expression to a string
type conv = rec(option::t[int] param,
vec[flag] flags,
count width,
count precision,
ty ty);
type conv =
rec(option::t[int] param,
vec[flag] flags,
count width,
count precision,
ty ty);
// A fragment of the output sequence
tag piece {
piece_string(str);
piece_conv(conv);
}
type error_fn = fn (str) -> !;
tag piece { piece_string(str); piece_conv(conv); }
type error_fn = fn(str) -> ! ;
fn parse_fmt_string(str s, error_fn error) -> vec[piece] {
let vec[piece] pieces = [];
auto lim = str::byte_len(s);
auto buf = "";
fn flush_buf(str buf, &mutable vec[piece] pieces) -> str {
if (str::byte_len(buf) > 0u) {
auto piece = piece_string(buf);
@ -92,7 +82,6 @@ mod ct {
}
ret "";
}
auto i = 0u;
while (i < lim) {
auto curr = str::substr(s, i, 1u);
@ -110,83 +99,57 @@ mod ct {
pieces += [res._0];
i = res._1;
}
} else {
buf += curr;
i += 1u;
}
} else { buf += curr; i += 1u; }
}
buf = flush_buf(buf, pieces);
ret pieces;
}
fn peek_num(str s, uint i, uint lim) -> option::t[tup(uint, uint)] {
if (i >= lim) {
ret none[tup(uint, uint)];
}
if (i >= lim) { ret none[tup(uint, uint)]; }
auto c = s.(i);
if (!('0' as u8 <= c && c <= '9' as u8)) {
ret option::none[tup(uint, uint)];
}
auto n = (c - ('0' as u8)) as uint;
auto n = c - ('0' as u8) as uint;
ret alt (peek_num(s, i + 1u, lim)) {
case (none) {
some[tup(uint, uint)](tup(n, i + 1u))
}
case (some(?next)) {
auto m = next._0;
auto j = next._1;
some[tup(uint, uint)](tup(n * 10u + m, j))
}
};
case (none) { some[tup(uint, uint)](tup(n, i + 1u)) }
case (some(?next)) {
auto m = next._0;
auto j = next._1;
some[tup(uint, uint)](tup(n * 10u + m, j))
}
};
}
fn parse_conversion(str s, uint i, uint lim,
error_fn error) -> tup(piece, uint) {
fn parse_conversion(str s, uint i, uint lim, error_fn error) ->
tup(piece, uint) {
auto parm = parse_parameter(s, i, lim);
auto flags = parse_flags(s, parm._1, lim);
auto width = parse_count(s, flags._1, lim);
auto prec = parse_precision(s, width._1, lim);
auto ty = parse_type(s, prec._1, lim, error);
ret tup(piece_conv(rec(param = parm._0,
flags = flags._0,
width = width._0,
precision = prec._0,
ty = ty._0)),
ty._1);
ret tup(piece_conv(rec(param=parm._0,
flags=flags._0,
width=width._0,
precision=prec._0,
ty=ty._0)), ty._1);
}
fn parse_parameter(str s, uint i, uint lim) -> tup(option::t[int], uint) {
if (i >= lim) {
ret tup(none[int], i);
}
if (i >= lim) { ret tup(none[int], i); }
auto num = peek_num(s, i, lim);
ret alt (num) {
case (none) {
tup(none[int], i)
}
case (some(?t)) {
auto n = t._0;
auto j = t._1;
if (j < lim && s.(j) == '$' as u8) {
tup(some[int](n as int), j + 1u)
case (none) { tup(none[int], i) }
case (some(?t)) {
auto n = t._0;
auto j = t._1;
if (j < lim && s.(j) == '$' as u8) {
tup(some[int](n as int), j + 1u)
} else { tup(none[int], i) }
}
else {
tup(none[int], i)
}
}
};
};
}
fn parse_flags(str s, uint i, uint lim) -> tup(vec[flag], uint) {
let vec[flag] noflags = [];
if (i >= lim) {
ret tup(noflags, i);
}
if (i >= lim) { ret tup(noflags, i); }
fn more_(flag f, str s, uint i, uint lim) -> tup(vec[flag], uint) {
auto next = parse_flags(s, i + 1u, lim);
auto rest = next._0;
@ -194,144 +157,106 @@ mod ct {
let vec[flag] curr = [f];
ret tup(curr + rest, j);
}
auto more = bind more_(_, s, i, lim);
auto f = s.(i);
ret if (f == ('-' as u8)) {
more(flag_left_justify)
} else if (f == ('0' as u8)) {
more(flag_left_zero_pad)
} else if (f == (' ' as u8)) {
more(flag_space_for_sign)
} else if (f == ('+' as u8)) {
more(flag_sign_always)
} else if (f == ('#' as u8)) {
more(flag_alternate)
} else {
tup(noflags, i)
};
ret if (f == '-' as u8) {
more(flag_left_justify)
} else if (f == '0' as u8) {
more(flag_left_zero_pad)
} else if (f == ' ' as u8) {
more(flag_space_for_sign)
} else if (f == '+' as u8) {
more(flag_sign_always)
} else if (f == '#' as u8) {
more(flag_alternate)
} else { tup(noflags, i) };
}
fn parse_count(str s, uint i, uint lim) -> tup(count, uint) {
ret if (i >= lim) {
tup(count_implied, i)
} else if (s.(i) == ('*' as u8)) {
auto param = parse_parameter(s, i + 1u, lim);
auto j = param._1;
alt (param._0) {
case (none) {
tup(count_is_next_param, j)
tup(count_implied, i)
} else if (s.(i) == '*' as u8) {
auto param = parse_parameter(s, i + 1u, lim);
auto j = param._1;
alt (param._0) {
case (none) { tup(count_is_next_param, j) }
case (some(?n)) { tup(count_is_param(n), j) }
}
case (some(?n)) {
tup(count_is_param(n), j)
} else {
auto num = peek_num(s, i, lim);
alt (num) {
case (none) { tup(count_implied, i) }
case (some(?num)) { tup(count_is(num._0 as int), num._1) }
}
}
} else {
auto num = peek_num(s, i, lim);
alt (num) {
case (none) {
tup(count_implied, i)
}
case (some(?num)) {
tup(count_is(num._0 as int), num._1)
}
}
};
};
}
fn parse_precision(str s, uint i, uint lim) -> tup(count, uint) {
ret if (i >= lim) {
tup(count_implied, i)
} else if (s.(i) == '.' as u8) {
auto count = parse_count(s, i + 1u, lim);
// If there were no digits specified, i.e. the precision
// was ".", then the precision is 0
alt (count._0) {
case (count_implied) {
tup(count_is(0), count._1)
tup(count_implied, i)
} else if (s.(i) == '.' as u8) {
auto count = parse_count(s, i + 1u, lim);
// If there were no digits specified, i.e. the precision
// was ".", then the precision is 0
alt (count._0) {
case (count_implied) { tup(count_is(0), count._1) }
case (_) { count }
}
case (_) {
count
}
}
} else {
tup(count_implied, i)
};
} else { tup(count_implied, i) };
}
fn parse_type(str s, uint i, uint lim, error_fn error) -> tup(ty, uint) {
if (i >= lim) {
error("missing type in conversion");
}
if (i >= lim) { error("missing type in conversion"); }
auto tstr = str::substr(s, i, 1u);
auto t = if (str::eq(tstr, "b")) {
ty_bool
} else if (str::eq(tstr, "s")) {
ty_str
} else if (str::eq(tstr, "c")) {
ty_char
} else if (str::eq(tstr, "d")
|| str::eq(tstr, "i")) {
// TODO: Do we really want two signed types here?
// How important is it to be printf compatible?
ty_int(signed)
} else if (str::eq(tstr, "u")) {
ty_int(unsigned)
} else if (str::eq(tstr, "x")) {
ty_hex(case_lower)
} else if (str::eq(tstr, "X")) {
ty_hex(case_upper)
} else if (str::eq(tstr, "t")) {
ty_bits
} else if (str::eq(tstr, "o")) {
ty_octal
} else {
error("unknown type in conversion: " + tstr)
};
auto t =
if (str::eq(tstr, "b")) {
ty_bool
} else if (str::eq(tstr, "s")) {
ty_str
} else if (str::eq(tstr, "c")) {
ty_char
} else if (str::eq(tstr, "d") || str::eq(tstr, "i")) {
// TODO: Do we really want two signed types here?
// How important is it to be printf compatible?
ty_int(signed)
} else if (str::eq(tstr, "u")) {
ty_int(unsigned)
} else if (str::eq(tstr, "x")) {
ty_hex(case_lower)
} else if (str::eq(tstr, "X")) {
ty_hex(case_upper)
} else if (str::eq(tstr, "t")) {
ty_bits
} else if (str::eq(tstr, "o")) {
ty_octal
} else { error("unknown type in conversion: " + tstr) };
ret tup(t, i + 1u);
}
}
// Functions used by the fmt extension at runtime. For now there are a lot of
// decisions made a runtime. If it proves worthwhile then some of these
// conditions can be evaluated at compile-time. For now though it's cleaner to
// implement it this way, I think.
mod rt {
tag flag {
flag_left_justify;
flag_left_zero_pad;
flag_space_for_sign;
flag_sign_always;
flag_alternate;
// FIXME: This is a hack to avoid creating 0-length vec exprs,
// which have some difficulty typechecking currently. See
// comments in front::extfmt::make_flags
flag_none;
}
tag count {
count_is(int);
count_implied;
}
tag ty {
ty_default;
ty_bits;
ty_hex_upper;
ty_hex_lower;
ty_octal;
}
tag count { count_is(int); count_implied; }
tag ty { ty_default; ty_bits; ty_hex_upper; ty_hex_lower; ty_octal; }
// FIXME: May not want to use a vector here for flags;
// instead just use a bool per flag
type conv = rec(vec[flag] flags,
count width,
count precision,
ty ty);
type conv = rec(vec[flag] flags, count width, count precision, ty ty);
fn conv_int(&conv cv, int i) -> str {
auto radix = 10u;
@ -346,59 +271,45 @@ mod rt {
}
ret pad(cv, s, pad_signed);
}
fn conv_uint(&conv cv, uint u) -> str {
auto prec = get_int_precision(cv);
auto res = alt (cv.ty) {
case (ty_default) {
uint_to_str_prec(u, 10u, prec)
}
case (ty_hex_lower) {
uint_to_str_prec(u, 16u, prec)
}
case (ty_hex_upper) {
str::to_upper(uint_to_str_prec(u, 16u, prec))
}
case (ty_bits) {
uint_to_str_prec(u, 2u, prec)
}
case (ty_octal) {
uint_to_str_prec(u, 8u, prec)
}
};
auto res =
alt (cv.ty) {
case (ty_default) { uint_to_str_prec(u, 10u, prec) }
case (ty_hex_lower) { uint_to_str_prec(u, 16u, prec) }
case (ty_hex_upper) {
str::to_upper(uint_to_str_prec(u, 16u, prec))
}
case (ty_bits) { uint_to_str_prec(u, 2u, prec) }
case (ty_octal) { uint_to_str_prec(u, 8u, prec) }
};
ret pad(cv, res, pad_unsigned);
}
fn conv_bool(&conv cv, bool b) -> str {
auto s = if (b) {
"true"
} else {
"false"
};
auto s = if (b) { "true" } else { "false" };
// run the boolean conversion through the string conversion logic,
// giving it the same rules for precision, etc.
ret conv_str(cv, s);
}
fn conv_char(&conv cv, char c) -> str {
ret pad(cv, str::from_char(c), pad_nozero);
}
fn conv_str(&conv cv, str s) -> str {
auto unpadded = alt (cv.precision) {
case (count_implied) {
s
}
case (count_is(?max)) {
// For strings, precision is the maximum characters displayed
if (max as uint < str::char_len(s)) {
// FIXME: substr works on bytes, not chars!
str::substr(s, 0u, max as uint)
} else {
s
auto unpadded =
alt (cv.precision) {
case (count_implied) { s }
case (count_is(?max)) {
// For strings, precision is the maximum characters
// displayed
if (max as uint < str::char_len(s)) {
// FIXME: substr works on bytes, not chars!
str::substr(s, 0u, max as uint)
} else { s }
}
}
};
};
ret pad(cv, unpadded, pad_nozero);
}
@ -406,10 +317,8 @@ mod rt {
// 0 and num is 0 then the result is the empty string.
fn int_to_str_prec(int num, uint radix, uint prec) -> str {
ret if (num < 0) {
"-" + uint_to_str_prec((-num) as uint, radix, prec)
} else {
uint_to_str_prec(num as uint, radix, prec)
};
"-" + uint_to_str_prec(-num as uint, radix, prec)
} else { uint_to_str_prec(num as uint, radix, prec) };
}
// Convert a uint to string with a minimum number of digits. If precision
@ -417,29 +326,22 @@ mod rt {
// to uint: but it doesn't seem all that useful.
fn uint_to_str_prec(uint num, uint radix, uint prec) -> str {
ret if (prec == 0u && num == 0u) {
""
} else {
auto s = uint::to_str(num, radix);
auto len = str::char_len(s);
if (len < prec) {
auto diff = prec - len;
auto pad = str_init_elt('0', diff);
pad + s
""
} else {
s
}
};
auto s = uint::to_str(num, radix);
auto len = str::char_len(s);
if (len < prec) {
auto diff = prec - len;
auto pad = str_init_elt('0', diff);
pad + s
} else { s }
};
}
fn get_int_precision(&conv cv) -> uint {
ret alt (cv.precision) {
case (count_is(?c)) {
c as uint
}
case (count_implied) {
1u
}
};
case (count_is(?c)) { c as uint }
case (count_implied) { 1u }
};
}
// FIXME: This might be useful in str: but needs to be utf8 safe first
@ -447,90 +349,59 @@ mod rt {
auto svec = vec::init_elt[u8](c as u8, n_elts);
// FIXME: Using unsafe_from_bytes because rustboot
// can't figure out the is_utf8 predicate on from_bytes?
ret str::unsafe_from_bytes(svec);
}
tag pad_mode {
pad_signed;
pad_unsigned;
pad_nozero;
}
tag pad_mode { pad_signed; pad_unsigned; pad_nozero; }
fn pad(&conv cv, str s, pad_mode mode) -> str {
auto uwidth;
alt (cv.width) {
case (count_implied) {
ret s;
}
case (count_implied) { ret s; }
case (count_is(?width)) {
// FIXME: Maybe width should be uint
uwidth = width as uint;
}
}
auto strlen = str::char_len(s);
if (uwidth <= strlen) {
ret s;
}
if (uwidth <= strlen) { ret s; }
auto padchar = ' ';
auto diff = uwidth - strlen;
if (have_flag(cv.flags, flag_left_justify)) {
auto padstr = str_init_elt(padchar, diff);
ret s + padstr;
}
auto might_zero_pad = false;
auto signed = false;
alt (mode) {
case (pad_nozero) {
// fallthrough
}
case (pad_signed) {
might_zero_pad = true;
signed = true;
}
case (pad_unsigned) {
might_zero_pad = true;
}
}
}
case (pad_signed) { might_zero_pad = true; signed = true; }
case (pad_unsigned) { might_zero_pad = true; }
}
fn have_precision(&conv cv) -> bool {
ret alt (cv.precision) {
case (count_implied) {
false
}
case (_) {
true
}
};
case (count_implied) { false }
case (_) { true }
};
}
auto zero_padding = false;
if (might_zero_pad
&& have_flag(cv.flags, flag_left_zero_pad)
&& !have_precision(cv)) {
if (might_zero_pad && have_flag(cv.flags, flag_left_zero_pad) &&
!have_precision(cv)) {
padchar = '0';
zero_padding = true;
}
auto padstr = str_init_elt(padchar, diff);
// This is completely heinous. If we have a signed value then
// potentially rip apart the intermediate result and insert some
// zeros. It may make sense to convert zero padding to a precision
// instead.
if (signed
&& zero_padding
&& str::byte_len(s) > 0u) {
if (signed && zero_padding && str::byte_len(s) > 0u) {
auto head = s.(0);
if (head == '+' as u8
|| head == '-' as u8
|| head == ' ' as u8) {
if (head == '+' as u8 || head == '-' as u8 || head == ' ' as u8) {
auto headstr = str::unsafe_from_bytes([head]);
auto bytelen = str::byte_len(s);
auto numpart = str::substr(s, 1u, bytelen - 1u);
@ -539,18 +410,11 @@ mod rt {
}
ret padstr + s;
}
fn have_flag(vec[flag] flags, flag f) -> bool {
for (flag candidate in flags) {
if (candidate == f) {
ret true;
}
}
for (flag candidate in flags) { if (candidate == f) { ret true; } }
ret false;
}
}
// Local Variables:
// mode: rust;
// fill-column: 78;

View File

@ -1,10 +1,10 @@
native "rust" mod rustrt {
fn rust_file_is_dir(str path) -> int;
fn rust_file_is_dir(str path) -> int;
}
fn path_sep() -> str {
ret str::from_char(os_fs::path_sep);
}
fn path_sep() -> str { ret str::from_char(os_fs::path_sep); }
type path = str;
@ -12,9 +12,7 @@ fn dirname(path p) -> path {
let int i = str::rindex(p, os_fs::path_sep as u8);
if (i == -1) {
i = str::rindex(p, os_fs::alt_path_sep as u8);
if (i == -1) {
ret p;
}
if (i == -1) { ret p; }
}
ret str::substr(p, 0u, i as uint);
}
@ -23,45 +21,40 @@ fn basename(path p) -> path {
let int i = str::rindex(p, os_fs::path_sep as u8);
if (i == -1) {
i = str::rindex(p, os_fs::alt_path_sep as u8);
if (i == -1) {
ret p;
}
if (i == -1) { ret p; }
}
auto len = str::byte_len(p);
if ((i+1) as uint >= len) { ret p; }
ret str::slice(p, i+1 as uint, len);
if (i + 1 as uint >= len) { ret p; }
ret str::slice(p, i + 1 as uint, len);
}
// FIXME: Need some typestate to avoid bounds check when len(pre) == 0
fn connect(path pre, path post) -> path {
auto len = str::byte_len(pre);
ret if (pre.(len - 1u) == (os_fs::path_sep as u8)) { // Trailing '/'?
pre + post
} else {
pre + path_sep() + post
};
ret if (pre.(len - 1u) == os_fs::path_sep as u8) {
// Trailing '/'?
pre + post
} else { pre + path_sep() + post };
}
fn file_is_dir(path p) -> bool {
ret rustrt::rust_file_is_dir(p) != 0;
}
fn file_is_dir(path p) -> bool { ret rustrt::rust_file_is_dir(p) != 0; }
fn list_dir(path p) -> vec[str] {
auto pl = str::byte_len(p);
if (pl == 0u || p.(pl - 1u) as char != os_fs::path_sep) {
p += path_sep();
}
let vec[str] full_paths = [];
for (str filename in os_fs::list_dir(p)) {
if (!str::eq(filename, ".")) {if (!str::eq(filename, "..")) {
vec::push[str](full_paths, p + filename);
}}
}
ret full_paths;
auto pl = str::byte_len(p);
if (pl == 0u || p.(pl - 1u) as char != os_fs::path_sep) {
p += path_sep();
}
let vec[str] full_paths = [];
for (str filename in os_fs::list_dir(p)) {
if (!str::eq(filename, ".")) {
if (!str::eq(filename, "..")) {
vec::push[str](full_paths, p + filename);
}
}
}
ret full_paths;
}
// Local Variables:
// mode: rust;
// fill-column: 78;

View File

@ -1,9 +1,8 @@
fn getenv(str n) -> option::t[str] {
auto s = os::libc::getenv(str::buf(n));
ret if ((s as int) == 0) {
option::none[str]
} else {
option::some[str](str::str_from_cstr(s))
};
}
fn getenv(str n) -> option::t[str] {
auto s = os::libc::getenv(str::buf(n));
ret if (s as int == 0) {
option::none[str]
} else { option::some[str](str::str_from_cstr(s)) };
}

View File

@ -1,3 +1,5 @@
/* Simple getopt alternative. Construct a vector of options, either by using
* reqopt, optopt, and optflag or by building them from components yourself,
* and pass them to getopts, along with a vector of actual arguments (not
@ -5,30 +7,22 @@
* You'll have to verify whether the amount of 'free' arguments in the match
* is what you expect. Use opt_* accessors (bottom of the file) to get
* argument values out of the match object.
*/
*/
import option::some;
import option::none;
export opt;
export reqopt;
export optopt;
export optflag;
export optflagopt;
export optmulti;
export getopts;
export result;
export success;
export failure;
export match;
export fail_;
export fail_str;
export opt_present;
export opt_str;
export opt_strs;
@ -36,63 +30,68 @@ export opt_maybe_str;
export opt_default;
tag name { long(str); short(char); }
tag hasarg { yes; no; maybe; }
tag occur { req; optional; multi; }
type opt = rec(name name, hasarg hasarg, occur occur);
fn mkname(str nm) -> name {
ret if (str::char_len(nm) == 1u) {
short(str::char_at(nm, 0u))
} else {
long(nm)
};
short(str::char_at(nm, 0u))
} else { long(nm) };
}
fn reqopt(str name) -> opt {
ret rec(name=mkname(name), hasarg=yes, occur=req);
}
fn optopt(str name) -> opt {
ret rec(name=mkname(name), hasarg=yes, occur=optional);
}
fn optflag(str name) -> opt {
ret rec(name=mkname(name), hasarg=no, occur=optional);
}
fn optflagopt(str name) -> opt {
ret rec(name=mkname(name), hasarg=maybe, occur=optional);
}
fn optmulti(str name) -> opt {
ret rec(name=mkname(name), hasarg=yes, occur=multi);
}
tag optval {
val(str);
given;
}
tag optval { val(str); given; }
type match = rec(vec[opt] opts, vec[mutable vec[optval]] vals, vec[str] free);
fn is_arg(str arg) -> bool {
ret str::byte_len(arg) > 1u && arg.(0) == '-' as u8;
}
fn name_str(name nm) -> str {
ret alt (nm) {
case (short(?ch)) {str::from_char(ch)}
case (long(?s)) {s}
};
case (short(?ch)) { str::from_char(ch) }
case (long(?s)) { s }
};
}
// FIXME rustboot workaround
fn name_eq(name a, name b) -> bool {
ret alt (a) {
case (long(?a)) {
alt (b) {
case (long(?b)) { str::eq(a, b) }
case (_) { false }
case (long(?a)) {
alt (b) {
case (long(?b)) { str::eq(a, b) }
case (_) { false }
}
}
}
case (_) { if (a == b) { true } else { false } }
};
case (_) { if (a == b) { true } else { false } }
};
}
fn find_opt(vec[opt] opts, name nm) -> option::t[uint] {
auto i = 0u;
auto l = vec::len[opt](opts);
@ -113,36 +112,32 @@ tag fail_ {
fn fail_str(fail_ f) -> str {
ret alt (f) {
case (argument_missing(?nm)) {
"Argument to option '" + nm + "' missing."
}
case (unrecognized_option(?nm)) {
"Unrecognized option: '" + nm + "'."
}
case (option_missing(?nm)) {
"Required option '" + nm + "' missing."
}
case (option_duplicated(?nm)) {
"Option '" + nm + "' given more than once."
}
case (unexpected_argument(?nm)) {
"Option " + nm + " does not take an argument."
}
};
case (argument_missing(?nm)) {
"Argument to option '" + nm + "' missing."
}
case (unrecognized_option(?nm)) {
"Unrecognized option: '" + nm + "'."
}
case (option_missing(?nm)) {
"Required option '" + nm + "' missing."
}
case (option_duplicated(?nm)) {
"Option '" + nm + "' given more than once."
}
case (unexpected_argument(?nm)) {
"Option " + nm + " does not take an argument."
}
};
}
tag result {
success(match);
failure(fail_);
}
tag result { success(match); failure(fail_); }
fn getopts(vec[str] args, vec[opt] opts) -> result {
auto n_opts = vec::len[opt](opts);
fn empty_(uint x) -> vec[optval]{ret vec::empty[optval]();}
fn empty_(uint x) -> vec[optval] { ret vec::empty[optval](); }
auto f = empty_;
auto vals = vec::init_fn_mut[vec[optval]](f, n_opts);
let vec[str] free = [];
auto l = vec::len[str](args);
auto i = 0u;
while (i < l) {
@ -163,8 +158,9 @@ fn getopts(vec[str] args, vec[opt] opts) -> result {
names = [long(tail)];
} else {
names = [long(str::slice(tail, 0u, eq as uint))];
i_arg = option::some[str]
(str::slice(tail, (eq as uint) + 1u, curlen - 2u));
i_arg =
option::some[str](str::slice(tail, (eq as uint) + 1u,
curlen - 2u));
}
} else {
auto j = 1u;
@ -180,7 +176,7 @@ fn getopts(vec[str] args, vec[opt] opts) -> result {
name_pos += 1u;
auto optid;
alt (find_opt(opts, nm)) {
case (some(?id)) {optid = id;}
case (some(?id)) { optid = id; }
case (none) {
ret failure(unrecognized_option(name_str(nm)));
}
@ -197,7 +193,7 @@ fn getopts(vec[str] args, vec[opt] opts) -> result {
vec::push[optval](vals.(optid),
val(option::get[str](i_arg)));
} else if (name_pos < vec::len[name](names) ||
i + 1u == l || is_arg(args.(i + 1u))) {
i + 1u == l || is_arg(args.(i + 1u))) {
vec::push[optval](vals.(optid), given);
} else {
i += 1u;
@ -220,63 +216,60 @@ fn getopts(vec[str] args, vec[opt] opts) -> result {
}
i += 1u;
}
i = 0u;
while (i < n_opts) {
auto n = vec::len[optval](vals.(i));
auto occ = opts.(i).occur;
if (occ == req) {if (n == 0u) {
ret failure(option_missing(name_str(opts.(i).name)));
}}
if (occ != multi) {if (n > 1u) {
ret failure(option_duplicated(name_str(opts.(i).name)));
}}
if (occ == req) {
if (n == 0u) {
ret failure(option_missing(name_str(opts.(i).name)));
}
}
if (occ != multi) {
if (n > 1u) {
ret failure(option_duplicated(name_str(opts.(i).name)));
}
}
i += 1u;
}
ret success(rec(opts=opts, vals=vals, free=free));
}
fn opt_vals(match m, str nm) -> vec[optval] {
ret alt (find_opt(m.opts, mkname(nm))) {
case (some(?id)) { m.vals.(id) }
case (none) {
log_err "No option '" + nm + "' defined.";
fail
}
};
}
fn opt_val(match m, str nm) -> optval {
ret opt_vals(m, nm).(0);
case (some(?id)) { m.vals.(id) }
case (none) { log_err "No option '" + nm + "' defined."; fail }
};
}
fn opt_val(match m, str nm) -> optval { ret opt_vals(m, nm).(0); }
fn opt_present(match m, str nm) -> bool {
ret vec::len[optval](opt_vals(m, nm)) > 0u;
}
fn opt_str(match m, str nm) -> str {
ret alt (opt_val(m, nm)) {
case (val(?s)) { s }
case (_) { fail }
};
ret alt (opt_val(m, nm)) { case (val(?s)) { s } case (_) { fail } };
}
fn opt_strs(match m, str nm) -> vec[str] {
let vec[str] acc = [];
for (optval v in opt_vals(m, nm)) {
alt (v) {
case (val(?s)) { vec::push[str](acc, s); }
case (_) {}
}
alt (v) { case (val(?s)) { vec::push[str](acc, s); } case (_) { } }
}
ret acc;
}
fn opt_maybe_str(match m, str nm) -> option::t[str] {
auto vals = opt_vals(m, nm);
if (vec::len[optval](vals) == 0u) { ret none[str]; }
ret alt (vals.(0)) {
case (val(?s)) { some[str](s) }
case (_) { none[str] }
};
case (val(?s)) { some[str](s) }
case (_) { none[str] }
};
}
/// Returns none if the option was not present, `def` if the option was
/// present but no argument was provided, and the argument if the option was
/// present and an argument was provided.
@ -284,11 +277,10 @@ fn opt_default(match m, str nm, str def) -> option::t[str] {
auto vals = opt_vals(m, nm);
if (vec::len[optval](vals) == 0u) { ret none[str]; }
ret alt (vals.(0)) {
case (val(?s)) { some[str](s) }
case (_) { some[str](def) }
}
case (val(?s)) { some[str](s) }
case (_) { some[str](def) }
}
}
// Local Variables:
// mode: rust;
// fill-column: 78;

View File

@ -1,61 +1,65 @@
fn add(int x, int y) -> int { ret x + y; }
fn sub(int x, int y) -> int { ret x - y; }
fn mul(int x, int y) -> int { ret x * y; }
fn div(int x, int y) -> int { ret x / y; }
fn rem(int x, int y) -> int { ret x % y; }
fn lt(int x, int y) -> bool { ret x < y; }
fn le(int x, int y) -> bool { ret x <= y; }
fn eq(int x, int y) -> bool { ret x == y; }
fn ne(int x, int y) -> bool { ret x != y; }
fn ge(int x, int y) -> bool { ret x >= y; }
fn gt(int x, int y) -> bool { ret x > y; }
fn positive(int x) -> bool { ret x > 0; }
fn negative(int x) -> bool { ret x < 0; }
fn nonpositive(int x) -> bool { ret x <= 0; }
fn nonnegative(int x) -> bool { ret x >= 0; }
// FIXME: Make sure this works with negative integers.
fn hash(&int x) -> uint { ret x as uint; }
fn eq_alias(&int x, &int y) -> bool { ret x == y; }
iter range(int lo, int hi) -> int {
let int lo_ = lo;
while (lo_ < hi) {
put lo_;
lo_ += 1;
}
while (lo_ < hi) { put lo_; lo_ += 1; }
}
fn to_str(int n, uint radix) -> str
{
fn to_str(int n, uint radix) -> str {
assert (0u < radix && radix <= 16u);
ret if (n < 0) {
"-" + uint::to_str((-n) as uint, radix)
} else {
uint::to_str(n as uint, radix)
};
"-" + uint::to_str(-n as uint, radix)
} else { uint::to_str(n as uint, radix) };
}
fn pow(int base, uint exponent) -> int {
ret if (exponent == 0u) {
1
} else if (base == 0) {
0
} else {
auto accum = base;
auto count = exponent;
while (count > 1u) {
accum *= base;
count -= 1u;
}
accum
};
1
} else if (base == 0) {
0
} else {
auto accum = base;
auto count = exponent;
while (count > 1u) { accum *= base; count -= 1u; }
accum
};
}
// Local Variables:
// mode: rust;
// fill-column: 78;

View File

@ -1,132 +1,123 @@
import os::libc;
native "rust" mod rustrt {
fn rust_get_stdin() -> os::libc::FILE;
fn rust_get_stdout() -> os::libc::FILE;
fn rust_get_stdin() -> os::libc::FILE;
fn rust_get_stdout() -> os::libc::FILE;
}
// Reading
// FIXME This is all buffered. We might need an unbuffered variant as well
tag seek_style { seek_set; seek_end; seek_cur; }
tag seek_style {seek_set; seek_end; seek_cur;}
// The raw underlying reader class. All readers must implement this.
type buf_reader =
state obj {
fn read(uint len) -> vec[u8];
fn read_byte() -> int;
fn unread_byte(int byte);
fn eof() -> bool;
obj {
fn read(uint) -> vec[u8] ;
fn read_byte() -> int ;
fn unread_byte(int) ;
fn eof() -> bool ;
// FIXME: Seekable really should be orthogonal. We will need
// inheritance.
fn seek(int offset, seek_style whence);
fn tell() -> uint;
// FIXME: Seekable really should be orthogonal. We will need
// inheritance.
fn seek(int, seek_style) ;
fn tell() -> uint ;
};
// Convenience methods for reading.
type reader =
state obj {
// FIXME: This should inherit from buf_reader.
fn get_buf_reader() -> buf_reader;
obj {
fn read_byte() -> int;
fn unread_byte(int byte);
fn read_bytes(uint len) -> vec[u8];
fn read_char() -> char;
fn eof() -> bool;
fn read_line() -> str;
fn read_c_str() -> str;
fn read_le_uint(uint size) -> uint;
fn read_le_int(uint size) -> int;
fn read_be_uint(uint size) -> uint;
fn read_whole_stream() -> vec[u8];
// FIXME: This should inherit from buf_reader.
fn get_buf_reader() -> buf_reader ;
fn read_byte() -> int ;
fn unread_byte(int) ;
fn read_bytes(uint) -> vec[u8] ;
fn read_char() -> char ;
fn eof() -> bool ;
fn read_line() -> str ;
fn read_c_str() -> str ;
fn read_le_uint(uint) -> uint ;
fn read_le_int(uint) -> int ;
fn read_be_uint(uint) -> uint ;
fn read_whole_stream() -> vec[u8] ;
fn seek(int, seek_style) ;
fn tell() -> uint ; // FIXME: eventually u64
fn seek(int offset, seek_style whence);
fn tell() -> uint; // FIXME: eventually u64
};
fn convert_whence(seek_style whence) -> int {
ret alt (whence) {
case (seek_set) {0}
case (seek_cur) {1}
case (seek_end) {2}
};
case (seek_set) { 0 }
case (seek_cur) { 1 }
case (seek_end) { 2 }
};
}
state obj FILE_buf_reader(os::libc::FILE f, bool must_close) {
obj FILE_buf_reader(os::libc::FILE f, bool must_close) {
fn read(uint len) -> vec[u8] {
auto buf = vec::alloc[u8](len);
auto read = os::libc::fread(vec::buf[u8](buf), 1u, len, f);
vec::len_set[u8](buf, read);
ret buf;
}
fn read_byte() -> int {
ret os::libc::fgetc(f);
}
fn unread_byte(int byte) {
os::libc::ungetc(byte, f);
}
fn eof() -> bool {
ret os::libc::feof(f) != 0;
}
fn read_byte() -> int { ret os::libc::fgetc(f); }
fn unread_byte(int byte) { os::libc::ungetc(byte, f); }
fn eof() -> bool { ret os::libc::feof(f) != 0; }
fn seek(int offset, seek_style whence) {
assert (os::libc::fseek(f, offset, convert_whence(whence)) == 0);
}
fn tell() -> uint {
ret os::libc::ftell(f) as uint;
}
drop {
if (must_close) { os::libc::fclose(f); }
}
}drop { if (must_close) { os::libc::fclose(f); } }
}
// FIXME: Convert this into pseudomethods on buf_reader.
state obj new_reader(buf_reader rdr) {
fn get_buf_reader() -> buf_reader {
ret rdr;
}
fn read_byte() -> int {
ret rdr.read_byte();
}
fn unread_byte(int byte) {
ret rdr.unread_byte(byte);
}
fn read_bytes(uint len) -> vec[u8] {
ret rdr.read(len);
}
obj new_reader(buf_reader rdr) {
fn get_buf_reader() -> buf_reader { ret rdr; }
fn read_byte() -> int { ret rdr.read_byte(); }
fn unread_byte(int byte) { ret rdr.unread_byte(byte); }
fn read_bytes(uint len) -> vec[u8] { ret rdr.read(len); }
fn read_char() -> char {
auto c0 = rdr.read_byte();
if (c0 == -1) {ret -1 as char;} // FIXME will this stay valid?
if (c0 == -1) {
ret -1 as char; // FIXME will this stay valid?
}
auto b0 = c0 as u8;
auto w = str::utf8_char_width(b0);
assert (w > 0u);
if (w == 1u) {ret b0 as char;}
if (w == 1u) { ret b0 as char; }
auto val = 0u;
while (w > 1u) {
w -= 1u;
auto next = rdr.read_byte();
assert (next > -1);
assert (next & 0xc0 == 0x80);
assert (next & 192 == 128);
val <<= 6u;
val += (next & 0x3f) as uint;
val += next & 63 as uint;
}
// See str::char_at
val += ((b0 << ((w + 1u) as u8)) as uint) << ((w - 1u) * 6u - w - 1u);
val += (b0 << (w + 1u as u8) as uint) << (w - 1u) * 6u - w - 1u;
ret val as char;
}
fn eof() -> bool {
ret rdr.eof();
}
fn eof() -> bool { ret rdr.eof(); }
fn read_line() -> str {
let vec[u8] buf = [];
// No break yet in rustc
auto go_on = true;
while (go_on) {
auto ch = rdr.read_byte();
if (ch == -1 || ch == 10) {go_on = false;}
else {vec::push[u8](buf, ch as u8);}
if (ch == -1 || ch == 10) {
go_on = false;
} else { vec::push[u8](buf, ch as u8); }
}
ret str::unsafe_from_bytes(buf);
}
@ -135,11 +126,13 @@ state obj new_reader(buf_reader rdr) {
auto go_on = true;
while (go_on) {
auto ch = rdr.read_byte();
if (ch < 1) {go_on = false;}
else {vec::push[u8](buf, ch as u8);}
if (ch < 1) {
go_on = false;
} else { vec::push[u8](buf, ch as u8); }
}
ret str::unsafe_from_bytes(buf);
}
// FIXME deal with eof?
fn read_le_uint(uint size) -> uint {
auto val = 0u;
@ -161,29 +154,25 @@ state obj new_reader(buf_reader rdr) {
}
ret val as int;
}
// FIXME deal with eof?
fn read_be_uint(uint size) -> uint {
auto val = 0u;
auto sz = size; // FIXME: trans::ml bug workaround
while (sz > 0u) {
sz -= 1u;
val += (rdr.read_byte() as uint) << (sz * 8u);
val += (rdr.read_byte() as uint) << sz * 8u;
}
ret val;
}
fn read_whole_stream() -> vec[u8] {
let vec[u8] buf = [];
while (!rdr.eof()) {
buf += rdr.read(2048u);
}
while (!rdr.eof()) { buf += rdr.read(2048u); }
ret buf;
}
fn seek(int offset, seek_style whence) {
ret rdr.seek(offset, whence);
}
fn tell() -> uint {
ret rdr.tell();
}
fn seek(int offset, seek_style whence) { ret rdr.seek(offset, whence); }
fn tell() -> uint { ret rdr.tell(); }
}
fn stdin() -> reader {
@ -192,17 +181,13 @@ fn stdin() -> reader {
fn file_reader(str path) -> reader {
auto f = os::libc::fopen(str::buf(path), str::buf("r"));
if (f as uint == 0u) {
log_err "error opening " + path;
fail;
}
if (f as uint == 0u) { log_err "error opening " + path; fail; }
ret new_reader(FILE_buf_reader(f, true));
}
// FIXME: Remove me once objects are exported.
fn new_reader_(buf_reader bufr) -> reader {
ret new_reader(bufr);
}
fn new_reader_(buf_reader bufr) -> reader { ret new_reader(bufr); }
// Byte buffer readers
@ -210,39 +195,28 @@ fn new_reader_(buf_reader bufr) -> reader {
// TODO: mutable? u8, but this fails with rustboot.
type byte_buf = @rec(vec[u8] buf, mutable uint pos);
state obj byte_buf_reader(byte_buf bbuf) {
obj byte_buf_reader(byte_buf bbuf) {
fn read(uint len) -> vec[u8] {
auto rest = vec::len[u8](bbuf.buf) - bbuf.pos;
auto to_read = len;
if (rest < to_read) {
to_read = rest;
}
if (rest < to_read) { to_read = rest; }
auto range = vec::slice[u8](bbuf.buf, bbuf.pos, bbuf.pos + to_read);
bbuf.pos += to_read;
ret range;
}
fn read_byte() -> int {
if (bbuf.pos == vec::len[u8](bbuf.buf)) {ret -1;}
if (bbuf.pos == vec::len[u8](bbuf.buf)) { ret -1; }
auto b = bbuf.buf.(bbuf.pos);
bbuf.pos += 1u;
ret b as int;
}
fn unread_byte(int byte) {
log_err "TODO: unread_byte";
fail;
}
fn eof() -> bool {
ret bbuf.pos == vec::len[u8](bbuf.buf);
}
fn unread_byte(int byte) { log_err "TODO: unread_byte"; fail; }
fn eof() -> bool { ret bbuf.pos == vec::len[u8](bbuf.buf); }
fn seek(int offset, seek_style whence) {
auto pos = bbuf.pos;
auto len = vec::len[u8](bbuf.buf);
bbuf.pos = seek_in_buf(offset, pos, len, whence);
}
fn tell() -> uint { ret bbuf.pos; }
}
@ -252,46 +226,35 @@ fn new_byte_buf_reader(vec[u8] buf) -> byte_buf_reader {
// Writing
tag fileflag { append; create; truncate; none; }
tag fileflag {
append;
create;
truncate;
none;
}
type buf_writer =
obj {
fn write(vec[u8]) ;
type buf_writer = state obj {
fn write(vec[u8] v);
// FIXME: Seekable really should be orthogonal. We will need
// inheritance.
fn seek(int, seek_style) ;
fn tell() -> uint ; // FIXME: eventually u64
// FIXME: Seekable really should be orthogonal. We will need inheritance.
fn seek(int offset, seek_style whence);
fn tell() -> uint; // FIXME: eventually u64
};
};
state obj FILE_writer(os::libc::FILE f, bool must_close) {
obj FILE_writer(os::libc::FILE f, bool must_close) {
fn write(vec[u8] v) {
auto len = vec::len[u8](v);
auto vbuf = vec::buf[u8](v);
auto nout = os::libc::fwrite(vbuf, len, 1u, f);
if (nout < 1u) {
log_err "error dumping buffer";
}
if (nout < 1u) { log_err "error dumping buffer"; }
}
fn seek(int offset, seek_style whence) {
assert (os::libc::fseek(f, offset, convert_whence(whence)) == 0);
}
fn tell() -> uint {
ret os::libc::ftell(f) as uint;
}
drop {
if (must_close) {os::libc::fclose(f);}
}
}drop { if (must_close) { os::libc::fclose(f); } }
}
state obj fd_buf_writer(int fd, bool must_close) {
obj fd_buf_writer(int fd, bool must_close) {
fn write(vec[u8] v) {
auto len = vec::len[u8](v);
auto count = 0u;
@ -307,41 +270,31 @@ state obj fd_buf_writer(int fd, bool must_close) {
count += nout as uint;
}
}
fn seek(int offset, seek_style whence) {
log_err "need 64-bit native calls for seek, sorry";
fail;
}
fn tell() -> uint {
log_err "need 64-bit native calls for tell, sorry";
fail;
}
drop {
if (must_close) {os::libc::close(fd);}
}
}drop { if (must_close) { 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();
os::libc_constants::O_WRONLY() | os::libc_constants::O_BINARY();
for (fileflag f in flags) {
alt (f) {
case (append) { fflags |= os::libc_constants::O_APPEND(); }
case (create) { fflags |= os::libc_constants::O_CREAT(); }
case (append) { fflags |= os::libc_constants::O_APPEND(); }
case (create) { fflags |= os::libc_constants::O_CREAT(); }
case (truncate) { fflags |= os::libc_constants::O_TRUNC(); }
case (none) {}
case (none) { }
}
}
auto fd = os::libc::open(str::buf(path),
fflags,
os::libc_constants::S_IRUSR() |
auto fd =
os::libc::open(str::buf(path), fflags,
os::libc_constants::S_IRUSR() |
os::libc_constants::S_IWUSR());
if (fd < 0) {
log_err "error opening file for writing";
log_err sys::rustrt::last_os_error();
@ -351,65 +304,50 @@ fn file_buf_writer(str path, vec[fileflag] flags) -> buf_writer {
}
type writer =
state obj {
fn get_buf_writer() -> buf_writer;
// write_str will continue to do utf-8 output only. an alternative
// function will be provided for general encoded string output
fn write_str(str s);
fn write_line(str s);
fn write_char(char ch);
fn write_int(int n);
fn write_uint(uint n);
fn write_bytes(vec[u8] bytes);
fn write_le_uint(uint n, uint size);
fn write_le_int(int n, uint size);
fn write_be_uint(uint n, uint size);
obj {
fn get_buf_writer() -> buf_writer ;
// write_str will continue to do utf-8 output only. an alternative
// function will be provided for general encoded string output
fn write_str(str) ;
fn write_line(str) ;
fn write_char(char) ;
fn write_int(int) ;
fn write_uint(uint) ;
fn write_bytes(vec[u8]) ;
fn write_le_uint(uint, uint) ;
fn write_le_int(int, uint) ;
fn write_be_uint(uint, uint) ;
};
fn uint_to_le_bytes(uint n, uint size) -> vec[u8] {
let vec[u8] bytes = [];
while (size > 0u) {
bytes += [(n & 255u) as u8];
n >>= 8u;
size -= 1u;
}
while (size > 0u) { bytes += [n & 255u as u8]; n >>= 8u; size -= 1u; }
ret bytes;
}
fn uint_to_be_bytes(uint n, uint size) -> vec[u8] {
let vec[u8] bytes = [];
auto i = (size - 1u) as int;
while (i >= 0) {
bytes += [((n >> ((i * 8) as uint)) & 255u) as u8];
i -= 1;
}
auto i = size - 1u as int;
while (i >= 0) { bytes += [n >> (i * 8 as uint) & 255u as u8]; i -= 1; }
ret bytes;
}
state obj new_writer(buf_writer out) {
fn get_buf_writer() -> buf_writer {
ret out;
}
fn write_str(str s) {
out.write(str::bytes(s));
}
obj new_writer(buf_writer out) {
fn get_buf_writer() -> buf_writer { ret out; }
fn write_str(str s) { out.write(str::bytes(s)); }
fn write_line(str s) {
out.write(str::bytes(s));
out.write(str::bytes("\n"));
}
fn write_char(char ch) {
// FIXME needlessly consy
out.write(str::bytes(str::from_char(ch)));
}
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)));
}
fn write_bytes(vec[u8] bytes) {
out.write(bytes);
}
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))); }
fn write_bytes(vec[u8] bytes) { out.write(bytes); }
fn write_le_uint(uint n, uint size) {
out.write(uint_to_le_bytes(n, size));
}
@ -421,109 +359,94 @@ state obj new_writer(buf_writer out) {
}
}
// FIXME: Remove me once objects are exported.
fn new_writer_(buf_writer out) -> writer {
ret new_writer(out);
}
fn new_writer_(buf_writer out) -> writer { ret new_writer(out); }
fn file_writer(str path, vec[fileflag] flags) -> writer {
ret new_writer(file_buf_writer(path, flags));
}
// FIXME: fileflags
fn buffered_file_buf_writer(str path) -> buf_writer {
auto f = os::libc::fopen(str::buf(path), str::buf("w"));
if (f as uint == 0u) {
log_err "error opening " + path;
fail;
}
if (f as uint == 0u) { log_err "error opening " + path; fail; }
ret FILE_writer(f, true);
}
// FIXME it would be great if this could be a const
fn stdout() -> writer {
ret new_writer(fd_buf_writer(1, false));
}
fn stdout() -> writer { ret new_writer(fd_buf_writer(1, false)); }
type str_writer =
state obj {
fn get_writer() -> writer;
fn get_str() -> str;
obj {
fn get_writer() -> writer ;
fn get_str() -> str ;
};
type mutable_byte_buf = @rec(mutable vec[mutable u8] buf, mutable uint pos);
state obj byte_buf_writer(mutable_byte_buf buf) {
obj byte_buf_writer(mutable_byte_buf buf) {
fn write(vec[u8] v) {
// Fast path.
if (buf.pos == vec::len(buf.buf)) {
// FIXME: Fix our type system. There's no reason you shouldn't be
// able to add a mutable vector to an immutable one.
auto mv = vec::rustrt::unsafe_vec_to_mut[u8](v);
buf.buf += mv;
buf.pos += vec::len[u8](v);
ret;
}
// FIXME: Optimize: These should be unique pointers.
auto vlen = vec::len[u8](v);
auto vpos = 0u;
while (vpos < vlen) {
auto b = v.(vpos);
if (buf.pos == vec::len(buf.buf)) {
buf.buf += [mutable b];
} else {
buf.buf.(buf.pos) = b;
}
} else { buf.buf.(buf.pos) = b; }
buf.pos += 1u;
vpos += 1u;
}
}
fn seek(int offset, seek_style whence) {
auto pos = buf.pos;
auto len = vec::len(buf.buf);
buf.pos = seek_in_buf(offset, pos, len, whence);
}
fn tell() -> uint { ret buf.pos; }
}
fn string_writer() -> str_writer {
// FIXME: yikes, this is bad. Needs fixing of mutable syntax.
let vec[mutable u8] b = [mutable 0u8];
vec::pop(b);
let mutable_byte_buf buf = @rec(mutable buf = b, mutable pos = 0u);
state obj str_writer_wrap(writer wr, mutable_byte_buf buf) {
fn get_writer() -> writer {ret wr;}
fn get_str() -> str {ret str::unsafe_from_bytes(buf.buf);}
let mutable_byte_buf buf = @rec(mutable buf=b, mutable pos=0u);
obj str_writer_wrap(writer wr, mutable_byte_buf buf) {
fn get_writer() -> writer { ret wr; }
fn get_str() -> str { ret str::unsafe_from_bytes(buf.buf); }
}
ret str_writer_wrap(new_writer(byte_buf_writer(buf)), buf);
}
// Utility functions
fn seek_in_buf(int offset, uint pos, uint len, seek_style whence) -> uint {
auto bpos = pos as int;
auto blen = len as int;
alt (whence) {
case (seek_set) { bpos = offset; }
case (seek_cur) { bpos += offset; }
case (seek_set) { bpos = offset; }
case (seek_cur) { bpos += offset; }
case (seek_end) { bpos = blen + offset; }
}
if (bpos < 0) {
bpos = 0;
} else if (bpos > blen) {
bpos = blen;
}
if (bpos < 0) { bpos = 0; } else if (bpos > blen) { bpos = blen; }
ret bpos as uint;
}
//
// Local Variables:
// mode: rust

View File

@ -1,16 +1,15 @@
import str::sbuf;
import vec::vbuf;
// FIXME Somehow merge stuff duplicated here and macosx_os.rs. Made difficult
// by https://github.com/graydon/rust/issues#issue/268
native mod libc = "libc.so.6" {
native "cdecl" mod libc {
fn open(sbuf s, int flags, uint mode) -> int;
fn read(int fd, vbuf buf, uint count) -> int;
fn write(int fd, vbuf buf, uint count) -> int;
fn close(int fd) -> int;
type FILE;
fn fopen(sbuf path, sbuf mode) -> FILE;
fn fdopen(int fd, sbuf mode) -> FILE;
@ -22,47 +21,43 @@ native mod libc = "libc.so.6" {
fn fwrite(vbuf buf, uint size, uint n, FILE f) -> uint;
fn fseek(FILE f, int offset, int whence) -> int;
fn ftell(FILE f) -> int;
type dir;
fn opendir(sbuf d) -> dir;
fn closedir(dir d) -> int;
type dirent;
fn readdir(dir d) -> dirent;
fn getenv(sbuf n) -> sbuf;
fn setenv(sbuf n, sbuf v, int overwrite) -> int;
fn unsetenv(sbuf n) -> int;
fn pipe(vbuf buf) -> int;
fn waitpid(int pid, vbuf status, int options) -> int;
}
mod libc_constants {
fn O_RDONLY() -> int { ret 0x0000; }
fn O_WRONLY() -> int { ret 0x0001; }
fn O_RDWR() -> int { ret 0x0002; }
fn O_APPEND() -> int { ret 0x0400; }
fn O_CREAT() -> int { ret 0x0040; }
fn O_EXCL() -> int { ret 0x0080; }
fn O_TRUNC() -> int { ret 0x0200; }
fn O_TEXT() -> int { ret 0x0000; } // nonexistent in linux libc
fn O_BINARY() -> int { ret 0x0000; } // nonexistent in linux libc
fn O_RDONLY() -> int { ret 0; }
fn O_WRONLY() -> int { ret 1; }
fn O_RDWR() -> int { ret 2; }
fn O_APPEND() -> int { ret 1024; }
fn O_CREAT() -> int { ret 64; }
fn O_EXCL() -> int { ret 128; }
fn O_TRUNC() -> int { ret 512; }
fn O_TEXT() -> int {
ret 0; // nonexistent in linux libc
fn S_IRUSR() -> uint { ret 0x0100u; }
fn S_IWUSR() -> uint { ret 0x0080u; }
}
fn O_BINARY() -> int {
ret 0; // nonexistent in linux libc
}
fn S_IRUSR() -> uint { ret 256u; }
fn S_IWUSR() -> uint { ret 128u; }
}
fn exec_suffix() -> str {
ret "";
}
fn exec_suffix() -> str { ret ""; }
fn target_os() -> str {
ret "linux";
}
fn target_os() -> str { ret "linux"; }
fn dylib_filename(str base) -> str {
ret "lib" + base + ".so";
}
fn dylib_filename(str base) -> str { ret "lib" + base + ".so"; }
fn pipe() -> tup(int, int) {
let vec[mutable int] fds = [mutable 0, 0];
@ -70,16 +65,13 @@ fn pipe() -> tup(int, int) {
ret tup(fds.(0), fds.(1));
}
fn fd_FILE(int fd) -> libc::FILE {
ret libc::fdopen(fd, str::buf("r"));
}
fn fd_FILE(int fd) -> libc::FILE { ret libc::fdopen(fd, str::buf("r")); }
fn waitpid(int pid) -> int {
let vec[mutable int] status = [mutable 0];
assert (os::libc::waitpid(pid, vec::buf(status), 0) != -1);
ret status.(0);
}
// Local Variables:
// mode: rust;
// fill-column: 78;

View File

@ -1,102 +1,74 @@
import option::some;
import option::none;
// FIXME: It would probably be more appealing to define this as
// type list[T] = rec(T hd, option[@list[T]] tl), but at the moment
// our recursion rules do not permit that.
tag list[T] {
cons(T, @list[T]);
nil;
}
tag list[T] { cons(T, @list[T]); nil; }
fn from_vec[T](vec[T] v) -> list[T] {
auto l = nil[T];
// FIXME: This would be faster and more space efficient if it looped over
// a reverse vector iterator. Unfortunately generic iterators seem not to
// work yet.
for (T item in vec::reversed(v)) {
l = cons[T](item, @l);
}
for (T item in vec::reversed(v)) { l = cons[T](item, @l); }
ret l;
}
fn foldl[T,U](&list[T] ls, &U u, fn(&T t, &U u) -> U f) -> U {
alt(ls) {
fn foldl[T, U](&list[T] ls, &U u, fn(&T, &U) -> U f) -> U {
alt (ls) {
case (cons(?hd, ?tl)) {
auto u_ = f(hd, u);
be foldl[T,U](*tl, u_, f);
}
case (nil) {
ret u;
be foldl[T, U](*tl, u_, f);
}
case (nil) { ret u; }
}
}
fn find[T,U](&list[T] ls,
(fn(&T) -> option::t[U]) f) -> option::t[U] {
alt(ls) {
fn find[T, U](&list[T] ls, fn(&T) -> option::t[U] f) -> option::t[U] {
alt (ls) {
case (cons(?hd, ?tl)) {
alt (f(hd)) {
case (none) {
be find[T,U](*tl, f);
}
case (some(?res)) {
ret some[U](res);
}
case (none) { be find[T, U](*tl, f); }
case (some(?res)) { ret some[U](res); }
}
}
case (nil) {
ret none[U];
}
case (nil) { ret none[U]; }
}
}
fn has[T](&list[T] ls, &T elt) -> bool {
alt(ls) {
alt (ls) {
case (cons(?hd, ?tl)) {
if (elt == hd) {
ret true;
} else {
be has(*tl, elt);
}
if (elt == hd) { ret true; } else { be has(*tl, elt); }
}
case (nil) { ret false; }
}
}
fn length[T](&list[T] ls) -> uint {
fn count[T](&T t, &uint u) -> uint {
ret u + 1u;
}
ret foldl[T,uint](ls, 0u, bind count[T](_, _));
fn count[T](&T t, &uint u) -> uint { ret u + 1u; }
ret foldl[T, uint](ls, 0u, bind count[T](_, _));
}
fn cdr[T](&list[T] ls) -> list[T] {
alt (ls) {
case (cons(_, ?tl)) {ret *tl;}
}
}
fn car[T](&list[T] ls) -> T {
alt (ls) {
case (cons(?hd, _)) {ret hd;}
}
alt (ls) { case (cons(_, ?tl)) { ret *tl; } }
}
fn car[T](&list[T] ls) -> T { alt (ls) { case (cons(?hd, _)) { ret hd; } } }
fn append[T](&list[T] l, &list[T] m) -> list[T] {
alt (l) {
case (nil) {
ret m;
}
case (nil) { ret m; }
case (cons(?x, ?xs)) {
let list[T] rest = append[T](*xs, m);
ret cons[T](x, @rest);
}
}
}
// Local Variables:
// mode: rust;
// fill-column: 78;

View File

@ -1,13 +1,12 @@
import str::sbuf;
import vec::vbuf;
native mod libc = "libc.dylib" {
native "cdecl" mod libc {
fn open(sbuf s, int flags, uint mode) -> int;
fn read(int fd, vbuf buf, uint count) -> int;
fn write(int fd, vbuf buf, uint count) -> int;
fn close(int fd) -> int;
type FILE;
fn fopen(sbuf path, sbuf mode) -> FILE;
fn fdopen(int fd, sbuf mode) -> FILE;
@ -19,47 +18,43 @@ native mod libc = "libc.dylib" {
fn fwrite(vbuf buf, uint size, uint n, FILE f) -> uint;
fn fseek(FILE f, int offset, int whence) -> int;
fn ftell(FILE f) -> int;
type dir;
fn opendir(sbuf d) -> dir;
fn closedir(dir d) -> int;
type dirent;
fn readdir(dir d) -> dirent;
fn getenv(sbuf n) -> sbuf;
fn setenv(sbuf n, sbuf v, int overwrite) -> int;
fn unsetenv(sbuf n) -> int;
fn pipe(vbuf buf) -> int;
fn waitpid(int pid, vbuf status, int options) -> int;
}
mod libc_constants {
fn O_RDONLY() -> int { ret 0x0000; }
fn O_WRONLY() -> int { ret 0x0001; }
fn O_RDWR() -> int { ret 0x0002; }
fn O_APPEND() -> int { ret 0x0008; }
fn O_CREAT() -> int { ret 0x0200; }
fn O_EXCL() -> int { ret 0x0800; }
fn O_TRUNC() -> int { ret 0x0400; }
fn O_TEXT() -> int { ret 0x0000; } // nonexistent in darwin libc
fn O_BINARY() -> int { ret 0x0000; } // nonexistent in darwin libc
fn O_RDONLY() -> int { ret 0; }
fn O_WRONLY() -> int { ret 1; }
fn O_RDWR() -> int { ret 2; }
fn O_APPEND() -> int { ret 8; }
fn O_CREAT() -> int { ret 512; }
fn O_EXCL() -> int { ret 2048; }
fn O_TRUNC() -> int { ret 1024; }
fn O_TEXT() -> int {
ret 0; // nonexistent in darwin libc
fn S_IRUSR() -> uint { ret 0x0400u; }
fn S_IWUSR() -> uint { ret 0x0200u; }
}
fn O_BINARY() -> int {
ret 0; // nonexistent in darwin libc
}
fn S_IRUSR() -> uint { ret 1024u; }
fn S_IWUSR() -> uint { ret 512u; }
}
fn exec_suffix() -> str {
ret "";
}
fn exec_suffix() -> str { ret ""; }
fn target_os() -> str {
ret "macos";
}
fn target_os() -> str { ret "macos"; }
fn dylib_filename(str base) -> str {
ret "lib" + base + ".dylib";
}
fn dylib_filename(str base) -> str { ret "lib" + base + ".dylib"; }
fn pipe() -> tup(int, int) {
let vec[mutable int] fds = [mutable 0, 0];
@ -67,16 +62,13 @@ fn pipe() -> tup(int, int) {
ret tup(fds.(0), fds.(1));
}
fn fd_FILE(int fd) -> libc::FILE {
ret libc::fdopen(fd, str::buf("r"));
}
fn fd_FILE(int fd) -> libc::FILE { ret libc::fdopen(fd, str::buf("r")); }
fn waitpid(int pid) -> int {
let vec[mutable int] status = [mutable 0];
assert (os::libc::waitpid(pid, vec::buf(status), 0) != -1);
ret status.(0);
}
// Local Variables:
// mode: rust;
// fill-column: 78;

View File

@ -1,37 +1,34 @@
/**
* At the moment, this is a partial hashmap implementation, not yet fit for
* use, but useful as a stress test for rustboot.
*/
type hashfn[K] = fn(&K) -> uint ;
type hashfn[K] = fn(&K) -> uint;
type eqfn[K] = fn(&K, &K) -> bool;
type eqfn[K] = fn(&K, &K) -> bool ;
state type hashmap[K, V] = state obj {
fn size() -> uint;
fn insert(&K key, &V val) -> bool;
fn contains_key(&K key) -> bool;
fn get(&K key) -> V;
fn find(&K key) -> option::t[V];
fn remove(&K key) -> option::t[V];
fn rehash();
iter items() -> @tup(K,V);
};
type hashmap[K, V] =
obj {
fn size() -> uint ;
fn insert(&K, &V) -> bool ;
fn contains_key(&K) -> bool ;
fn get(&K) -> V ;
fn find(&K) -> option::t[V] ;
fn remove(&K) -> option::t[V] ;
fn rehash() ;
iter items() -> @tup(K, V) ;
};
fn mk_hashmap[K, V](&hashfn[K] hasher, &eqfn[K] eqer) -> hashmap[K, V] {
let uint initial_capacity = 32u; // 2^5
let util::rational load_factor = rec(num=3, den=4);
tag bucket[K, V] {
nil;
deleted;
some(K, V);
}
tag bucket[K, V] { nil; deleted; some(K, V); }
fn make_buckets[K, V](uint nbkts) -> vec[mutable bucket[K, V]] {
ret vec::init_elt_mut[bucket[K, V]](nil[K, V], nbkts);
}
// Derive two hash functions from the one given by taking the upper
// half and lower half of the uint bits. Our bucket probing
// sequence is then defined by
@ -46,199 +43,159 @@ fn mk_hashmap[K, V](&hashfn[K] hasher, &eqfn[K] eqer) -> hashmap[K, V] {
// is always a power of 2), so that all buckets are probed for a
// fixed key.
fn hashl(uint n, uint nbkts) -> uint {
ret ((n >>> 16u) * 2u + 1u);
}
fn hashr(uint n, uint nbkts) -> uint {
ret (0x0000_ffff_u & n);
}
fn hashl(uint n, uint nbkts) -> uint { ret (n >>> 16u) * 2u + 1u; }
fn hashr(uint n, uint nbkts) -> uint { ret 0x0000_ffff_u & n; }
fn hash(uint h, uint nbkts, uint i) -> uint {
ret (hashl(h, nbkts) * i + hashr(h, nbkts)) % nbkts;
}
/**
* We attempt to never call this with a full table. If we do, it
* will fail.
*/
fn insert_common[K, V](&hashfn[K] hasher,
&eqfn[K] eqer,
vec[mutable bucket[K, V]] bkts,
uint nbkts,
&K key,
&V val)
-> bool
{
fn insert_common[K,
V](&hashfn[K] hasher, &eqfn[K] eqer,
vec[mutable bucket[K, V]] bkts, uint nbkts, &K key,
&V val) -> bool {
let uint i = 0u;
let uint h = hasher(key);
while (i < nbkts) {
let uint j = hash(h, nbkts, i);
alt (bkts.(j)) {
case (some(?k, _)) {
// Copy key to please alias analysis.
auto k_ = k;
if (eqer(key, k_)) {
bkts.(j) = some[K, V](k_, val);
ret false;
}
i += 1u;
}
case (_) { bkts.(j) = some[K, V](key, val); ret true; }
}
}
fail; // full table
}
fn find_common[K,
V](&hashfn[K] hasher, &eqfn[K] eqer,
vec[mutable bucket[K, V]] bkts, uint nbkts, &K key) ->
option::t[V] {
let uint i = 0u;
let uint h = hasher(key);
while (i < nbkts) {
let uint j = hash(h, nbkts, i);
alt (bkts.(j)) {
case (some(?k, ?v)) {
// Copy to please alias analysis.
auto k_ = k;
auto v_ = v;
if (eqer(key, k_)) { ret option::some[V](v_); }
}
case (nil) { ret option::none[V]; }
case (deleted[K, V]) { }
}
i += 1u;
}
ret option::none[V];
}
fn rehash[K,
V](&hashfn[K] hasher, &eqfn[K] eqer,
vec[mutable bucket[K, V]] oldbkts, uint noldbkts,
vec[mutable bucket[K, V]] newbkts, uint nnewbkts) {
for (bucket[K, V] b in oldbkts) {
alt (b) {
case (some(?k_, ?v_)) {
auto k = k_;
auto v = v_;
insert_common[K,
V](hasher, eqer, newbkts, nnewbkts, k, v);
}
case (_) { }
}
}
}
obj hashmap[K,
V](hashfn[K] hasher,
eqfn[K] eqer,
mutable vec[mutable bucket[K, V]] bkts,
mutable uint nbkts,
mutable uint nelts,
util::rational lf) {
fn size() -> uint { ret nelts; }
fn insert(&K key, &V val) -> bool {
let util::rational load =
rec(num=nelts + 1u as int, den=nbkts as int);
if (!util::rational_leq(load, lf)) {
let uint nnewbkts = uint::next_power_of_two(nbkts + 1u);
let vec[mutable bucket[K, V]] newbkts =
make_buckets[K, V](nnewbkts);
rehash[K, V](hasher, eqer, bkts, nbkts, newbkts, nnewbkts);
bkts = newbkts;
nbkts = nnewbkts;
}
if (insert_common[K, V](hasher, eqer, bkts, nbkts, key, val)) {
nelts += 1u;
ret true;
}
ret false;
}
fn contains_key(&K key) -> bool {
ret alt (find_common[K, V](hasher, eqer, bkts, nbkts, key)) {
case (option::some(_)) { true }
case (_) { false }
};
}
fn get(&K key) -> V {
ret alt (find_common[K, V](hasher, eqer, bkts, nbkts, key)) {
case (option::some(?val)) { val }
case (_) { fail }
};
}
fn find(&K key) -> option::t[V] {
be find_common[K, V](hasher, eqer, bkts, nbkts, key);
}
fn remove(&K key) -> option::t[V] {
let uint i = 0u;
let uint h = hasher(key);
while (i < nbkts) {
let uint j = hash(h, nbkts, i);
alt (bkts.(j)) {
case (some(?k, _)) {
// Copy key to please alias analysis.
auto k_ = k;
if (eqer(key, k_)) {
bkts.(j) = some[K, V](k_, val);
ret false;
}
i += 1u;
}
case (_) {
bkts.(j) = some[K, V](key, val);
ret true;
}
}
}
fail; // full table
}
fn find_common[K, V](&hashfn[K] hasher,
&eqfn[K] eqer,
vec[mutable bucket[K, V]] bkts,
uint nbkts,
&K key)
-> option::t[V]
{
let uint i = 0u;
let uint h = hasher(key);
while (i < nbkts) {
let uint j = (hash(h, nbkts, i));
alt (bkts.(j)) {
case (some(?k, ?v)) {
// Copy to please alias analysis.
auto k_ = k;
auto v_ = v;
auto vo = option::some(v);
if (eqer(key, k_)) {
ret option::some[V](v_);
bkts.(j) = deleted[K, V];
nelts -= 1u;
ret vo;
}
}
case (nil) {
ret option::none[V];
}
case (deleted[K, V]) { }
case (deleted) { }
case (nil) { ret option::none[V]; }
}
i += 1u;
}
ret option::none[V];
}
fn rehash[K, V](&hashfn[K] hasher,
&eqfn[K] eqer,
vec[mutable bucket[K, V]] oldbkts, uint noldbkts,
vec[mutable bucket[K, V]] newbkts, uint nnewbkts)
{
for (bucket[K, V] b in oldbkts) {
fn rehash() {
let vec[mutable bucket[K, V]] newbkts = make_buckets[K, V](nbkts);
rehash[K, V](hasher, eqer, bkts, nbkts, newbkts, nbkts);
bkts = newbkts;
}
iter items() -> @tup(K, V) {
for (bucket[K, V] b in bkts) {
alt (b) {
case (some(?k_, ?v_)) {
auto k = k_; auto v = v_;
insert_common[K, V](hasher, eqer, newbkts,
nnewbkts, k, v);
}
case (some(?k, ?v)) { put @tup(k, v); }
case (_) { }
}
}
}
state obj hashmap[K, V](hashfn[K] hasher,
eqfn[K] eqer,
mutable vec[mutable bucket[K, V]] bkts,
mutable uint nbkts,
mutable uint nelts,
util::rational lf)
{
fn size() -> uint { ret nelts; }
fn insert(&K key, &V val) -> bool {
let util::rational load = rec(num=(nelts + 1u) as int,
den=nbkts as int);
if (!util::rational_leq(load, lf)) {
let uint nnewbkts = uint::next_power_of_two(nbkts + 1u);
let vec[mutable bucket[K, V]] newbkts =
make_buckets[K, V](nnewbkts);
rehash[K, V](hasher, eqer, bkts, nbkts,
newbkts, nnewbkts);
bkts = newbkts;
nbkts = nnewbkts;
}
if (insert_common[K, V](hasher, eqer, bkts,
nbkts, key, val)) {
nelts += 1u;
ret true;
}
ret false;
}
fn contains_key(&K key) -> bool {
ret alt (find_common[K, V](hasher, eqer, bkts, nbkts, key)) {
case (option::some(_)) { true }
case (_) { false }
};
}
fn get(&K key) -> V {
ret alt (find_common[K, V](hasher, eqer, bkts, nbkts, key)) {
case (option::some(?val)) { val }
case (_) { fail }
};
}
fn find(&K key) -> option::t[V] {
be find_common[K, V](hasher, eqer, bkts, nbkts, key);
}
fn remove(&K key) -> option::t[V] {
let uint i = 0u;
let uint h = hasher(key);
while (i < nbkts) {
let uint j = (hash(h, nbkts, i));
alt (bkts.(j)) {
case (some(?k, ?v)) {
auto k_ = k; auto vo = option::some(v);
if (eqer(key, k_)) {
bkts.(j) = deleted[K, V];
nelts -= 1u;
ret vo;
}
}
case (deleted) { }
case (nil) {
ret option::none[V];
}
}
i += 1u;
}
ret option::none[V];
}
fn rehash() {
let vec[mutable bucket[K, V]] newbkts =
make_buckets[K, V](nbkts);
rehash[K, V](hasher, eqer, bkts, nbkts, newbkts, nbkts);
bkts = newbkts;
}
iter items() -> @tup(K,V) {
for (bucket[K,V] b in bkts) {
alt (b) {
case(some(?k,?v)) {
put @tup(k,v);
}
case (_) { }
}
}
}
}
let vec[mutable bucket[K, V]] bkts =
make_buckets[K, V](initial_capacity);
}
let vec[mutable bucket[K, V]] bkts = make_buckets[K, V](initial_capacity);
ret hashmap[K, V](hasher, eqer, bkts, initial_capacity, 0u, load_factor);
}
// Local Variables:
// mode: rust;
// fill-column: 78;

View File

@ -1,39 +1,24 @@
// lib/option::rs
tag t[T] { none; some(T); }
tag t[T] {
none;
some(T);
}
type operator[T, U] = fn(&T) -> U;
type operator[T, U] = fn(&T) -> U ;
fn get[T](&t[T] opt) -> T {
ret alt (opt) {
case (some(?x)) {
x
}
case (none) {
fail
}
};
ret alt (opt) { case (some(?x)) { x } case (none) { fail } };
}
fn map[T, U](&operator[T, U] f, &t[T] opt) -> t[U] {
ret alt (opt) {
case (some(?x)) {
some[U](f(x))
}
case (none) {
none[U]
}
};
case (some(?x)) { some[U](f(x)) }
case (none) { none[U] }
};
}
fn is_none[T](&t[T] opt) -> bool {
ret alt (opt) {
case (none) { true }
case (some(_)) { false }
};
ret alt (opt) { case (none) { true } case (some(_)) { false } };
}
fn from_maybe[T](&T def, &t[T] opt) -> T {
@ -41,21 +26,15 @@ fn from_maybe[T](&T def, &t[T] opt) -> T {
ret maybe[T, T](def, f, opt);
}
fn maybe[T, U](&U def, fn(&T) -> U f, &t[T] opt) -> U {
ret alt (opt) {
case (none) { def }
case (some(?t)) { f(t) }
};
fn maybe[T, U](&U def, fn(&T) -> U f, &t[T] opt) -> U {
ret alt (opt) { case (none) { def } case (some(?t)) { f(t) } };
}
// Can be defined in terms of the above when/if we have const bind.
fn may[T](fn(&T) f, &t[T] opt) {
alt (opt) {
case (none) { /* nothing */ }
case (some(?t)) { f(t); }
}
fn may[T](fn(&T) f, &t[T] opt) {
alt (opt) { case (none) {/* nothing */ } case (some(?t)) { f(t); } }
}
// Local Variables:
// mode: rust;
// fill-column: 78;
@ -64,4 +43,3 @@ fn may[T](fn(&T) f, &t[T] opt) {
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:

View File

@ -1,38 +1,41 @@
native "rust" mod rustrt {
fn rust_list_files(str path) -> vec[str];
fn rust_dirent_filename(os::libc::dirent ent) -> str;
fn rust_list_files(str path) -> vec[str];
fn rust_dirent_filename(os::libc::dirent ent) -> str;
}
fn list_dir(str path) -> vec[str] {
ret rustrt::rust_list_files(path);
// TODO ensure this is always closed
ret rustrt::rust_list_files(path);
// TODO ensure this is always closed
// FIXME: No idea why, but this appears to corrupt memory on OSX. I suspect
// it has to do with the tasking primitives somehow, or perhaps the
// FFI. Worth investigating more when we're digging into the FFI and unsafe
// mode in more detail; in the meantime we just call list_files above and
// skip this code.
// FIXME: No idea why, but this appears to corrupt memory on OSX. I
// suspect it has to do with the tasking primitives somehow, or perhaps
// the FFI. Worth investigating more when we're digging into the FFI and
// unsafe mode in more detail; in the meantime we just call list_files
// above and skip this code.
/*
auto dir = os::libc::opendir(str::buf(path));
assert (dir as uint != 0u);
let vec[str] result = [];
while (true) {
auto ent = os::libc::readdir(dir);
if (ent as int == 0) {
os::libc::closedir(dir);
ret result;
}
vec::push[str](result, rustrt::rust_dirent_filename(ent));
}
os::libc::closedir(dir);
ret result;
*/
/*
auto dir = os::libc::opendir(str::buf(path));
assert (dir as uint != 0u);
let vec[str] result = [];
while (true) {
auto ent = os::libc::readdir(dir);
if (ent as int == 0) {
os::libc::closedir(dir);
ret result;
}
vec::push[str](result, rustrt::rust_dirent_filename(ent));
}
os::libc::closedir(dir);
ret result;
*/
}
const char path_sep = '/';
const char alt_path_sep = '/';
const char alt_path_sep = '/';
// Local Variables:
// mode: rust;
// fill-column: 78;

View File

@ -1,7 +1,9 @@
/**
* Bindings the runtime's random number generator (ISAAC).
*/
native "rust" mod rustrt {
type rctx;
fn rand_new() -> rctx;
@ -9,21 +11,19 @@ native "rust" mod rustrt {
fn rand_free(rctx c);
}
type rng = obj { fn next() -> u32; };
type rng =
obj {
fn next() -> u32 ;
};
fn mk_rng() -> rng {
obj rt_rng(rustrt::rctx c) {
fn next() -> u32 {
ret rustrt::rand_next(c);
}
drop {
rustrt::rand_free(c);
}
}drop { rustrt::rand_free(c); }
}
ret rt_rng(rustrt::rand_new());
}
// Local Variables:
// mode: rust;
// fill-column: 78;

View File

@ -1,3 +1,4 @@
import str::sbuf;
import vec::vbuf;
@ -7,73 +8,62 @@ native "rust" mod rustrt {
fn arg_vec(str prog, vec[str] args) -> vec[sbuf] {
auto argptrs = [str::buf(prog)];
for (str arg in args) {
vec::push[sbuf](argptrs, str::buf(arg));
}
for (str arg in args) { vec::push[sbuf](argptrs, str::buf(arg)); }
vec::push[sbuf](argptrs, 0 as sbuf);
ret argptrs;
}
fn run_program(str prog, vec[str] args) -> int {
auto pid = rustrt::rust_run_program(vec::buf[sbuf](arg_vec(prog, args)),
0, 0, 0);
auto pid =
rustrt::rust_run_program(vec::buf[sbuf](arg_vec(prog, args)), 0, 0,
0);
ret os::waitpid(pid);
}
type program =
state obj {
fn get_id() -> int;
fn input() -> io::writer;
fn output() -> io::reader;
fn close_input();
fn finish() -> int;
obj {
fn get_id() -> int ;
fn input() -> io::writer ;
fn output() -> io::reader ;
fn close_input() ;
fn finish() -> int ;
};
fn start_program(str prog, vec[str] args) -> @program {
auto pipe_input = os::pipe();
auto pipe_output = os::pipe();
auto pid = rustrt::rust_run_program
(vec::buf[sbuf](arg_vec(prog, args)),
pipe_input._0, pipe_output._1, 0);
if (pid == -1) {fail;}
auto pid =
rustrt::rust_run_program(vec::buf[sbuf](arg_vec(prog, args)),
pipe_input._0, pipe_output._1, 0);
if (pid == -1) { fail; }
os::libc::close(pipe_input._0);
os::libc::close(pipe_output._1);
state obj new_program(int pid,
int in_fd,
os::libc::FILE out_file,
mutable bool finished) {
fn get_id() -> int {ret pid;}
obj new_program(int pid,
int in_fd,
os::libc::FILE out_file,
mutable bool finished) {
fn get_id() -> int { ret pid; }
fn input() -> io::writer {
ret io::new_writer(io::fd_buf_writer(in_fd, false));
}
fn output() -> io::reader {
ret io::new_reader(io::FILE_buf_reader(out_file, false));
}
fn close_input() {
os::libc::close(in_fd);
}
fn close_input() { os::libc::close(in_fd); }
fn finish() -> int {
if (finished) {ret 0;}
if (finished) { ret 0; }
finished = true;
os::libc::close(in_fd);
ret os::waitpid(pid);
}
drop {
if (!finished) {
os::libc::close(in_fd);
os::waitpid(pid);
}
os::libc::fclose(out_file);
}
}drop {
if (!finished) { os::libc::close(in_fd); os::waitpid(pid); }
os::libc::fclose(out_file);
}
}
ret @new_program(pid, pipe_input._1,
os::fd_FILE(pipe_output._0),
false);
ret @new_program(pid, pipe_input._1, os::fd_FILE(pipe_output._0), false);
}
fn program_output(str prog, vec[str] args)
-> rec(int status, str out) {
fn program_output(str prog, vec[str] args) -> rec(int status, str out) {
auto pr = start_program(prog, args);
pr.close_input();
auto out = pr.output();
@ -84,8 +74,6 @@ fn program_output(str prog, vec[str] args)
}
ret rec(status=pr.finish(), out=buf);
}
// Local Variables:
// mode: rust
// fill-column: 78;

View File

@ -1,116 +1,119 @@
/*
* A SHA-1 implementation derived from Paul E. Jones's reference
* implementation, which is written for clarity, not speed. At some
* point this will want to be rewritten.
*/
export sha1;
export mk_sha1;
state type sha1 = state obj {
// Provide message input as bytes
fn input(&vec[u8]);
type sha1 =
obj {
// Provide message input as string
fn input_str(&str);
// Provide message input as bytes
fn input(&vec[u8]) ;
// Read the digest as a vector of 20 bytes. After
// calling this no further input may provided
// until reset is called
fn result() -> vec[u8];
// Provide message input as string
fn input_str(&str) ;
// Same as above, just a hex-string version.
fn result_str() -> str;
// Read the digest as a vector of 20 bytes. After
// calling this no further input may provided
// until reset is called
fn result() -> vec[u8] ;
// Same as above, just a hex-string version.
fn result_str() -> str ;
// Reset the sha1 state for reuse. This is called
// automatically during construction
fn reset() ;
};
// Reset the sha1 state for reuse. This is called
// automatically during construction
fn reset();
};
// Some unexported constants
const uint digest_buf_len = 5u;
const uint msg_block_len = 64u;
const uint work_buf_len = 80u;
const u32 k0 = 0x5A827999u32;
const u32 k1 = 0x6ED9EBA1u32;
const u32 k2 = 0x8F1BBCDCu32;
const u32 k3 = 0xCA62C1D6u32;
// Builds a sha1 object
fn mk_sha1() -> sha1 {
state type sha1state = rec(vec[mutable u32] h,
mutable u32 len_low,
mutable u32 len_high,
vec[mutable u8] msg_block,
mutable uint msg_block_idx,
mutable bool computed,
vec[mutable u32] work_buf);
type sha1state =
rec(vec[mutable u32] h,
mutable u32 len_low,
mutable u32 len_high,
vec[mutable u8] msg_block,
mutable uint msg_block_idx,
mutable bool computed,
vec[mutable u32] work_buf);
fn add_input(&sha1state st, &vec[u8] msg) {
// FIXME: Should be typestate precondition
assert (!st.computed);
assert (!st.computed);
for (u8 element in msg) {
st.msg_block.(st.msg_block_idx) = element;
st.msg_block_idx += 1u;
st.len_low += 8u32;
if (st.len_low == 0u32) {
st.len_high += 1u32;
if (st.len_high == 0u32) {
// FIXME: Need better failure mode
fail;
}
}
if (st.msg_block_idx == msg_block_len) {
process_msg_block(st);
}
if (st.msg_block_idx == msg_block_len) { process_msg_block(st); }
}
}
fn process_msg_block(&sha1state st) {
// FIXME: Make precondition
assert (vec::len(st.h) == digest_buf_len);
assert (vec::len(st.work_buf) == work_buf_len);
let int t; // Loop counter
auto w = st.work_buf;
auto w = st.work_buf;
// Initialize the first 16 words of the vector w
t = 0;
while (t < 16) {
auto tmp;
tmp = (st.msg_block.(t * 4) as u32) << 24u32;
tmp = tmp | ((st.msg_block.(t * 4 + 1) as u32) << 16u32);
tmp = tmp | ((st.msg_block.(t * 4 + 2) as u32) << 8u32);
tmp = tmp | (st.msg_block.(t * 4 + 1) as u32) << 16u32;
tmp = tmp | (st.msg_block.(t * 4 + 2) as u32) << 8u32;
tmp = tmp | (st.msg_block.(t * 4 + 3) as u32);
w.(t) = tmp;
t += 1;
}
// Initialize the rest of vector w
while (t < 80) {
auto val = w.(t-3) ^ w.(t-8) ^ w.(t-14) ^ w.(t-16);
auto val = w.(t - 3) ^ w.(t - 8) ^ w.(t - 14) ^ w.(t - 16);
w.(t) = circular_shift(1u32, val);
t += 1;
}
auto a = st.h.(0);
auto b = st.h.(1);
auto c = st.h.(2);
auto d = st.h.(3);
auto e = st.h.(4);
let u32 temp;
t = 0;
while (t < 20) {
temp = circular_shift(5u32, a)
+ ((b & c) | ((!b) & d)) + e + w.(t) + k0;
temp =
circular_shift(5u32, a) + (b & c | !b & d) + e + w.(t) + k0;
e = d;
d = c;
c = circular_shift(30u32, b);
@ -118,10 +121,8 @@ fn mk_sha1() -> sha1 {
a = temp;
t += 1;
}
while (t < 40) {
temp = circular_shift(5u32, a)
+ (b ^ c ^ d) + e + w.(t) + k1;
temp = circular_shift(5u32, a) + (b ^ c ^ d) + e + w.(t) + k1;
e = d;
d = c;
c = circular_shift(30u32, b);
@ -129,10 +130,10 @@ fn mk_sha1() -> sha1 {
a = temp;
t += 1;
}
while (t < 60) {
temp = circular_shift(5u32, a)
+ ((b & c) | (b & d) | (c & d)) + e + w.(t) + k2;
temp =
circular_shift(5u32, a) + (b & c | b & d | c & d) + e + w.(t)
+ k2;
e = d;
d = c;
c = circular_shift(30u32, b);
@ -140,10 +141,8 @@ fn mk_sha1() -> sha1 {
a = temp;
t += 1;
}
while (t < 80) {
temp = circular_shift(5u32, a)
+ (b ^ c ^ d) + e + w.(t) + k3;
temp = circular_shift(5u32, a) + (b ^ c ^ d) + e + w.(t) + k3;
e = d;
d = c;
c = circular_shift(30u32, b);
@ -151,40 +150,32 @@ fn mk_sha1() -> sha1 {
a = temp;
t += 1;
}
st.h.(0) = st.h.(0) + a;
st.h.(1) = st.h.(1) + b;
st.h.(2) = st.h.(2) + c;
st.h.(3) = st.h.(3) + d;
st.h.(4) = st.h.(4) + e;
st.msg_block_idx = 0u;
}
fn circular_shift(u32 bits, u32 word) -> u32 {
// FIXME: This is a workaround for a rustboot
// "unrecognized quads" codegen bug
auto bits_hack = bits;
ret (word << bits_hack) | (word >> (32u32 - bits));
ret word << bits_hack | word >> 32u32 - bits;
}
fn mk_result(&sha1state st) -> vec[u8] {
if (!st.computed) {
pad_msg(st);
st.computed = true;
}
if (!st.computed) { pad_msg(st); st.computed = true; }
let vec[u8] res = [];
for (u32 hpart in st.h) {
auto a = (hpart >> 24u32) & 0xFFu32 as u8;
auto b = (hpart >> 16u32) & 0xFFu32 as u8;
auto c = (hpart >> 8u32) & 0xFFu32 as u8;
auto d = (hpart & 0xFFu32 as u8);
res += [a,b,c,d];
auto a = hpart >> 24u32 & 0xFFu32 as u8;
auto b = hpart >> 16u32 & 0xFFu32 as u8;
auto c = hpart >> 8u32 & 0xFFu32 as u8;
auto d = hpart & 0xFFu32 as u8;
res += [a, b, c, d];
}
ret res;
}
/*
* According to the standard, the message must be padded to an even
* 512 bits. The first padding bit must be a '1'. The last 64 bits
@ -194,101 +185,82 @@ fn mk_sha1() -> sha1 {
* call process_msg_block() appropriately. When it returns, it
* can be assumed that the message digest has been computed.
*/
fn pad_msg(&sha1state st) {
// FIXME: Should be a precondition
assert (vec::len(st.msg_block) == msg_block_len);
assert (vec::len(st.msg_block) == msg_block_len);
/*
* Check to see if the current message block is too small to hold
* the initial padding bits and length. If so, we will pad the
* block, process it, and then continue padding into a second block.
*/
if (st.msg_block_idx > 55u) {
st.msg_block.(st.msg_block_idx) = 0x80u8;
st.msg_block_idx += 1u;
while (st.msg_block_idx < msg_block_len) {
st.msg_block.(st.msg_block_idx) = 0u8;
st.msg_block_idx += 1u;
}
process_msg_block(st);
} else {
st.msg_block.(st.msg_block_idx) = 0x80u8;
st.msg_block_idx += 1u;
}
while (st.msg_block_idx < 56u) {
st.msg_block.(st.msg_block_idx) = 0u8;
st.msg_block_idx += 1u;
}
// Store the message length as the last 8 octets
st.msg_block.(56) = (st.len_high >> 24u32) & 0xFFu32 as u8;
st.msg_block.(57) = (st.len_high >> 16u32) & 0xFFu32 as u8;
st.msg_block.(58) = (st.len_high >> 8u32) & 0xFFu32 as u8;
st.msg_block.(59) = st.len_high & 0xFFu32 as u8;
st.msg_block.(60) = (st.len_low >> 24u32) & 0xFFu32 as u8;
st.msg_block.(61) = (st.len_low >> 16u32) & 0xFFu32 as u8;
st.msg_block.(62) = (st.len_low >> 8u32) & 0xFFu32 as u8;
st.msg_block.(63) = st.len_low & 0xFFu32 as u8;
st.msg_block.(56) = st.len_high >> 24u32 & 0xFFu32 as u8;
st.msg_block.(57) = st.len_high >> 16u32 & 0xFFu32 as u8;
st.msg_block.(58) = st.len_high >> 8u32 & 0xFFu32 as u8;
st.msg_block.(59) = st.len_high & 0xFFu32 as u8;
st.msg_block.(60) = st.len_low >> 24u32 & 0xFFu32 as u8;
st.msg_block.(61) = st.len_low >> 16u32 & 0xFFu32 as u8;
st.msg_block.(62) = st.len_low >> 8u32 & 0xFFu32 as u8;
st.msg_block.(63) = st.len_low & 0xFFu32 as u8;
process_msg_block(st);
}
state obj sha1(sha1state st) {
obj sha1(sha1state st) {
fn reset() {
// FIXME: Should be typestate precondition
assert (vec::len(st.h) == digest_buf_len);
assert (vec::len(st.h) == digest_buf_len);
st.len_low = 0u32;
st.len_high = 0u32;
st.msg_block_idx = 0u;
st.h.(0) = 0x67452301u32;
st.h.(1) = 0xEFCDAB89u32;
st.h.(2) = 0x98BADCFEu32;
st.h.(3) = 0x10325476u32;
st.h.(4) = 0xC3D2E1F0u32;
st.computed = false;
}
fn input(&vec[u8] msg) {
add_input(st, msg);
}
fn input_str(&str msg) {
add_input(st, str::bytes(msg));
}
fn result() -> vec[u8] {
ret mk_result(st);
}
fn input(&vec[u8] msg) { add_input(st, msg); }
fn input_str(&str msg) { add_input(st, str::bytes(msg)); }
fn result() -> vec[u8] { ret mk_result(st); }
fn result_str() -> str {
auto r = mk_result(st);
auto s = "";
for (u8 b in r) {
s += uint::to_str(b as uint, 16u);
}
for (u8 b in r) { s += uint::to_str(b as uint, 16u); }
ret s;
}
}
auto st = rec(h = vec::init_elt_mut[u32](0u32, digest_buf_len),
mutable len_low = 0u32,
mutable len_high = 0u32,
msg_block = vec::init_elt_mut[u8](0u8, msg_block_len),
mutable msg_block_idx = 0u,
mutable computed = false,
work_buf = vec::init_elt_mut[u32](0u32, work_buf_len));
auto st =
rec(h=vec::init_elt_mut[u32](0u32, digest_buf_len),
mutable len_low=0u32,
mutable len_high=0u32,
msg_block=vec::init_elt_mut[u8](0u8, msg_block_len),
mutable msg_block_idx=0u,
mutable computed=false,
work_buf=vec::init_elt_mut[u32](0u32, work_buf_len));
auto sh = sha1(st);
sh.reset();
ret sh;
}
// Local Variables:
// mode: rust;
// fill-column: 78;

View File

@ -1,13 +1,14 @@
/// A simple map based on a vector for small integer keys. Space requirements
/// are O(highest integer key).
import option::none;
import option::some;
type smallintmap[T] = rec(mutable vec[mutable option::t[T]] v);
fn mk[T]() -> smallintmap[T] {
let vec[mutable option::t[T]] v = [mutable];
let vec[mutable option::t[T]] v = [mutable ];
ret rec(mutable v=v);
}
@ -38,7 +39,4 @@ fn truncate[T](&smallintmap[T] m, uint len) {
m.v = vec::slice_mut[option::t[T]](m.v, 0u, len);
}
fn max_key[T](&smallintmap[T] m) -> uint {
ret vec::len[option::t[T]](m.v);
}
fn max_key[T](&smallintmap[T] m) -> uint { ret vec::len[option::t[T]](m.v); }

View File

@ -1,15 +1,14 @@
import vec::len;
import vec::slice;
export lteq;
export merge_sort;
export quick_sort;
export quick_sort3;
type lteq[T] = fn(&T a, &T b) -> bool;
type lteq[T] = fn(&T, &T) -> bool ;
fn merge_sort[T](lteq[T] le, vec[T] v) -> vec[T] {
fn merge[T](lteq[T] le, vec[T] a, vec[T] b) -> vec[T] {
let vec[T] res = [];
let uint a_len = len[T](a);
@ -20,28 +19,18 @@ fn merge_sort[T](lteq[T] le, vec[T] v) -> vec[T] {
if (le(a.(a_ix), b.(b_ix))) {
res += [a.(a_ix)];
a_ix += 1u;
} else {
res += [b.(b_ix)];
b_ix += 1u;
}
} else { res += [b.(b_ix)]; b_ix += 1u; }
}
res += slice[T](a, a_ix, a_len);
res += slice[T](b, b_ix, b_len);
ret res;
}
let uint v_len = len[T](v);
if (v_len <= 1u) {
ret v;
}
if (v_len <= 1u) { ret v; }
let uint mid = v_len / 2u;
let vec[T] a = slice[T](v, 0u, mid);
let vec[T] b = slice[T](v, mid, v_len);
ret merge[T](le,
merge_sort[T](le, a),
merge_sort[T](le, b));
ret merge[T](le, merge_sort[T](le, a), merge_sort[T](le, b));
}
fn swap[T](vec[mutable T] arr, uint x, uint y) {
@ -50,17 +39,16 @@ fn swap[T](vec[mutable T] arr, uint x, uint y) {
arr.(y) = a;
}
fn part[T](lteq[T] compare_func, vec[mutable T] arr, uint left,
uint right, uint pivot) -> uint {
fn part[T](lteq[T] compare_func, vec[mutable T] arr, uint left, uint right,
uint pivot) -> uint {
auto pivot_value = arr.(pivot);
swap[T](arr, pivot, right);
let uint storage_index = left;
let uint i = left;
while (i<right) {
if (compare_func({arr.(i)}, pivot_value)) {
swap[T](arr, i, storage_index);
storage_index += 1u;
while (i < right) {
if (compare_func({ arr.(i) }, pivot_value)) {
swap[T](arr, i, storage_index);
storage_index += 1u;
}
i += 1u;
}
@ -68,26 +56,19 @@ fn part[T](lteq[T] compare_func, vec[mutable T] arr, uint left,
ret storage_index;
}
fn qsort[T](lteq[T] compare_func, vec[mutable T] arr, uint left,
uint right) {
fn qsort[T](lteq[T] compare_func, vec[mutable T] arr, uint left, uint right) {
if (right > left) {
auto pivot = (left+right)/2u;
auto pivot = (left + right) / 2u;
auto new_pivot = part[T](compare_func, arr, left, right, pivot);
if (new_pivot == 0u) {
ret;
}
if (new_pivot == 0u) { ret; }
qsort[T](compare_func, arr, left, new_pivot - 1u);
qsort[T](compare_func, arr, new_pivot + 1u, right);
}
}
fn quick_sort[T](lteq[T] compare_func, vec[mutable T] arr) {
if (len[T](arr) == 0u) {
ret;
}
qsort[T](compare_func, arr, 0u, (len[T](arr)) - 1u);
if (len[T](arr) == 0u) { ret; }
qsort[T](compare_func, arr, 0u, len[T](arr) - 1u);
}
@ -95,81 +76,60 @@ fn quick_sort[T](lteq[T] compare_func, vec[mutable T] arr) {
// http://www.cs.princeton.edu/~rs/talks/QuicksortIsOptimal.pdf
// According to these slides this is the algorithm of choice for
// 'randomly ordered keys, abstract compare' & 'small number of key values'
fn qsort3[T](lteq[T] compare_func_lt, lteq[T] compare_func_eq,
vec[mutable T] arr, int left, int right) {
if (right <= left) {
ret;
}
if (right <= left) { ret; }
let T v = arr.(right);
let int i = left - 1;
let int j = right;
let int p = i;
let int q = j;
while (true) {
i += 1;
while (compare_func_lt({arr.(i)}, v)) {
i += 1;
}
while (compare_func_lt({ arr.(i) }, v)) { i += 1; }
j -= 1;
while (compare_func_lt(v, {arr.(j)})) {
if (j == left) {
break;
}
while (compare_func_lt(v, { arr.(j) })) {
if (j == left) { break; }
j -= 1;
}
if (i >= j) {
break;
}
if (i >= j) { break; }
swap[T](arr, i as uint, j as uint);
if (compare_func_eq({arr.(i)}, v)) {
if (compare_func_eq({ arr.(i) }, v)) {
p += 1;
swap[T](arr, p as uint, i as uint);
}
if (compare_func_eq(v, {arr.(j)})) {
if (compare_func_eq(v, { arr.(j) })) {
q -= 1;
swap[T](arr, j as uint, q as uint);
}
}
}
swap[T](arr, i as uint, right as uint);
j = i - 1;
i += 1;
let int k = left;
while (k < p) {
swap[T](arr, k as uint, j as uint);
k += 1;
j -= 1;
if (k == vec::len[T](arr) as int) {
break;
}
if (k == vec::len[T](arr) as int) { break; }
}
k = right - 1;
while (k > q) {
swap[T](arr, i as uint, k as uint);
k -= 1;
i += 1;
if (k == 0) {
break;
}
if (k == 0) { break; }
}
qsort3[T](compare_func_lt, compare_func_eq, arr, left, j);
qsort3[T](compare_func_lt, compare_func_eq, arr, i, right);
}
fn quick_sort3[T](lteq[T] compare_func_lt, lteq[T] compare_func_eq,
vec[mutable T] arr) {
if (vec::len[T](arr) == 0u) {
ret;
}
vec[mutable T] arr) {
if (vec::len[T](arr) == 0u) { ret; }
qsort3[T](compare_func_lt, compare_func_eq, arr, 0,
(vec::len[T](arr) as int) - 1);
}
// Local Variables:
// mode: rust;
// fill-column: 78;

View File

@ -1,7 +1,6 @@
import rustrt::sbuf;
import vec::rustrt::vbuf;
export sbuf;
export rustrt;
export eq;
@ -63,16 +62,12 @@ native "rust" mod rustrt {
fn eq(&str a, &str b) -> bool {
let uint i = byte_len(a);
if (byte_len(b) != i) {
ret false;
}
if (byte_len(b) != i) { ret false; }
while (i > 0u) {
i -= 1u;
auto cha = a.(i);
auto chb = b.(i);
if (cha != chb) {
ret false;
}
if (cha != chb) { ret false; }
}
ret true;
}
@ -81,62 +76,62 @@ fn lteq(&str a, &str b) -> bool {
let uint i = byte_len(a);
let uint j = byte_len(b);
let uint n = i;
if (j < n) {
n = j;
}
if (j < n) { n = j; }
let uint x = 0u;
while (x < n) {
auto cha = a.(x);
auto chb = b.(x);
if (cha < chb) {
ret true;
}
else if (cha > chb) {
ret false;
}
if (cha < chb) { ret true; } else if (cha > chb) { ret false; }
x += 1u;
}
ret i <= j;
}
fn hash(&str s) -> uint {
// djb hash.
// FIXME: replace with murmur.
let uint u = 5381u;
for (u8 c in s) {
u *= 33u;
u += (c as uint);
}
for (u8 c in s) { u *= 33u; u += c as uint; }
ret u;
}
// UTF-8 tags and ranges
const u8 tag_cont_u8 = 0x80_u8;
const uint tag_cont = 0x80_u;
const uint max_one_b = 0x80_u;
const uint tag_two_b = 0xc0_u;
const uint max_two_b = 0x800_u;
const uint tag_three_b = 0xe0_u;
const uint max_three_b = 0x10000_u;
const uint tag_four_b = 0xf0_u;
const uint max_four_b = 0x200000_u;
const uint tag_five_b = 0xf8_u;
const uint max_five_b = 0x4000000_u;
const uint tag_six_b = 0xfc_u;
const u8 tag_cont_u8 = 128u8;
const uint tag_cont = 128u;
const uint max_one_b = 128u;
const uint tag_two_b = 192u;
const uint max_two_b = 2048u;
const uint tag_three_b = 224u;
const uint max_three_b = 65536u;
const uint tag_four_b = 240u;
const uint max_four_b = 2097152u;
const uint tag_five_b = 248u;
const uint max_five_b = 67108864u;
const uint tag_six_b = 252u;
fn is_utf8(vec[u8] v) -> bool {
auto i = 0u;
auto total = vec::len[u8](v);
while (i < total) {
auto chsize = utf8_char_width(v.(i));
if (chsize == 0u) {ret false;}
if (i + chsize > total) {ret false;}
if (chsize == 0u) { ret false; }
if (i + chsize > total) { ret false; }
i += 1u;
while (chsize > 1u) {
if (v.(i) & 0xc0_u8 != tag_cont_u8) {ret false;}
if (v.(i) & 192u8 != tag_cont_u8) { ret false; }
i += 1u;
chsize -= 1u;
}
@ -146,52 +141,35 @@ fn is_utf8(vec[u8] v) -> bool {
fn is_ascii(str s) -> bool {
let uint i = byte_len(s);
while (i > 0u) {
i -= 1u;
if ((s.(i) & 0x80_u8) != 0u8) {
ret false;
}
}
while (i > 0u) { i -= 1u; if (s.(i) & 128u8 != 0u8) { ret false; } }
ret true;
}
fn alloc(uint n_bytes) -> str {
ret rustrt::str_alloc(n_bytes);
}
fn alloc(uint n_bytes) -> str { ret rustrt::str_alloc(n_bytes); }
// Returns the number of bytes (a.k.a. UTF-8 code units) in s.
// Contrast with a function that would return the number of code
// points (char's), combining character sequences, words, etc. See
// http://icu-project.org/apiref/icu4c/classBreakIterator.html for a
// way to implement those.
fn byte_len(str s) -> uint {
ret rustrt::str_byte_len(s);
}
fn byte_len(str s) -> uint { ret rustrt::str_byte_len(s); }
fn buf(str s) -> sbuf {
ret rustrt::str_buf(s);
}
fn buf(str s) -> sbuf { ret rustrt::str_buf(s); }
fn bytes(str s) -> vec[u8] {
ret rustrt::str_vec(s);
}
fn bytes(str s) -> vec[u8] { ret rustrt::str_vec(s); }
fn from_bytes(vec[u8] v) -> str { ret rustrt::str_from_vec(v); }
fn from_bytes(vec[u8] v) : is_utf8(v) -> str {
ret rustrt::str_from_vec(v);
}
// FIXME temp thing
fn unsafe_from_bytes(vec[mutable? u8] v) -> str {
ret rustrt::str_from_vec(v);
}
fn unsafe_from_byte(u8 u) -> str {
ret rustrt::str_from_vec([u]);
}
fn unsafe_from_byte(u8 u) -> str { ret rustrt::str_from_vec([u]); }
fn str_from_cstr(sbuf cstr) -> str {
ret rustrt::str_from_cstr(cstr);
}
fn str_from_cstr(sbuf cstr) -> str { ret rustrt::str_from_cstr(cstr); }
fn str_from_buf(sbuf buf, uint len) -> str {
ret rustrt::str_from_buf(buf, len);
@ -202,30 +180,30 @@ fn push_utf8_bytes(&mutable str s, char ch) {
if (code < max_one_b) {
s = rustrt::str_push_byte(s, code);
} else if (code < max_two_b) {
s = rustrt::str_push_byte(s, ((code >> 6u) & 0x1f_u) | tag_two_b);
s = rustrt::str_push_byte(s, (code & 0x3f_u) | tag_cont);
s = rustrt::str_push_byte(s, code >> 6u & 31u | tag_two_b);
s = rustrt::str_push_byte(s, code & 63u | tag_cont);
} else if (code < max_three_b) {
s = rustrt::str_push_byte(s, ((code >> 12u) & 0x0f_u) | tag_three_b);
s = rustrt::str_push_byte(s, ((code >> 6u) & 0x3f_u) | tag_cont);
s = rustrt::str_push_byte(s, (code & 0x3f_u) | tag_cont);
s = rustrt::str_push_byte(s, code >> 12u & 15u | tag_three_b);
s = rustrt::str_push_byte(s, code >> 6u & 63u | tag_cont);
s = rustrt::str_push_byte(s, code & 63u | tag_cont);
} else if (code < max_four_b) {
s = rustrt::str_push_byte(s, ((code >> 18u) & 0x07_u) | tag_four_b);
s = rustrt::str_push_byte(s, ((code >> 12u) & 0x3f_u) | tag_cont);
s = rustrt::str_push_byte(s, ((code >> 6u) & 0x3f_u) | tag_cont);
s = rustrt::str_push_byte(s, (code & 0x3f_u) | tag_cont);
s = rustrt::str_push_byte(s, code >> 18u & 7u | tag_four_b);
s = rustrt::str_push_byte(s, code >> 12u & 63u | tag_cont);
s = rustrt::str_push_byte(s, code >> 6u & 63u | tag_cont);
s = rustrt::str_push_byte(s, code & 63u | tag_cont);
} else if (code < max_five_b) {
s = rustrt::str_push_byte(s, ((code >> 24u) & 0x03_u) | tag_five_b);
s = rustrt::str_push_byte(s, ((code >> 18u) & 0x3f_u) | tag_cont);
s = rustrt::str_push_byte(s, ((code >> 12u) & 0x3f_u) | tag_cont);
s = rustrt::str_push_byte(s, ((code >> 6u) & 0x3f_u) | tag_cont);
s = rustrt::str_push_byte(s, (code & 0x3f_u) | tag_cont);
s = rustrt::str_push_byte(s, code >> 24u & 3u | tag_five_b);
s = rustrt::str_push_byte(s, code >> 18u & 63u | tag_cont);
s = rustrt::str_push_byte(s, code >> 12u & 63u | tag_cont);
s = rustrt::str_push_byte(s, code >> 6u & 63u | tag_cont);
s = rustrt::str_push_byte(s, code & 63u | tag_cont);
} else {
s = rustrt::str_push_byte(s, ((code >> 30u) & 0x01_u) | tag_six_b);
s = rustrt::str_push_byte(s, ((code >> 24u) & 0x3f_u) | tag_cont);
s = rustrt::str_push_byte(s, ((code >> 18u) & 0x3f_u) | tag_cont);
s = rustrt::str_push_byte(s, ((code >> 12u) & 0x3f_u) | tag_cont);
s = rustrt::str_push_byte(s, ((code >> 6u) & 0x3f_u) | tag_cont);
s = rustrt::str_push_byte(s, (code & 0x3f_u) | tag_cont);
s = rustrt::str_push_byte(s, code >> 30u & 1u | tag_six_b);
s = rustrt::str_push_byte(s, code >> 24u & 63u | tag_cont);
s = rustrt::str_push_byte(s, code >> 18u & 63u | tag_cont);
s = rustrt::str_push_byte(s, code >> 12u & 63u | tag_cont);
s = rustrt::str_push_byte(s, code >> 6u & 63u | tag_cont);
s = rustrt::str_push_byte(s, code & 63u | tag_cont);
}
}
@ -237,18 +215,21 @@ fn from_char(char ch) -> str {
fn from_chars(vec[char] chs) -> str {
auto buf = "";
for (char ch in chs) {push_utf8_bytes(buf, ch);}
for (char ch in chs) { push_utf8_bytes(buf, ch); }
ret buf;
}
fn utf8_char_width(u8 b) -> uint {
let uint byte = b as uint;
if (byte < 0x80_u) {ret 1u;}
if (byte < 0xc0_u) {ret 0u;} // Not a valid start byte
if (byte < 0xe0_u) {ret 2u;}
if (byte < 0xf0_u) {ret 3u;}
if (byte < 0xf8_u) {ret 4u;}
if (byte < 0xfc_u) {ret 5u;}
if (byte < 128u) { ret 1u; }
if (byte < 192u) {
ret 0u; // Not a valid start byte
}
if (byte < 224u) { ret 2u; }
if (byte < 240u) { ret 3u; }
if (byte < 248u) { ret 4u; }
if (byte < 252u) { ret 5u; }
ret 6u;
}
@ -256,27 +237,26 @@ fn char_range_at(str s, uint i) -> tup(char, uint) {
auto b0 = s.(i);
auto w = utf8_char_width(b0);
assert (w != 0u);
if (w == 1u) {ret tup(b0 as char, i + 1u);}
if (w == 1u) { ret tup(b0 as char, i + 1u); }
auto val = 0u;
auto end = i + w;
i += 1u;
while (i < end) {
auto byte = s.(i);
assert (byte & 0xc0_u8 == tag_cont_u8);
assert (byte & 192u8 == tag_cont_u8);
val <<= 6u;
val += (byte & 0x3f_u8) as uint;
val += byte & 63u8 as uint;
i += 1u;
}
// Clunky way to get the right bits from the first byte. Uses two shifts,
// the first to clip off the marker bits at the left of the byte, and then
// a second (as uint) to get it to the right position.
val += ((b0 << ((w + 1u) as u8)) as uint) << ((w - 1u) * 6u - w - 1u);
val += (b0 << (w + 1u as u8) as uint) << (w - 1u) * 6u - w - 1u;
ret tup(val as char, i);
}
fn char_at(str s, uint i) -> char {
ret char_range_at(s, i)._0;
}
fn char_at(str s, uint i) -> char { ret char_range_at(s, i)._0; }
fn char_len(str s) -> uint {
auto i = 0u;
@ -304,13 +284,11 @@ fn to_chars(str s) -> vec[char] {
ret buf;
}
fn push_char(&mutable str s, char ch) {
s += from_char(ch);
}
fn push_char(&mutable str s, char ch) { s += from_char(ch); }
fn pop_char(&mutable str s) -> char {
auto end = byte_len(s);
while (end > 0u && s.(end - 1u) & 0xc0_u8 == tag_cont_u8) {end -= 1u;}
while (end > 0u && s.(end - 1u) & 192u8 == tag_cont_u8) { end -= 1u; }
assert (end > 0u);
auto ch = char_at(s, end - 1u);
s = substr(s, 0u, end - 1u);
@ -327,6 +305,7 @@ fn unshift_char(&mutable str s, char ch) {
// Workaround for rustboot order-of-evaluation issue -- if I put s
// directly after the +, the string ends up containing (only) the
// character, twice.
auto x = s;
s = from_char(ch) + x;
}
@ -338,76 +317,47 @@ fn refcount(str s) -> uint {
} else {
// -2 because calling this function and the native function both
// incremented the refcount.
ret r - 2u;
ret r - 2u;
}
}
// Standard bits from the world of string libraries.
fn index(str s, u8 c) -> int {
let int i = 0;
for (u8 k in s) {
if (k == c) {
ret i;
}
i += 1;
}
for (u8 k in s) { if (k == c) { ret i; } i += 1; }
ret -1;
}
fn rindex(str s, u8 c) -> int {
let int n = str::byte_len(s) as int;
while (n >= 0) {
if (s.(n) == c) {
ret n;
}
n -= 1;
}
while (n >= 0) { if (s.(n) == c) { ret n; } n -= 1; }
ret n;
}
fn find(str haystack, str needle) -> int {
let int haystack_len = byte_len(haystack) as int;
let int needle_len = byte_len(needle) as int;
if (needle_len == 0) {
ret 0;
}
fn match_at(&str haystack,
&str needle,
int i) -> bool {
if (needle_len == 0) { ret 0; }
fn match_at(&str haystack, &str needle, int i) -> bool {
let int j = i;
for (u8 c in needle) {
if (haystack.(j) != c) {
ret false;
}
j += 1;
}
for (u8 c in needle) { if (haystack.(j) != c) { ret false; } j += 1; }
ret true;
}
let int i = 0;
while (i <= haystack_len - needle_len) {
if (match_at(haystack, needle, i)) {
ret i;
}
if (match_at(haystack, needle, i)) { ret i; }
i += 1;
}
ret -1;
ret -1;
}
fn starts_with(str haystack, str needle) -> bool {
let uint haystack_len = byte_len(haystack);
let uint needle_len = byte_len(needle);
if (needle_len == 0u) {
ret true;
}
if (needle_len > haystack_len) {
ret false;
}
if (needle_len == 0u) { ret true; }
if (needle_len > haystack_len) { ret false; }
ret eq(substr(haystack, 0u, needle_len), needle);
}
@ -415,15 +365,13 @@ fn ends_with(str haystack, str needle) -> bool {
let uint haystack_len = byte_len(haystack);
let uint needle_len = byte_len(needle);
ret if (needle_len == 0u) {
true
} else if (needle_len > haystack_len) {
false
} else {
eq(substr(haystack,
haystack_len - needle_len,
needle_len),
needle)
};
true
} else if (needle_len > haystack_len) {
false
} else {
eq(substr(haystack, haystack_len - needle_len, needle_len),
needle)
};
}
fn substr(str s, uint begin, uint len) -> str {
@ -432,6 +380,7 @@ fn substr(str s, uint begin, uint len) -> str {
fn slice(str s, uint begin, uint end) -> str {
// FIXME: Typestate precondition
assert (begin <= end);
assert (end <= str::byte_len(s));
ret rustrt::str_slice(s, begin, end);
@ -473,23 +422,15 @@ fn split(str s, u8 sep) -> vec[str] {
v += [accum];
accum = "";
ends_with_sep = true;
} else {
accum += unsafe_from_byte(c);
ends_with_sep = false;
}
}
if (str::byte_len(accum) != 0u ||
ends_with_sep) {
v += [accum];
} else { accum += unsafe_from_byte(c); ends_with_sep = false; }
}
if (str::byte_len(accum) != 0u || ends_with_sep) { v += [accum]; }
ret v;
}
fn concat(vec[str] v) -> str {
let str s = "";
for (str ss in v) {
s += ss;
}
for (str ss in v) { s += ss; }
ret s;
}
@ -497,16 +438,13 @@ fn connect(vec[str] v, str sep) -> str {
let str s = "";
let bool first = true;
for (str ss in v) {
if (first) {
first = false;
} else {
s += sep;
}
if (first) { first = false; } else { s += sep; }
s += ss;
}
ret s;
}
// FIXME: This only handles ASCII
fn to_upper(str s) -> str {
auto outstr = "";
@ -517,15 +455,11 @@ fn to_upper(str s) -> str {
auto next;
if (ascii_a <= byte && byte <= ascii_z) {
next = byte - diff;
} else {
next = byte;
}
} else { next = byte; }
push_byte(outstr, next);
}
ret outstr;
}
// Local Variables:
// mode: rust;
// fill-column: 78;

View File

@ -1,25 +1,18 @@
export rustrt;
native "rust" mod rustrt {
// Explicitly re-export native stuff we want to be made
// available outside this crate. Otherwise it's
// visible-in-crate, but not re-exported.
export last_os_error;
export size_of;
export align_of;
export refcount;
export do_gc;
fn last_os_error() -> str;
// Explicitly re-export native stuff we want to be made
// available outside this crate. Otherwise it's
// visible-in-crate, but not re-exported.
fn last_os_error() -> str;
fn size_of[T]() -> uint;
fn align_of[T]() -> uint;
fn refcount[T](@T t) -> uint;
fn do_gc();
fn unsupervise();
}
// Local Variables:
// mode: rust;
// fill-column: 78;

View File

@ -1,29 +1,46 @@
// Simple ANSI color library.
//
// TODO: Windows support.
const u8 color_black = 0u8;
const u8 color_red = 1u8;
const u8 color_green = 2u8;
const u8 color_yellow = 3u8;
const u8 color_blue = 4u8;
const u8 color_magenta = 5u8;
const u8 color_cyan = 6u8;
const u8 color_light_gray = 7u8;
const u8 color_light_grey = 7u8;
const u8 color_dark_gray = 8u8;
const u8 color_dark_grey = 8u8;
const u8 color_bright_red = 9u8;
const u8 color_bright_green = 10u8;
const u8 color_bright_yellow = 11u8;
const u8 color_bright_blue = 12u8;
const u8 color_bright_magenta = 13u8;
const u8 color_bright_cyan = 14u8;
const u8 color_bright_white = 15u8;
fn esc(io::buf_writer writer) {
writer.write([0x1bu8, '[' as u8]);
}
fn esc(io::buf_writer writer) { writer.write([0x1bu8, '[' as u8]); }
fn reset(io::buf_writer writer) {
esc(writer);
@ -36,12 +53,8 @@ fn color_supported() -> bool {
fn set_color(io::buf_writer writer, u8 first_char, u8 color) {
assert (color < 16u8);
esc(writer);
if (color >= 8u8) {
writer.write(['1' as u8, ';' as u8]);
color -= 8u8;
}
if (color >= 8u8) { writer.write(['1' as u8, ';' as u8]); color -= 8u8; }
writer.write([first_char, ('0' as u8) + color, 'm' as u8]);
}
@ -52,7 +65,5 @@ fn fg(io::buf_writer writer, u8 color) {
fn bg(io::buf_writer writer, u8 color) {
ret set_color(writer, '4' as u8, color);
}
// export fg;
// export bg;

View File

@ -1,3 +1,5 @@
native "rust" mod rustrt {
fn get_time(&mutable u32 sec, &mutable u32 usec);
}
@ -5,8 +7,8 @@ native "rust" mod rustrt {
type timeval = rec(u32 sec, u32 usec);
fn get_time() -> timeval {
auto sec = 0u32; auto usec = 0u32;
auto sec = 0u32;
auto usec = 0u32;
rustrt::get_time(sec, usec);
ret rec(sec=sec, usec=usec);
}
}

View File

@ -1,23 +1,28 @@
fn add(u8 x, u8 y) -> u8 { ret x + y; }
fn sub(u8 x, u8 y) -> u8 { ret x - y; }
fn mul(u8 x, u8 y) -> u8 { ret x * y; }
fn div(u8 x, u8 y) -> u8 { ret x / y; }
fn rem(u8 x, u8 y) -> u8 { ret x % y; }
fn lt(u8 x, u8 y) -> bool { ret x < y; }
fn le(u8 x, u8 y) -> bool { ret x <= y; }
fn eq(u8 x, u8 y) -> bool { ret x == y; }
fn ne(u8 x, u8 y) -> bool { ret x != y; }
fn ge(u8 x, u8 y) -> bool { ret x >= y; }
fn gt(u8 x, u8 y) -> bool { ret x > y; }
iter range(u8 lo, u8 hi) -> u8 {
while (lo < hi) {
put lo;
lo += 1u8;
}
}
iter range(u8 lo, u8 hi) -> u8 { while (lo < hi) { put lo; lo += 1u8; } }
// Local Variables:
// mode: rust;
// fill-column: 78;

View File

@ -1,16 +1,19 @@
import option::none;
import option::some;
// A very naive implementation of union-find with unsigned integer nodes.
// Maintains the invariant that the root of a node is always equal to or less
// than the node itself.
type node = option::t[uint];
type ufind = rec(mutable vec[mutable node] nodes);
fn make() -> ufind {
let vec[mutable node] v = [mutable none[uint]];
vec::pop(v); // FIXME: botch
vec::pop(v); // FIXME: botch
ret rec(mutable nodes=v);
}
@ -20,6 +23,7 @@ fn make_set(&ufind ufnd) -> uint {
ret idx;
}
/// Creates sets as necessary to ensure that least `n` sets are present in the
/// data structure.
fn grow(&ufind ufnd, uint n) {
@ -38,22 +42,16 @@ fn union(&ufind ufnd, uint m, uint n) {
auto n_root = find(ufnd, n);
if (m_root < n_root) {
ufnd.nodes.(n_root) = some[uint](m_root);
} else if (m_root > n_root) {
ufnd.nodes.(m_root) = some[uint](n_root);
}
} else if (m_root > n_root) { ufnd.nodes.(m_root) = some[uint](n_root); }
}
fn set_count(&ufind ufnd) -> uint {
ret vec::len[node](ufnd.nodes);
}
fn set_count(&ufind ufnd) -> uint { ret vec::len[node](ufnd.nodes); }
// Removes all sets with IDs greater than or equal to the given value.
fn prune(&ufind ufnd, uint n) {
// TODO: Use "slice" once we get rid of "mutable?"
auto len = vec::len[node](ufnd.nodes);
while (len != n) {
vec::pop[node](ufnd.nodes);
len -= 1u;
}
}
auto len = vec::len[node](ufnd.nodes);
while (len != n) { vec::pop[node](ufnd.nodes); len -= 1u; }
}

View File

@ -1,40 +1,42 @@
fn add(uint x, uint y) -> uint { ret x + y; }
fn sub(uint x, uint y) -> uint { ret x - y; }
fn mul(uint x, uint y) -> uint { ret x * y; }
fn div(uint x, uint y) -> uint { ret x / y; }
fn rem(uint x, uint y) -> uint { ret x % y; }
fn lt(uint x, uint y) -> bool { ret x < y; }
fn le(uint x, uint y) -> bool { ret x <= y; }
fn eq(uint x, uint y) -> bool { ret x == y; }
fn ne(uint x, uint y) -> bool { ret x != y; }
fn ge(uint x, uint y) -> bool { ret x >= y; }
fn gt(uint x, uint y) -> bool { ret x > y; }
fn max(uint x, uint y) -> uint {
if (x > y) { ret x; }
ret y;
}
fn max(uint x, uint y) -> uint { if (x > y) { ret x; } ret y; }
iter range(uint lo, uint hi) -> uint {
auto lo_ = lo;
while (lo_ < hi) {
put lo_;
lo_ += 1u;
}
while (lo_ < hi) { put lo_; lo_ += 1u; }
}
fn next_power_of_two(uint n) -> uint {
// FIXME change |* uint(4)| below to |* uint(8) / uint(2)| and watch the
// world explode.
let uint halfbits = sys::rustrt::size_of[uint]() * 4u;
let uint tmp = n - 1u;
let uint shift = 1u;
while (shift <= halfbits) {
tmp |= tmp >> shift;
shift <<= 1u;
}
while (shift <= halfbits) { tmp |= tmp >> shift; shift <<= 1u; }
ret tmp + 1u;
}
@ -43,65 +45,53 @@ fn parse_buf(vec[u8] buf, uint radix) -> uint {
log_err "parse_buf(): buf is empty";
fail;
}
auto i = vec::len[u8](buf) - 1u;
auto power = 1u;
auto n = 0u;
while (true) {
n += (((buf.(i)) - ('0' as u8)) as uint) * power;
n += (buf.(i) - ('0' as u8) as uint) * power;
power *= radix;
if (i == 0u) { ret n; }
i -= 1u;
}
fail;
}
fn to_str(uint num, uint radix) -> str
{
fn to_str(uint num, uint radix) -> str {
auto n = num;
assert (0u < radix && radix <= 16u);
fn digit(uint n) -> char {
ret alt (n) {
case (0u) { '0' }
case (1u) { '1' }
case (2u) { '2' }
case (3u) { '3' }
case (4u) { '4' }
case (5u) { '5' }
case (6u) { '6' }
case (7u) { '7' }
case (8u) { '8' }
case (9u) { '9' }
case (10u) { 'a' }
case (11u) { 'b' }
case (12u) { 'c' }
case (13u) { 'd' }
case (14u) { 'e' }
case (15u) { 'f' }
case (_) { fail }
};
case (0u) { '0' }
case (1u) { '1' }
case (2u) { '2' }
case (3u) { '3' }
case (4u) { '4' }
case (5u) { '5' }
case (6u) { '6' }
case (7u) { '7' }
case (8u) { '8' }
case (9u) { '9' }
case (10u) { 'a' }
case (11u) { 'b' }
case (12u) { 'c' }
case (13u) { 'd' }
case (14u) { 'e' }
case (15u) { 'f' }
case (_) { fail }
};
}
if (n == 0u) { ret "0"; }
let str s = "";
while (n != 0u) {
s += str::unsafe_from_byte(digit(n % radix) as u8);
n /= radix;
}
let str s1 = "";
let uint len = str::byte_len(s);
while (len != 0u) {
len -= 1u;
s1 += str::unsafe_from_byte(s.(len));
}
while (len != 0u) { len -= 1u; s1 += str::unsafe_from_byte(s.(len)); }
ret s1;
}
// Local Variables:
// mode: rust;
// fill-column: 78;

View File

@ -1,28 +1,24 @@
fn id[T](&T x) -> T {
ret x;
}
fn id[T](&T x) -> T { ret x; }
/* FIXME (issue #141): See test/run-pass/constrained-type.rs. Uncomment
* the constraint once fixed. */
type rational = rec(int num, int den); // : int::positive(*.den);
type rational = rec(int num, int den);
// : int::positive(*.den);
fn rational_leq(&rational x, &rational y) -> bool {
// NB: Uses the fact that rationals have positive denominators WLOG:
ret x.num * y.den <= y.num * x.den;
}
fn fst[T, U](&tup(T, U) x) -> T {
ret x._0;
}
fn fst[T, U](&tup(T, U) x) -> T { ret x._0; }
fn snd[T, U](&tup(T, U) x) -> U {
ret x._1;
}
fn orb(&bool a, &bool b) -> bool {
ret a || b;
}
fn snd[T, U](&tup(T, U) x) -> U { ret x._1; }
fn orb(&bool a, &bool b) -> bool { ret a || b; }
// Local Variables:
// mode: rust;
// fill-column: 78;

View File

@ -1,39 +1,35 @@
import option::none;
import option::some;
import util::orb;
type vbuf = rustrt::vbuf;
type operator2[T,U,V] = fn(&T, &U) -> V;
type operator2[T, U, V] = fn(&T, &U) -> V ;
type array[T] = vec[mutable? T];
native "rust" mod rustrt {
type vbuf;
fn vec_buf[T](vec[T] v, uint offset) -> vbuf;
fn vec_len[T](vec[T] v) -> uint;
/**
* Sometimes we modify the vec internal data via vec_buf and need to
* update the vec's fill length accordingly.
*/
fn vec_len_set[T](vec[T] v, uint n);
/**
* The T in vec_alloc[T, U] is the type of the vec to allocate. The
* U is the type of an element in the vec. So to allocate a vec[U] we
* want to invoke this as vec_alloc[vec[U], U].
*/
fn vec_alloc[T, U](uint n_elts) -> vec[U];
/**
* Sometimes we modify the vec internal data via vec_buf and need to
* update the vec's fill length accordingly.
*/
fn vec_len_set[T](vec[T] v, uint n);
/**
* The T in vec_alloc[T, U] is the type of the vec to allocate. The
* U is the type of an element in the vec. So to allocate a vec[U] we
* want to invoke this as vec_alloc[vec[U], U].
*/
fn vec_alloc[T, U](uint n_elts) -> vec[U];
fn vec_alloc_mut[T, U](uint n_elts) -> vec[mutable U];
fn refcount[T](vec[T] v) -> uint;
fn vec_print_debug_info[T](vec[T] v);
fn vec_from_vbuf[T](vbuf v, uint n_elts) -> vec[T];
fn unsafe_vec_to_mut[T](vec[T] v) -> vec[mutable T];
}
@ -52,7 +48,8 @@ fn refcount[T](array[T] v) -> uint {
} else {
// -2 because calling this function and the native function both
// incremented the refcount.
ret r - 2u;
ret r - 2u;
}
}
@ -60,35 +57,27 @@ fn vec_from_vbuf[T](vbuf v, uint n_elts) -> vec[T] {
ret rustrt::vec_from_vbuf[T](v, n_elts);
}
// FIXME: Remove me; this is a botch to get around rustboot's bad typechecker.
fn empty[T]() -> vec[T] {
ret alloc[T](0u);
}
// FIXME: Remove me; this is a botch to get around rustboot's bad typechecker.
fn empty_mut[T]() -> vec[mutable T] {
ret alloc_mut[T](0u);
}
fn empty[T]() -> vec[T] { ret alloc[T](0u); }
type init_op[T] = fn(uint i) -> T;
// FIXME: Remove me; this is a botch to get around rustboot's bad typechecker.
fn empty_mut[T]() -> vec[mutable T] { ret alloc_mut[T](0u); }
type init_op[T] = fn(uint) -> T ;
fn init_fn[T](&init_op[T] op, uint n_elts) -> vec[T] {
let vec[T] v = alloc[T](n_elts);
let uint i = 0u;
while (i < n_elts) {
v += [op(i)];
i += 1u;
}
while (i < n_elts) { v += [op(i)]; i += 1u; }
ret v;
}
fn init_fn_mut[T](&init_op[T] op, uint n_elts) -> vec[mutable T] {
let vec[mutable T] v = alloc_mut[T](n_elts);
let uint i = 0u;
while (i < n_elts) {
v += [mutable op(i)];
i += 1u;
}
while (i < n_elts) { v += [mutable op(i)]; i += 1u; }
ret v;
}
@ -100,79 +89,60 @@ fn init_elt[T](&T t, uint n_elts) -> vec[T] {
* let init_op[T] inner = bind elt_op[T](t, _);
* ret init_fn[T](inner, n_elts);
*/
let vec[T] v = alloc[T](n_elts);
let uint i = n_elts;
while (i > 0u) {
i -= 1u;
v += [t];
}
while (i > 0u) { i -= 1u; v += [t]; }
ret v;
}
fn init_elt_mut[T](&T t, uint n_elts) -> vec[mutable T] {
let vec[mutable T] v = alloc_mut[T](n_elts);
let uint i = n_elts;
while (i > 0u) {
i -= 1u;
v += [mutable t];
}
while (i > 0u) { i -= 1u; v += [mutable t]; }
ret v;
}
fn buf[T](array[T] v) -> vbuf {
ret rustrt::vec_buf[T](v, 0u);
}
fn buf[T](array[T] v) -> vbuf { ret rustrt::vec_buf[T](v, 0u); }
fn len[T](array[T] v) -> uint {
ret rustrt::vec_len[T](v);
}
fn len[T](array[T] v) -> uint { ret rustrt::vec_len[T](v); }
fn len_set[T](array[T] v, uint n) {
rustrt::vec_len_set[T](v, n);
}
fn len_set[T](array[T] v, uint n) { rustrt::vec_len_set[T](v, n); }
fn buf_off[T](array[T] v, uint offset) -> vbuf {
assert (offset < len[T](v));
assert (offset < len[T](v));
ret rustrt::vec_buf[T](v, offset);
}
fn print_debug_info[T](array[T] v) {
rustrt::vec_print_debug_info[T](v);
}
fn print_debug_info[T](array[T] v) { rustrt::vec_print_debug_info[T](v); }
// Returns the last element of v.
fn last[T](array[T] v) -> option::t[T] {
auto l = len[T](v);
if (l == 0u) {
ret none[T];
}
if (l == 0u) { ret none[T]; }
ret some[T](v.(l - 1u));
}
// Returns elements from [start..end) from v.
// Returns elements from [start..end) from v.
fn slice[T](array[T] v, uint start, uint end) -> vec[T] {
assert (start <= end);
assert (end <= len[T](v));
auto result = alloc[T](end - start);
let uint i = start;
while (i < end) {
result += [v.(i)];
i += 1u;
}
while (i < end) { result += [v.(i)]; i += 1u; }
ret result;
}
// FIXME: Should go away eventually.
fn slice_mut[T](array[T] v, uint start, uint end) -> vec[mutable T] {
assert (start <= end);
assert (end <= len[T](v));
auto result = alloc_mut[T](end - start);
let uint i = start;
while (i < end) {
result += [mutable v.(i)];
i += 1u;
}
while (i < end) { result += [mutable v.(i)]; i += 1u; }
ret result;
}
@ -196,12 +166,10 @@ fn pop[T](&mutable array[T] v) -> T {
fn top[T](&array[T] v) -> T {
auto ln = len[T](v);
assert (ln > 0u);
ret v.(ln-1u);
ret v.(ln - 1u);
}
fn push[T](&mutable array[T] v, &T t) {
v += [t];
}
fn push[T](&mutable array[T] v, &T t) { v += [t]; }
fn unshift[T](&mutable array[T] v, &T t) {
auto res = alloc[T](len[T](v) + 1u);
@ -212,132 +180,96 @@ fn unshift[T](&mutable array[T] v, &T t) {
fn grow[T](&mutable array[T] v, uint n, &T initval) {
let uint i = n;
while (i > 0u) {
i -= 1u;
v += [initval];
}
while (i > 0u) { i -= 1u; v += [initval]; }
}
fn grow_set[T](&mutable vec[mutable T] v, uint index, &T initval, &T val) {
auto length = vec::len(v);
if (index >= length) {
grow(v, index - length + 1u, initval);
}
if (index >= length) { grow(v, index - length + 1u, initval); }
v.(index) = val;
}
fn grow_init_fn[T](&mutable array[T] v, uint n, fn()->T init_fn) {
fn grow_init_fn[T](&mutable array[T] v, uint n, fn() -> T init_fn) {
let uint i = n;
while (i > 0u) {
i -= 1u;
v += [init_fn()];
}
while (i > 0u) { i -= 1u; v += [init_fn()]; }
}
fn grow_init_fn_set[T](&array[T] v, uint index, fn()->T init_fn, &T val) {
fn grow_init_fn_set[T](&array[T] v, uint index, fn() -> T init_fn, &T val) {
auto length = vec::len(v);
if (index >= length) { grow_init_fn(v, index - length + 1u, init_fn); }
v.(index) = val;
}
fn map[T, U](&fn(&T) -> U f, &vec[T] v) -> vec[U] {
fn map[T, U](&fn(&T) -> U f, &vec[T] v) -> vec[U] {
let vec[U] res = alloc[U](len[T](v));
for (T ve in v) {
res += [f(ve)];
}
for (T ve in v) { res += [f(ve)]; }
ret res;
}
fn filter_map[T, U](&fn(&T) -> option::t[U] f, &vec[T] v) -> vec[U] {
fn filter_map[T, U](&fn(&T) -> option::t[U] f, &vec[T] v) -> vec[U] {
let vec[U] res = [];
for(T ve in v) {
alt(f(ve)) {
case (some(?elt)) { res += [elt]; }
case (none) {}
}
for (T ve in v) {
alt (f(ve)) { case (some(?elt)) { res += [elt]; } case (none) { } }
}
ret res;
}
fn map2[T,U,V](&operator2[T,U,V] f, &vec[T] v0, &vec[U] v1) -> vec[V] {
fn map2[T, U, V](&operator2[T, U, V] f, &vec[T] v0, &vec[U] v1) -> vec[V] {
auto v0_len = len[T](v0);
if (v0_len != len[U](v1)) {
fail;
}
if (v0_len != len[U](v1)) { fail; }
let vec[V] u = alloc[V](v0_len);
auto i = 0u;
while (i < v0_len) {
u += [f({v0.(i)}, {v1.(i)})];
i += 1u;
}
while (i < v0_len) { u += [f({ v0.(i) }, { v1.(i) })]; i += 1u; }
ret u;
}
fn find[T](fn (&T) -> bool f, &vec[T] v) -> option::t[T] {
for (T elt in v) {
if (f(elt)) {
ret some[T](elt);
}
}
fn find[T](fn(&T) -> bool f, &vec[T] v) -> option::t[T] {
for (T elt in v) { if (f(elt)) { ret some[T](elt); } }
ret none[T];
}
fn member[T](&T x, &array[T] v) -> bool {
for (T elt in v) {
if (x == elt) { ret true; }
}
for (T elt in v) { if (x == elt) { ret true; } }
ret false;
}
fn count[T](&T x, &array[T] v) -> uint {
auto cnt = 0u;
for (T elt in v) {
if (x == elt) { cnt += 1u; }
}
for (T elt in v) { if (x == elt) { cnt += 1u; } }
ret cnt;
}
fn foldl[T, U](fn (&U, &T) -> U p, &U z, &vec[T] v) -> U {
fn foldl[T, U](fn(&U, &T) -> U p, &U z, &vec[T] v) -> U {
auto sz = len[T](v);
if (sz == 0u) {
ret z;
}
else {
} else {
auto rest = slice[T](v, 1u, sz);
ret (p(foldl[T,U](p, z, rest), v.(0)));
ret p(foldl[T, U](p, z, rest), v.(0));
}
}
fn unzip[T, U](&vec[tup(T, U)] v) -> tup(vec[T], vec[U]) {
auto sz = len[tup(T, U)](v);
if (sz == 0u) {
ret tup(alloc[T](0u), alloc[U](0u));
}
else {
} else {
auto rest = slice[tup(T, U)](v, 1u, sz);
auto tl = unzip[T, U](rest);
auto a = [v.(0)._0];
auto b = [v.(0)._1];
auto tl = unzip[T, U](rest);
auto a = [v.(0)._0];
auto b = [v.(0)._1];
ret tup(a + tl._0, b + tl._1);
}
}
// FIXME make the lengths being equal a constraint
fn zip[T, U](&vec[T] v, &vec[U] u) -> vec[tup(T, U)] {
auto sz = len[T](v);
assert (sz == len[U](u));
if (sz == 0u) {
ret alloc[tup(T, U)](0u);
}
else {
} else {
auto rest = zip[T, U](slice[T](v, 1u, sz), slice[U](u, 1u, sz));
vec::push(rest, tup(v.(0), u.(0)));
ret rest;
@ -349,41 +281,29 @@ fn or(&vec[bool] v) -> bool {
ret vec::foldl[bool, bool](f, false, v);
}
fn clone[T](&vec[T] v) -> vec[T] {
ret slice[T](v, 0u, len[T](v));
}
fn clone[T](&vec[T] v) -> vec[T] { ret slice[T](v, 0u, len[T](v)); }
fn plus_option[T](&mutable vec[T] v, &option::t[T] o) -> () {
alt (o) {
case (none) {}
case (some(?x)) { v += [x]; }
}
fn plus_option[T](&mutable vec[T] v, &option::t[T] o) {
alt (o) { case (none) { } case (some(?x)) { v += [x]; } }
}
fn cat_options[T](&vec[option::t[T]] v) -> vec[T] {
let vec[T] res = [];
for (option::t[T] o in v) {
alt (o) {
case (none) { }
case (some(?t)) {
res += [t];
}
}
alt (o) { case (none) { } case (some(?t)) { res += [t]; } }
}
ret res;
}
// TODO: Remove in favor of built-in "freeze" operation when it's implemented.
fn freeze[T](vec[mutable T] v) -> vec[T] {
let vec[T] result = [];
for (T elem in v) {
result += [elem];
}
for (T elem in v) { result += [elem]; }
ret result;
}
// Swaps two elements in a vector
fn swap[T](&vec[mutable T] v, uint a, uint b) {
let T t = v.(a);
@ -391,44 +311,31 @@ fn swap[T](&vec[mutable T] v, uint a, uint b) {
v.(b) = t;
}
// In place vector reversal
fn reverse[T](&vec[mutable T] v) -> () {
fn reverse[T](&vec[mutable T] v) {
let uint i = 0u;
auto ln = len[T](v);
while(i < ln / 2u) {
swap(v, i, ln - i - 1u);
i += 1u;
}
while (i < ln / 2u) { swap(v, i, ln - i - 1u); i += 1u; }
}
// Functional vector reversal. Returns a reversed copy of v.
fn reversed[T](vec[T] v) -> vec[T] {
let vec[T] res = [];
auto i = len[T](v);
if (i == 0u) {
ret res;
}
else {
i -= 1u;
}
while(i != 0u) {
push[T](res, v.(i));
i -= 1u;
}
if (i == 0u) { ret res; } else { i -= 1u; }
while (i != 0u) { push[T](res, v.(i)); i -= 1u; }
push[T](res, v.(0));
ret res;
}
/// Truncates the vector to length `new_len`.
/// FIXME: This relies on a typechecker bug (covariance vs. invariance).
fn truncate[T](&mutable vec[mutable? T] v, uint new_len) {
v = slice[T](v, 0u, new_len);
}
// Local Variables:
// mode: rust;
// fill-column: 78;

View File

@ -1,11 +1,12 @@
native "rust" mod rustrt {
fn rust_list_files(str path) -> vec[str];
fn rust_file_is_dir(str path) -> int;
fn rust_list_files(str path) -> vec[str];
fn rust_file_is_dir(str path) -> int;
}
fn list_dir(str path) -> vec[str] {
ret rustrt::rust_list_files(path+"*");
}
fn list_dir(str path) -> vec[str] { ret rustrt::rust_list_files(path + "*"); }
/* FIXME: win32 path handling actually accepts '/' or '\' and has subtly
* different semantics for each. Since we build on mingw, we are usually
@ -14,8 +15,8 @@ fn list_dir(str path) -> vec[str] {
* tag type.
*/
const char path_sep = '/';
const char alt_path_sep = '\\';
const char alt_path_sep = '\\';
// Local Variables:
// mode: rust;
// fill-column: 78;

View File

@ -1,12 +1,12 @@
import str::sbuf;
import vec::vbuf;
native mod libc = "msvcrt.dll" {
fn open(sbuf s, int flags, uint mode) -> int = "_open";
fn read(int fd, vbuf buf, uint count) -> int = "_read";
fn write(int fd, vbuf buf, uint count) -> int = "_write";
fn close(int fd) -> int = "_close";
native "cdecl" mod libc {
fn open(sbuf s, int flags, uint mode) -> int"_open";
fn read(int fd, vbuf buf, uint count) -> int"_read";
fn write(int fd, vbuf buf, uint count) -> int"_write";
fn close(int fd) -> int"_close";
type FILE;
fn fopen(sbuf path, sbuf mode) -> FILE;
fn _fdopen(int fd, sbuf mode) -> FILE;
@ -18,58 +18,50 @@ native mod libc = "msvcrt.dll" {
fn fwrite(vbuf buf, uint size, uint n, FILE f) -> uint;
fn fseek(FILE f, int offset, int whence) -> int;
fn ftell(FILE f) -> int;
fn getenv(sbuf n) -> sbuf;
fn _pipe(vbuf fds, uint size, int mode) -> int;
}
mod libc_constants {
fn O_RDONLY() -> int { ret 0x0000; }
fn O_WRONLY() -> int { ret 0x0001; }
fn O_RDWR() -> int { ret 0x0002; }
fn O_APPEND() -> int { ret 0x0400; }
fn O_CREAT() -> int { ret 0x0040; }
fn O_EXCL() -> int { ret 0x0080; }
fn O_TRUNC() -> int { ret 0x0200; }
fn O_TEXT() -> int { ret 0x4000; }
fn O_BINARY() -> int { ret 0x8000; }
fn O_RDONLY() -> int { ret 0; }
fn O_WRONLY() -> int { ret 1; }
fn O_RDWR() -> int { ret 2; }
fn O_APPEND() -> int { ret 1024; }
fn O_CREAT() -> int { ret 64; }
fn O_EXCL() -> int { ret 128; }
fn O_TRUNC() -> int { ret 512; }
fn O_TEXT() -> int { ret 16384; }
fn O_BINARY() -> int { ret 32768; }
fn S_IRUSR() -> uint {
ret 256u; // really _S_IREAD in win32
fn S_IRUSR() -> uint { ret 0x0100u; } // really _S_IREAD in win32
fn S_IWUSR() -> uint { ret 0x0080u; } // really _S_IWRITE in win32
}
fn S_IWUSR() -> uint {
ret 128u; // really _S_IWRITE in win32
}
}
fn exec_suffix() -> str {
ret ".exe";
}
fn exec_suffix() -> str { ret ".exe"; }
fn target_os() -> str {
ret "win32";
}
fn target_os() -> str { ret "win32"; }
fn dylib_filename(str base) -> str {
ret base + ".dll";
}
fn dylib_filename(str base) -> str { ret base + ".dll"; }
fn pipe() -> tup(int, int) {
let vec[mutable int] fds = [mutable 0, 0];
assert (os::libc::_pipe(vec::buf(fds), 1024u,
libc_constants::O_BINARY()) == 0);
assert (os::libc::_pipe(vec::buf(fds), 1024u, libc_constants::O_BINARY())
== 0);
ret tup(fds.(0), fds.(1));
}
fn fd_FILE(int fd) -> libc::FILE {
ret libc::_fdopen(fd, str::buf("r"));
}
fn fd_FILE(int fd) -> libc::FILE { ret libc::_fdopen(fd, str::buf("r")); }
native "rust" mod rustrt {
fn rust_process_wait(int handle) -> int;
}
fn waitpid(int pid) -> int {
ret rustrt::rust_process_wait(pid);
}
fn waitpid(int pid) -> int { ret rustrt::rust_process_wait(pid); }
// Local Variables:
// mode: rust;
// fill-column: 78;

View File

@ -1,3 +1,5 @@
/* -*- mode::rust;indent-tabs-mode::nil -*-
* Implementation of 99 Bottles of Beer
* http://99-bottles-of-beer.net/
@ -6,62 +8,48 @@ use std;
import std::int;
import std::str;
fn b1() -> str {
ret "# of beer on the wall, # of beer.";
}
fn b1() -> str { ret "# of beer on the wall, # of beer."; }
fn b2() -> str {
ret "Take one down and pass it around, # of beer on the wall.";
ret "Take one down and pass it around, # of beer on the wall.";
}
fn b7() ->str {
ret "No more bottles of beer on the wall, no more bottles of beer.";
fn b7() -> str {
ret "No more bottles of beer on the wall, no more bottles of beer.";
}
fn b8() -> str {
ret "Go to the store and buy some more, # of beer on the wall.";
ret "Go to the store and buy some more, # of beer on the wall.";
}
fn sub(str t, int n) -> str {
let str b = "";
let uint i = 0u;
let str ns;
alt (n) {
case (0) {
ns = "no more bottles";
let str b = "";
let uint i = 0u;
let str ns;
alt (n) {
case (0) { ns = "no more bottles"; }
case (1) { ns = "1 bottle"; }
case (_) { ns = int::to_str(n, 10u) + " bottles"; }
}
case (1) {
ns = "1 bottle";
}
case (_) {
ns = int::to_str(n, 10u) + " bottles";
}
}
while (i < str::byte_len(t)) {
if (t.(i) == ('#' as u8)) {
b += ns;
while (i < str::byte_len(t)) {
if (t.(i) == '#' as u8) {
b += ns;
} else { str::push_byte(b, t.(i)); }
i += 1u;
}
else {
str::push_byte(b, t.(i));
}
i += 1u;
}
ret b;
ret b;
}
/* Using an interator */
iter ninetynine() -> int {
let int n = 100;
while (n > 1) {
n -= 1;
put n;
}
}
fn main() {
for each (int n in ninetynine()) {
log sub(b1(), n);
log sub(b2(), n-1);
log "";
}
log b7();
log b8();
}
iter ninetynine() -> int { let int n = 100; while (n > 1) { n -= 1; put n; } }
fn main() {
for each (int n in ninetynine()) {
log sub(b1(), n);
log sub(b2(), n - 1);
log "";
}
log b7();
log b8();
}

View File

@ -1,3 +1,5 @@
/* -*- mode::rust;indent-tabs-mode::nil -*-
* Implementation of 99 Bottles of Beer
* http://99-bottles-of-beer.net/
@ -6,70 +8,55 @@ use std;
import std::int;
import std::str;
tag bottle { none; dual; single; multiple(int);}
tag bottle { none; dual; single; multiple(int); }
fn show(bottle b) {
alt(b) {
case (none) {
log "No more bottles of beer on the wall, no more bottles of beer,";
log "Go to the store and buy some more, "
+"99 bottles of beer on the wall.";
alt (b) {
case (none) {
log "No more bottles of beer on the wall, " +
"no more bottles of beer,";
log "Go to the store and buy some more, " +
"99 bottles of beer on the wall.";
}
case (single) {
log "1 bottle of beer on the wall, 1 bottle of beer,";
log "Take one down and pass it around, " +
"no more bottles of beer on the wall.";
}
case (dual) {
log "2 bottles of beer on the wall, 2 bottles of beer,";
log "Take one down and pass it around, " +
"1 bottle of beer on the wall.";
}
case (multiple(?n)) {
let str nb = int::to_str(n, 10u);
let str mb = int::to_str(n - 1, 10u);
log nb + " bottles of beer on the wall, " + nb +
" bottles of beer,";
log "Take one down and pass it around, " + mb +
" bottles of beer on the wall.";
}
}
case (single) {
log "1 bottle of beer on the wall, 1 bottle of beer,";
log "Take one down and pass it around, "
+"no more bottles of beer on the wall.";
}
case (dual) {
log "2 bottles of beer on the wall, 2 bottles of beer,";
log "Take one down and pass it around, 1 bottle of beer on the wall.";
}
case (multiple(?n)) {
let str nb = int::to_str(n, 10u);
let str mb = int::to_str(n - 1, 10u);
log nb + " bottles of beer on the wall, " + nb + " bottles of beer,";
log "Take one down and pass it around, "
+ mb + " bottles of beer on the wall.";
}
}
}
fn next(bottle b) -> bottle {
alt(b) {
case (none) {
ret none;
alt (b) {
case (none) { ret none; }
case (single) { ret none; }
case (dual) { ret single; }
case (multiple(3)) { ret dual; }
case (multiple(?n)) { ret multiple(n - 1); }
}
case (single) {
ret none;
}
case (dual) {
ret single;
}
case (multiple(3)) {
ret dual;
}
case (multiple(?n)) {
ret multiple(n - 1);
}
}
}
// Won't need this when tags can be compared with ==
fn more(bottle b) -> bool {
alt(b) {
case (none) {
ret false;
}
case (_) {
ret true;
}
}
alt (b) { case (none) { ret false; } case (_) { ret true; } }
}
fn main() {
let bottle b = multiple(99);
let bool running = true;
while (running) {
show(b);
log "";
running = more(b);
b = next(b);
}
let bottle b = multiple(99);
let bool running = true;
while (running) { show(b); log ""; running = more(b); b = next(b); }
}

View File

@ -1,3 +1,5 @@
/* -*- mode::rust;indent-tabs-mode::nil -*-
* Implementation of 99 Bottles of Beer
* http://99-bottles-of-beer.net/
@ -6,56 +8,43 @@ use std;
import std::int;
import std::str;
fn b1() -> str {
ret "# of beer on the wall, # of beer.";
}
fn b1() -> str { ret "# of beer on the wall, # of beer."; }
fn b2() -> str {
ret "Take one down and pass it around, # of beer on the wall.";
ret "Take one down and pass it around, # of beer on the wall.";
}
fn b7() ->str {
ret "No more bottles of beer on the wall, no more bottles of beer.";
fn b7() -> str {
ret "No more bottles of beer on the wall, no more bottles of beer.";
}
fn b8() -> str {
ret "Go to the store and buy some more, # of beer on the wall.";
ret "Go to the store and buy some more, # of beer on the wall.";
}
fn sub(str t, int n) -> str {
let str b = "";
let uint i = 0u;
let str ns;
alt (n) {
case (0) {
ns = "no more bottles";
let str b = "";
let uint i = 0u;
let str ns;
alt (n) {
case (0) { ns = "no more bottles"; }
case (1) { ns = "1 bottle"; }
case (_) { ns = int::to_str(n, 10u) + " bottles"; }
}
case (1) {
ns = "1 bottle";
}
case (_) {
ns = int::to_str(n, 10u) + " bottles";
}
}
while (i < str::byte_len(t)) {
if (t.(i) == ('#' as u8)) {
b += ns;
while (i < str::byte_len(t)) {
if (t.(i) == '#' as u8) {
b += ns;
} else { str::push_byte(b, t.(i)); }
i += 1u;
}
else {
str::push_byte(b, t.(i));
}
i += 1u;
}
ret b;
ret b;
}
/* Straightforward counter */
fn main() {
let int n=99;
while (n > 0) {
log sub(b1(), n);
log sub(b2(), n - 1);
log "";
n -= 1;
}
log b7();
log sub(b8(),99);
}
let int n = 99;
while (n > 0) { log sub(b1(), n); log sub(b2(), n - 1); log ""; n -= 1; }
log b7();
log sub(b8(), 99);
}

View File

@ -7,37 +7,33 @@ import std::int;
import std::str;
fn main() {
fn multiple(int n) {
let str nb = int::to_str(n, 10u);
let str mb = int::to_str(n - 1, 10u);
log nb + " bottles of beer on the wall, " + nb + " bottles of beer,";
log "Take one down and pass it around, "
+ mb + " bottles of beer on the wall.";
log "";
if (n > 3) {
be multiple(n - 1);
fn multiple(int n) {
let str nb = int::to_str(n, 10u);
let str mb = int::to_str(n - 1, 10u);
log nb + " bottles of beer on the wall, " + nb + " bottles of beer,";
log "Take one down and pass it around, " + mb +
" bottles of beer on the wall.";
log "";
if (n > 3) { be multiple(n - 1); } else { be dual(); }
}
else {
be dual();
fn dual() {
log "2 bottles of beer on the wall, 2 bottles of beer,";
log "Take one down and pass it around, 1 bottle of beer on the wall.";
log "";
be single();
}
}
fn dual() {
log "2 bottles of beer on the wall, 2 bottles of beer,";
log "Take one down and pass it around, 1 bottle of beer on the wall.";
log "";
be single();
}
fn single() {
log "1 bottle of beer on the wall, 1 bottle of beer,";
log "Take one down and pass it around, "
+ "no more bottles of beer on the wall.";
log "";
be none();
}
fn none() {
log "No more bottles of beer on the wall, no more bottles of beer,";
log "Go to the store and buy some more, 99 bottles of beer on the wall.";
log "";
}
multiple(99);
fn single() {
log "1 bottle of beer on the wall, 1 bottle of beer,";
log "Take one down and pass it around, " +
"no more bottles of beer on the wall.";
log "";
be none();
}
fn none() {
log "No more bottles of beer on the wall, no more bottles of beer,";
log "Go to the store and buy some more, " +
"99 bottles of beer on the wall.";
log "";
}
multiple(99);
}

View File

@ -1,25 +1,25 @@
// -*- rust -*-
// -*- rust -*-
fn ack(int m, int n) -> int {
if (m == 0) {
ret n+1;
} else {
if (n == 0) {
ret ack(m-1, 1);
if (m == 0) {
ret n + 1;
} else {
ret ack(m-1, ack(m, n-1));
if (n == 0) {
ret ack(m - 1, 1);
} else { ret ack(m - 1, ack(m, n - 1)); }
}
}
}
fn main() {
assert (ack(0,0) == 1);
assert (ack(3,2) == 29);
assert (ack(3,4) == 125);
assert (ack(0, 0) == 1);
assert (ack(3, 2) == 29);
assert (ack(3, 4) == 125);
// This takes a while; but a comparison may amuse: on win32 at least, the
// posted C version of the 'benchmark' running ack(4,1) overruns its stack
// segment and crashes. We just grow our stack (to 4mb) as we go.
// This takes a while; but a comparison may amuse: on win32 at least, the
// posted C version of the 'benchmark' running ack(4,1) overruns its stack
// segment and crashes. We just grow our stack (to 4mb) as we go.
// assert (ack(4,1) == 65533);
// assert (ack(4,1) == 65533);
}

View File

@ -1,74 +1,53 @@
use std;
use std;
import std::int;
tag tree {
nil;
node(@tree, @tree, int);
}
tag tree { nil; node(@tree, @tree, int); }
fn item_check(@tree t) -> int {
alt (*t) {
case (nil) {
ret 0;
alt (*t) {
case (nil) { ret 0; }
case (node(?left, ?right, ?item)) {
ret item + item_check(left) - item_check(right);
}
}
case (node(?left, ?right, ?item)) {
ret item + item_check(left) - item_check(right);
}
}
}
fn bottom_up_tree(int item, int depth) -> @tree{
if (depth > 0) {
ret @node(bottom_up_tree(2 * item - 1, depth - 1),
bottom_up_tree(2 * item, depth - 1),
item);
} else {
ret @nil;
}
fn bottom_up_tree(int item, int depth) -> @tree {
if (depth > 0) {
ret @node(bottom_up_tree(2 * item - 1, depth - 1),
bottom_up_tree(2 * item, depth - 1), item);
} else { ret @nil; }
}
fn main() {
auto n = 8;
auto min_depth = 4;
auto max_depth;
if (min_depth + 2 > n) {
max_depth = min_depth + 2;
} else {
max_depth = n;
}
auto stretch_depth = max_depth + 1;
auto stretch_tree = bottom_up_tree(0, stretch_depth);
log #fmt("stretch tree of depth %d\t check: %d",
stretch_depth, item_check(stretch_tree));
auto long_lived_tree = bottom_up_tree(0, max_depth);
auto depth = min_depth;
while (depth <= max_depth) {
auto iterations = int::pow(2, (max_depth - depth + min_depth) as uint);
auto chk = 0;
auto i = 1;
while (i <= iterations) {
auto temp_tree = bottom_up_tree(i, depth);
chk += item_check(temp_tree);
temp_tree = bottom_up_tree(-i, depth);
chk += item_check(temp_tree);
i += 1;
auto n = 8;
auto min_depth = 4;
auto max_depth;
if (min_depth + 2 > n) {
max_depth = min_depth + 2;
} else { max_depth = n; }
auto stretch_depth = max_depth + 1;
auto stretch_tree = bottom_up_tree(0, stretch_depth);
log #fmt("stretch tree of depth %d\t check: %d", stretch_depth,
item_check(stretch_tree));
auto long_lived_tree = bottom_up_tree(0, max_depth);
auto depth = min_depth;
while (depth <= max_depth) {
auto iterations = int::pow(2, max_depth - depth + min_depth as uint);
auto chk = 0;
auto i = 1;
while (i <= iterations) {
auto temp_tree = bottom_up_tree(i, depth);
chk += item_check(temp_tree);
temp_tree = bottom_up_tree(-i, depth);
chk += item_check(temp_tree);
i += 1;
}
log #fmt("%d\t trees of depth %d\t check: %d", iterations * 2, depth,
chk);
depth += 2;
}
log #fmt("%d\t trees of depth %d\t check: %d",
iterations * 2, depth, chk);
depth += 2;
}
log #fmt("long lived trees of depth %d\t check: %d",
max_depth, item_check(long_lived_tree));
log #fmt("long lived trees of depth %d\t check: %d", max_depth,
item_check(long_lived_tree));
}

View File

@ -1,99 +1,64 @@
// Based on Isaac Gouy's fannkuchredux.csharp
use std;
import std::int;
import std::vec;
fn fannkuch(int n) -> int {
fn perm1init(uint i) -> int { ret i as int; }
auto perm1init_ = perm1init; // Rustboot workaround
fn perm1init(uint i) -> int {
ret i as int;
}
auto perm1init_ = perm1init; // Rustboot workaround
auto perm = vec::init_elt_mut(0, n as uint);
auto perm1 = vec::init_fn_mut(perm1init_, n as uint);
auto count = vec::init_elt_mut(0, n as uint);
auto f = 0;
auto i = 0;
auto k = 0;
auto r = 0;
auto flips = 0;
auto nperm = 0;
auto checksum = 0;
r = n;
while (r > 0) {
i = 0;
while (r != 1) { count.(r - 1) = r; r -= 1; }
while (i < n) { perm.(i) = perm1.(i); i += 1; }
// Count flips and update max and checksum
auto perm = vec::init_elt_mut(0, n as uint);
auto perm1 = vec::init_fn_mut(perm1init_, n as uint);
auto count = vec::init_elt_mut(0, n as uint);
f = 0;
k = perm.(0);
while (k != 0) {
i = 0;
while (2 * i < k) {
auto t = perm.(i);
perm.(i) = perm.(k - i);
perm.(k - i) = t;
i += 1;
}
k = perm.(0);
f += 1;
}
if (f > flips) { flips = f; }
if (nperm & 0x1 == 0) { checksum += f; } else { checksum -= f; }
// Use incremental change to generate another permutation
auto f = 0;
auto i = 0;
auto k = 0;
auto r = 0;
auto flips = 0;
auto nperm = 0;
auto checksum = 0;
r = n;
while (r > 0) {
i = 0;
while (r != 1) {
count.(r - 1) = r;
r -=1;
auto go = true;
while (go) {
if (r == n) { log checksum; ret flips; }
auto p0 = perm1.(0);
i = 0;
while (i < r) { auto j = i + 1; perm1.(i) = perm1.(j); i = j; }
perm1.(r) = p0;
count.(r) -= 1;
if (count.(r) > 0) { go = false; } else { r += 1; }
}
nperm += 1;
}
while (i < n) {
perm.(i) = perm1.(i);
i += 1;
}
// Count flips and update max and checksum
f = 0;
k = perm.(0);
while (k != 0) {
i = 0;
while (2 * i < k) {
auto t = perm.(i);
perm.(i) = perm.(k - i);
perm.(k - i) = t;
i += 1;
}
k = perm.(0);
f += 1;
}
if (f > flips) {
flips = f;
}
if ((nperm & 0x1) == 0) {
checksum += f;
} else {
checksum -= f;
}
// Use incremental change to generate another permutation
auto go = true;
while (go) {
if (r == n) {
log checksum;
ret flips;
}
auto p0 = perm1.(0);
i = 0;
while (i < r) {
auto j = i + 1;
perm1.(i) = perm1.(j);
i = j;
}
perm1.(r) = p0;
count.(r) -= 1;
if (count.(r) > 0) {
go = false;
} else {
r += 1;
}
}
nperm += 1;
}
ret flips;
ret flips;
}
fn main(vec[str] args) {
auto n = 7;
log #fmt("Pfannkuchen(%d) = %d", n, fannkuch(n));
auto n = 7;
log #fmt("Pfannkuchen(%d) = %d", n, fannkuch(n));
}

View File

@ -1,3 +1,5 @@
/* -*- mode: rust; indent-tabs-mode: nil -*-
* Implementation of 'fasta' benchmark from
* Computer Language Benchmarks Game
@ -9,119 +11,80 @@ import std::str;
import std::uint;
import std::int;
fn LINE_LENGTH() -> uint {
ret 60u;
}
fn LINE_LENGTH() -> uint { ret 60u; }
obj myrandom(mutable u32 last) {
fn next(u32 mx) -> u32 {
last = (last * 3877u32 + 29573u32) % 139968u32;
auto ans = (mx*last) / 139968u32;
ret ans;
}
fn next(u32 mx) -> u32 {
last = (last * 3877u32 + 29573u32) % 139968u32;
auto ans = mx * last / 139968u32;
ret ans;
}
}
type aminoacids = tup(char, u32);
fn make_cumulative(vec[aminoacids] aa) -> vec[aminoacids] {
let u32 cp = 0u32;
let vec[aminoacids] ans = [];
for (aminoacids a in aa) {
cp += a._1;
ans += [tup(a._0, cp)];
}
ret ans;
let u32 cp = 0u32;
let vec[aminoacids] ans = [];
for (aminoacids a in aa) { cp += a._1; ans += [tup(a._0, cp)]; }
ret ans;
}
fn select_random(u32 r, vec[aminoacids] genelist) -> char {
if (r < genelist.(0)._1) {
ret genelist.(0)._0;
}
fn bisect(vec[aminoacids] v, uint lo, uint hi, u32 target) -> char {
if (hi > (lo + 1u)) {
let uint mid = lo + (hi - lo) / 2u;
if (target < v.(mid)._1) {
be bisect(v, lo, mid, target);
}
else {
be bisect(v, mid, hi, target);
}
if (r < genelist.(0)._1) { ret genelist.(0)._0; }
fn bisect(vec[aminoacids] v, uint lo, uint hi, u32 target) -> char {
if (hi > lo + 1u) {
let uint mid = lo + (hi - lo) / 2u;
if (target < v.(mid)._1) {
be bisect(v, lo, mid, target);
} else { be bisect(v, mid, hi, target); }
} else { ret v.(hi)._0; }
}
else {
ret v.(hi)._0;
}
}
ret bisect(genelist, 0u, vec::len[aminoacids](genelist) - 1u, r);
ret bisect(genelist, 0u, vec::len[aminoacids](genelist) - 1u, r);
}
fn make_random_fasta(str id, str desc, vec[aminoacids] genelist, int n) {
log(">" + id + " " + desc);
auto rng = myrandom(std::rand::mk_rng().next());
let str op = "";
for each (uint i in uint::range(0u, n as uint)) {
str::push_byte(op, select_random(rng.next(100u32), genelist) as u8);
if (str::byte_len(op) >= LINE_LENGTH()) {
log(op);
op = "";
log ">" + id + " " + desc;
auto rng = myrandom(std::rand::mk_rng().next());
let str op = "";
for each (uint i in uint::range(0u, n as uint)) {
str::push_byte(op, select_random(rng.next(100u32), genelist) as u8);
if (str::byte_len(op) >= LINE_LENGTH()) { log op; op = ""; }
}
}
if (str::byte_len(op) > 0u) {
log(op);
}
if (str::byte_len(op) > 0u) { log op; }
}
fn make_repeat_fasta(str id, str desc, str s, int n) {
log(">" + id + " " + desc);
let str op = "";
let uint sl = str::byte_len(s);
for each (uint i in uint::range(0u, n as uint)) {
str::push_byte(op, s.(i % sl));
if (str::byte_len(op) >= LINE_LENGTH()) {
log(op);
op = "";
log ">" + id + " " + desc;
let str op = "";
let uint sl = str::byte_len(s);
for each (uint i in uint::range(0u, n as uint)) {
str::push_byte(op, s.(i % sl));
if (str::byte_len(op) >= LINE_LENGTH()) { log op; op = ""; }
}
}
if (str::byte_len(op) > 0u) {
log(op);
}
if (str::byte_len(op) > 0u) { log op; }
}
fn main(vec[str] args) {
let vec[aminoacids] iub = make_cumulative([tup( 'a', 27u32 ),
tup( 'c', 12u32 ),
tup( 'g', 12u32 ),
tup( 't', 27u32 ),
tup( 'B', 2u32 ),
tup( 'D', 2u32 ),
tup( 'H', 2u32 ),
tup( 'K', 2u32 ),
tup( 'M', 2u32 ),
tup( 'N', 2u32 ),
tup( 'R', 2u32 ),
tup( 'S', 2u32 ),
tup( 'V', 2u32 ),
tup( 'W', 2u32 ),
tup( 'Y', 2u32 )]);
let vec[aminoacids] homosapiens = make_cumulative([tup( 'a', 30u32 ),
tup( 'c', 20u32 ),
tup( 'g', 20u32 ),
tup( 't', 30u32 )]);
let str alu =
"GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG" +
"GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA" +
"CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT" +
"ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA" +
"GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG" +
"AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC" +
"AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA";
let int n = 512;
make_repeat_fasta ("ONE", "Homo sapiens alu", alu, n*2);
make_random_fasta("TWO", "IUB ambiguity codes", iub, n*3);
make_random_fasta ("THREE", "Homo sapiens frequency", homosapiens, n*5);
}
let vec[aminoacids] iub =
make_cumulative([tup('a', 27u32), tup('c', 12u32), tup('g', 12u32),
tup('t', 27u32), tup('B', 2u32), tup('D', 2u32),
tup('H', 2u32), tup('K', 2u32), tup('M', 2u32),
tup('N', 2u32), tup('R', 2u32), tup('S', 2u32),
tup('V', 2u32), tup('W', 2u32), tup('Y', 2u32)]);
let vec[aminoacids] homosapiens =
make_cumulative([tup('a', 30u32), tup('c', 20u32), tup('g', 20u32),
tup('t', 30u32)]);
let str alu =
"GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG" +
"GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA" +
"CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT" +
"ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA" +
"GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG" +
"AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC" +
"AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA";
let int n = 512;
make_repeat_fasta("ONE", "Homo sapiens alu", alu, n * 2);
make_random_fasta("TWO", "IUB ambiguity codes", iub, n * 3);
make_random_fasta("THREE", "Homo sapiens frequency", homosapiens, n * 5);
}

View File

@ -1,22 +1,19 @@
// -*- rust -*-
// -*- rust -*-
fn fib(int n) -> int {
// Several of the posted 'benchmark' versions of this compute the
// wrong Fibonacci numbers, of course.
if (n == 0) {
ret 0;
} else {
if (n <= 2) {
ret 1;
} else {
ret fib(n-1) + fib(n-2);
}
}
// Several of the posted 'benchmark' versions of this compute the
// wrong Fibonacci numbers, of course.
if (n == 0) {
ret 0;
} else { if (n <= 2) { ret 1; } else { ret fib(n - 1) + fib(n - 2); } }
}
fn main() {
assert (fib(8) == 21);
assert (fib(15) == 610);
log fib(8);
log fib(15);
}
assert (fib(8) == 21);
assert (fib(15) == 610);
log fib(8);
log fib(15);
}

View File

@ -1,18 +1,16 @@
// error-pattern:explicit failure
use std;
import std::option::*;
fn foo(str s) {
}
fn foo(str s) { }
fn main() {
auto i = alt (some[int](3)) {
case (none[int]) {
fail
}
case (some[int](_)) {
fail
}
};
foo(i);
}
auto i =
alt (some[int](3)) {
case (none[int]) { fail }
case (some[int](_)) { fail }
};
foo(i);
}

View File

@ -1,5 +1,5 @@
// error-pattern:woooo
fn main() {
fail "woooo";
}
// error-pattern:woooo
fn main() { fail"woooo"; }

View File

@ -1,5 +1,5 @@
// error-pattern:explicit
fn main() {
fail;
}
// error-pattern:explicit
fn main() { fail; }

View File

@ -1,19 +1,12 @@
// error-pattern:explicit failure
// error-pattern:explicit failure
fn f() -> ! { fail }
fn g() -> int {
auto x = alt (true) {
case (true) {
f()
}
case (false) {
10
}
};
ret x;
auto x = alt (true) { case (true) { f() } case (false) { 10 } };
ret x;
}
fn main() {
g();
}
fn main() { g(); }

View File

@ -1,12 +1,5 @@
// error-pattern:explicit failure
fn main() {
auto x = alt(true) {
case (false) {
0
}
case (true) {
fail
}
};
}
// error-pattern:explicit failure
fn main() { auto x = alt (true) { case (false) { 0 } case (true) { fail } }; }

View File

@ -1,7 +1,7 @@
// error-pattern:explicit failure
// error-pattern:explicit failure
fn f() -> ! { fail }
fn main() {
f();
}
fn main() { f(); }

View File

@ -1,16 +1,9 @@
// error-pattern:explicit failure
// error-pattern:explicit failure
fn f() -> ! { fail }
fn g() -> int {
auto x = if (true) {
f()
} else {
10
};
ret x;
}
fn g() -> int { auto x = if (true) { f() } else { 10 }; ret x; }
fn main() {
g();
}
fn main() { g(); }

View File

@ -1,11 +1,5 @@
// error-pattern:explicit failure
fn main() {
auto x = if (false) {
0
} else if (true) {
fail
} else {
10
};
}
// error-pattern:explicit failure
fn main() { auto x = if (false) { 0 } else if (true) { fail } else { 10 }; }

View File

@ -1,5 +1,5 @@
// error-pattern:1 == 2
fn main() {
assert (1 == 2);
}
// error-pattern:1 == 2
fn main() { assert (1 == 2); }

View File

@ -1,15 +1,9 @@
// -*- rust -*-
// error-pattern:non-exhaustive match failure
tag t { a; b; }
tag t {
a;
b;
}
fn main() {
auto x = a;
alt (x) {
case (b) { }
}
}
fn main() { auto x = a; alt (x) { case (b) { } } }

View File

@ -1,17 +1,11 @@
// -*- rust -*-
// xfail-stage0
// error-pattern:Predicate lt(b, a) failed
fn f(int a, int b) { }
fn f(int a, int b) : lt(a,b) {
}
pred lt(int a, int b) -> bool { ret a < b; }
pred lt(int a, int b) -> bool {
ret a < b;
}
fn main() {
let int a = 10;
let int b = 23;
check lt(b,a);
f(b,a);
}
fn main() { let int a = 10; let int b = 23; check (lt(b, a)); f(b, a); }

View File

@ -1,10 +1,8 @@
// Tests that trans treats the rhs of pth's decl
// as a _|_-typed thing, not a str-typed thing
// xfail-stage0
// error-pattern:bye
fn main() {
auto pth = fail "bye";
let rec(str t) res = rec(t=pth);
}
fn main() { auto pth = fail"bye"; let rec(str t) res = rec(t=pth); }

View File

@ -1,16 +1,18 @@
// -*- rust -*-
// error-pattern:bounds check
fn main() {
let str s = "hello";
let int x = 0;
assert (s.(x) == (0x68 as u8));
let str s = "hello";
let int x = 0;
assert (s.(x) == 0x68 as u8);
// NB: at the moment a string always has a trailing NULL,
// so the largest index value on the string above is 5, not
// 4. Possibly change this.
// NB: at the moment a string always has a trailing NULL,
// so the largest index value on the string above is 5, not
// 4. Possibly change this.
// Bounds-check failure.
// Bounds-check failure.
assert (s.(x + 6) == (0x0 as u8));
}
assert (s.(x + 6) == 0x0 as u8);
}

View File

@ -1,17 +1,18 @@
// xfail-stage0
// xfail-stage1
// xfail-stage2
/*
This program should hang on the po |> r line.
*/
fn main() {
let port[int] po = port();
let chan[int] ch = chan(po);
auto r; po |> r;
auto r;
po |> r;
ch <| 42;
log_err r;
}
}

View File

@ -1,11 +1,14 @@
// -*- rust -*-
// error-pattern:bounds check
fn main() {
let vec[int] v = [10];
let int x = 0;
assert (v.(x) == 10);
// Bounds-check failure.
assert (v.(x + 2) == 20);
}
let vec[int] v = [10];
let int x = 0;
assert (v.(x) == 10);
// Bounds-check failure.
assert (v.(x + 2) == 20);
}

View File

@ -1,11 +1,14 @@
// -*- rust -*-
// error-pattern:bounds check
fn main() {
let vec[int] v = [10, 20];
let int x = 0;
assert (v.(x) == 10);
// Bounds-check failure.
assert (v.(x-1) == 20);
}
let vec[int] v = [10, 20];
let int x = 0;
assert (v.(x) == 10);
// Bounds-check failure.
assert (v.(x - 1) == 20);
}

View File

@ -1,23 +1,16 @@
// Regression test for issue #374
// Regression test for issue #374
use std;
import std::option;
import std::option::none;
tag sty {
ty_nil;
}
tag sty { ty_nil; }
type raw_t = rec(sty struct,
option::t[str] cname,
uint hash);
type raw_t = rec(sty struct, option::t[str] cname, uint hash);
fn mk_raw_ty(sty st, &option::t[str] cname) -> raw_t {
ret rec(struct=st,
cname=cname,
hash=0u);
ret rec(struct=st, cname=cname, hash=0u);
}
fn main() {
mk_raw_ty(ty_nil, none[str]);
}
fn main() { mk_raw_ty(ty_nil, none[str]); }

View File

@ -1,15 +1,14 @@
// xfail-stage0
use std;
import std::option::*;
fn main() {
let int i = alt (some[int](3)) {
case (none[int]) {
fail
}
case (some[int](_)) {
5
}
};
log i;
let int i =
alt (some[int](3)) {
case (none[int]) { fail }
case (some[int](_)) { 5 }
};
log i;
}

View File

@ -1,3 +1,4 @@
use std;
import std::option;
import std::option::t;
@ -5,30 +6,17 @@ import std::option::none;
import std::option::some;
fn foo[T](&option::t[T] y) {
let int x;
let vec[int] res = [];
/* tests that x doesn't get put in the precondition for the
entire if expression */
if (true) {
}
else {
alt (y) {
case (none[T]) {
x = 17;
}
case (_) {
x = 42;
}
}
res += [x];
}
let int x;
let vec[int] res = [];
/* tests that x doesn't get put in the precondition for the
entire if expression */
ret;
if (true) {
} else {
alt (y) { case (none[T]) { x = 17; } case (_) { x = 42; } }
res += [x];
}
ret;
}
fn main() {
log("hello");
foo[int](some[int](5));
}
fn main() { log "hello"; foo[int](some[int](5)); }

View File

@ -1,14 +1,9 @@
mod m1 {
tag foo {
foo1;
foo2;
}
}
fn bar(m1::foo x) {
alt(x) {
case (m1::foo1) {
}
}
}
fn main(vec[str] args) {
tag foo { foo1; foo2; }
}
fn bar(m1::foo x) { alt (x) { case (m1::foo1) { } } }
fn main(vec[str] args) { }

View File

@ -1,32 +1,35 @@
// -*- rust -*-
// -*- rust -*-
use std;
import std::str;
// FIXME: import std::dbg.const_refcount. Currently
// cross-crate const references don't work.
const uint const_refcount = 0x7bad_face_u;
tag t {
make_t(str);
clam;
}
tag t { make_t(str); clam; }
fn foo(str s) {
let t x = make_t(s); // ref up
let t x = make_t(s); // ref up
alt (x) {
case (make_t(?y)) { log y; } // ref up then down
case (_) { log "?"; fail; }
}
alt (x) {
case (make_t(?y)) {
log y; // ref up then down
log str::refcount(s);
assert (str::refcount(s) == const_refcount);
}
case (_) { log "?"; fail; }
}
log str::refcount(s);
assert (str::refcount(s) == const_refcount);
}
fn main() {
let str s = "hi"; // ref up
foo(s); // ref up then down
log str::refcount(s);
assert (str::refcount(s) == const_refcount);
}
let str s = "hi"; // ref up
foo(s); // ref up then down
log str::refcount(s);
assert (str::refcount(s) == const_refcount);
}

Some files were not shown because too many files have changed in this diff Show More