From a3ec0b1f643d00b9418e4884bd7caa07bf052201 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Fri, 6 May 2011 22:13:13 +0200 Subject: Rename std modules to be camelcased (Have fun mergining your stuff with this.) --- src/lib/BitV.rs | 222 +++++++++++++++++++++ src/lib/Dbg.rs | 74 +++++++ src/lib/Deque.rs | 145 ++++++++++++++ src/lib/EBML.rs | 186 +++++++++++++++++ src/lib/ExtFmt.rs | 76 +++---- src/lib/FS.rs | 56 ++++++ src/lib/GenericOS.rs | 2 +- src/lib/GetOpts.rs | 80 ++++---- src/lib/IO.rs | 531 +++++++++++++++++++++++++++++++++++++++++++++++++ src/lib/Int.rs | 62 ++++++ src/lib/List.rs | 66 ++++++ src/lib/Map.rs | 246 +++++++++++++++++++++++ src/lib/Option.rs | 60 ++++++ src/lib/Rand.rs | 34 ++++ src/lib/Run_Program.rs | 96 +++++++++ src/lib/SHA1.rs | 294 +++++++++++++++++++++++++++ src/lib/Sort.rs | 101 ++++++++++ src/lib/Str.rs | 501 ++++++++++++++++++++++++++++++++++++++++++++++ src/lib/Sys.rs | 30 +++ src/lib/Task.rs | 21 ++ src/lib/Term.rs | 12 +- src/lib/U8.rs | 28 +++ src/lib/UFind.rs | 10 +- src/lib/UInt.rs | 107 ++++++++++ src/lib/Util.rs | 33 +++ src/lib/Vec.rs | 318 +++++++++++++++++++++++++++++ src/lib/_int.rs | 62 ------ src/lib/_str.rs | 501 ---------------------------------------------- src/lib/_task.rs | 21 -- src/lib/_u8.rs | 28 --- src/lib/_uint.rs | 107 ---------- src/lib/_vec.rs | 318 ----------------------------- src/lib/bitv.rs | 222 --------------------- src/lib/dbg.rs | 74 ------- src/lib/deque.rs | 145 -------------- src/lib/ebml.rs | 186 ----------------- src/lib/fs.rs | 56 ------ src/lib/io.rs | 531 ------------------------------------------------- src/lib/linux_OS.rs | 90 +++++++++ src/lib/linux_os.rs | 90 --------- src/lib/list.rs | 66 ------ src/lib/macos_OS.rs | 87 ++++++++ src/lib/macos_os.rs | 87 -------- src/lib/map.rs | 246 ----------------------- src/lib/option.rs | 60 ------ src/lib/posix_FS.rs | 32 +++ src/lib/posix_fs.rs | 32 --- src/lib/rand.rs | 34 ---- src/lib/run_program.rs | 96 --------- src/lib/sha1.rs | 294 --------------------------- src/lib/sort.rs | 101 ---------- src/lib/std.rc | 77 ++++--- src/lib/sys.rs | 30 --- src/lib/util.rs | 33 --- src/lib/win32_FS.rs | 26 +++ src/lib/win32_OS.rs | 80 ++++++++ src/lib/win32_fs.rs | 26 --- src/lib/win32_os.rs | 80 -------- 58 files changed, 3654 insertions(+), 3655 deletions(-) create mode 100644 src/lib/BitV.rs create mode 100644 src/lib/Dbg.rs create mode 100644 src/lib/Deque.rs create mode 100644 src/lib/EBML.rs create mode 100644 src/lib/FS.rs create mode 100644 src/lib/IO.rs create mode 100644 src/lib/Int.rs create mode 100644 src/lib/List.rs create mode 100644 src/lib/Map.rs create mode 100644 src/lib/Option.rs create mode 100644 src/lib/Rand.rs create mode 100644 src/lib/Run_Program.rs create mode 100644 src/lib/SHA1.rs create mode 100644 src/lib/Sort.rs create mode 100644 src/lib/Str.rs create mode 100644 src/lib/Sys.rs create mode 100644 src/lib/Task.rs create mode 100644 src/lib/U8.rs create mode 100644 src/lib/UInt.rs create mode 100644 src/lib/Util.rs create mode 100644 src/lib/Vec.rs delete mode 100644 src/lib/_int.rs delete mode 100644 src/lib/_str.rs delete mode 100644 src/lib/_task.rs delete mode 100644 src/lib/_u8.rs delete mode 100644 src/lib/_uint.rs delete mode 100644 src/lib/_vec.rs delete mode 100644 src/lib/bitv.rs delete mode 100644 src/lib/dbg.rs delete mode 100644 src/lib/deque.rs delete mode 100644 src/lib/ebml.rs delete mode 100644 src/lib/fs.rs delete mode 100644 src/lib/io.rs create mode 100644 src/lib/linux_OS.rs delete mode 100644 src/lib/linux_os.rs delete mode 100644 src/lib/list.rs create mode 100644 src/lib/macos_OS.rs delete mode 100644 src/lib/macos_os.rs delete mode 100644 src/lib/map.rs delete mode 100644 src/lib/option.rs create mode 100644 src/lib/posix_FS.rs delete mode 100644 src/lib/posix_fs.rs delete mode 100644 src/lib/rand.rs delete mode 100644 src/lib/run_program.rs delete mode 100644 src/lib/sha1.rs delete mode 100644 src/lib/sort.rs delete mode 100644 src/lib/sys.rs delete mode 100644 src/lib/util.rs create mode 100644 src/lib/win32_FS.rs create mode 100644 src/lib/win32_OS.rs delete mode 100644 src/lib/win32_fs.rs delete mode 100644 src/lib/win32_os.rs (limited to 'src/lib') diff --git a/src/lib/BitV.rs b/src/lib/BitV.rs new file mode 100644 index 00000000..b0a4c9ea --- /dev/null +++ b/src/lib/BitV.rs @@ -0,0 +1,222 @@ +// 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 +// for the case where nbits <= 32. + +// 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); + +// FIXME: this should be a constant once they work +fn uint_bits() -> uint { + ret 32u + ((1u << 32u) >> 27u); +} + +fn create(uint nbits, bool init) -> t { + auto elt; + if (init) { + elt = ~0u; + } else { + elt = 0u; + } + + auto storage = Vec.init_elt_mut[uint](elt, nbits / uint_bits() + 1u); + ret rec(storage = storage, nbits = nbits); +} + +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; + } + } + + ret changed; +} + +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 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 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); +} + +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); + 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; + } + i = i + 1u; + } + ret true; +} + +fn clear(&t v) { + for each (uint i in UInt.range(0u, Vec.len(v.storage))) { + v.storage.(i) = 0u; + } +} + +fn invert(&t v) { + for each (uint i in UInt.range(0u, Vec.len(v.storage))) { + v.storage.(i) = ~v.storage.(i); + } +} + +/* v0 = v0 - v1 */ +fn difference(&t v0, &t v1) -> bool { + invert(v1); + auto b = intersect(v0, v1); + invert(v1); + ret b; +} + +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; + if (x) { + v.storage.(w) = v.storage.(w) | flag; + } else { + v.storage.(w) = 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; + } + } + + 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; + } + } + + ret true; +} + +fn init_to_vec(t v, uint i) -> uint { + if (get(v, i)) { + ret 1u; + } else { + ret 0u; + } +} + +fn to_vec(&t v) -> vec[uint] { + auto sub = bind init_to_vec(v, _); + ret Vec.init_fn[uint](sub, v.nbits); +} + +fn to_str(&t v) -> str { + auto res = ""; + + for (uint i in BitV.to_vec(v)) { + 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)); + auto len = v0.nbits; + auto i = 0u; + while (i < len) { + auto w0 = get(v0, i); + auto w1 = v1.(i); + if ((!w0 && w1 != 0u) || (w0 && w1 == 0u)) { + ret false; + } + i = i + 1u; + } + ret true; +} + +// +// Local Variables: +// mode: rust +// fill-column: 78; +// indent-tabs-mode: nil +// c-basic-offset: 4 +// buffer-file-coding-system: utf-8-unix +// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; +// End: +// diff --git a/src/lib/Dbg.rs b/src/lib/Dbg.rs new file mode 100644 index 00000000..f155d119 --- /dev/null +++ b/src/lib/Dbg.rs @@ -0,0 +1,74 @@ +/** + * Unsafe debugging functions for inspecting values. + * + * Your RUST_LOG environment variable must contain "stdlib" for any debug + * logging. + */ + +// FIXME: handle 64-bit case. +const uint const_refcount = 0x7bad_face_u; + +native "rust" mod rustrt { + fn debug_tydesc[T](); + fn debug_opaque[T](&T x); + fn debug_box[T](@T x); + fn debug_tag[T](&T x); + fn debug_obj[T](&T x, uint nmethods, uint nbytes); + fn debug_fn[T](&T x); + fn debug_ptrcast[T, U](@T x) -> @U; + fn debug_trap(str msg); +} + +fn debug_vec[T](vec[T] v) { + Vec.print_debug_info[T](v); +} + +fn debug_tydesc[T]() { + rustrt.debug_tydesc[T](); +} + +fn debug_opaque[T](&T x) { + rustrt.debug_opaque[T](x); +} + +fn debug_box[T](@T x) { + rustrt.debug_box[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 + * runtime will print this many words of the obj vtbl). + * + * `nbytes` is the number of bytes of body data we expect the object to have. + * The runtime will print this many bytes of the obj body. You probably want + * this to at least be 4u, since an implicit captured tydesc pointer sits in + * the front of any obj's data tuple.x + */ +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 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; +// indent-tabs-mode: nil +// c-basic-offset: 4 +// buffer-file-coding-system: utf-8-unix +// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; +// End: diff --git a/src/lib/Deque.rs b/src/lib/Deque.rs new file mode 100644 index 00000000..a38e4fec --- /dev/null +++ b/src/lib/Deque.rs @@ -0,0 +1,145 @@ +/** + * 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; +}; + +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. + */ + fn grow[T](uint nelts, uint lo, vec[cell[T]] elts) -> vec[cell[T]] { + assert (nelts == Vec.len[cell[T]](elts)); + + fn fill[T](uint i, uint nelts, uint lo, + vec[cell[T]] old) -> cell[T] { + if (i < nelts) { + ret old.((lo + i) % nelts); + } else { + ret Option.none[T]; + } + } + + 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[cell[T]](copy_op, nalloc); + } + + fn get[T](vec[cell[T]] elts, uint i) -> T { + alt (elts.(i)) { + case (Option.some[T](?t)) { ret t; } + case (_) { fail; } + } + fail; // FIXME: remove me when exhaustiveness checking works + } + + obj deque[T](mutable uint nelts, + mutable uint lo, + mutable uint hi, + mutable vec[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; + } + + 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); + } + + } + let vec[cell[T]] v = Vec.init_elt[cell[T]](Option.none[T], + initial_capacity); + + ret deque[T](0u, 0u, 0u, v); +} + +// Local Variables: +// mode: rust; +// fill-column: 78; +// indent-tabs-mode: nil +// c-basic-offset: 4 +// buffer-file-coding-system: utf-8-unix +// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; +// End: diff --git a/src/lib/EBML.rs b/src/lib/EBML.rs new file mode 100644 index 00000000..9b17bf06 --- /dev/null +++ b/src/lib/EBML.rs @@ -0,0 +1,186 @@ +// 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); + +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 & 0x40u8 != 0u8) { + 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); + } 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; + } +} + +fn new_doc(vec[u8] data) -> doc { + ret rec(data=data, start=0u, end=Vec.len[u8](data)); +} + +fn doc_at(vec[u8] data, uint start) -> doc { + auto elt_tag = vint_at(data, start); + auto elt_size = vint_at(data, elt_tag._1); + auto end = elt_size._1 + elt_size._0; + ret rec(data=data, start=elt_size._1, end=end); +} + +fn maybe_get_doc(doc d, uint tg) -> Option.t[doc] { + auto pos = d.start; + while (pos < d.end) { + auto elt_tag = vint_at(d.data, pos); + auto elt_size = vint_at(d.data, elt_tag._1); + pos = elt_size._1 + elt_size._0; + if (elt_tag._0 == tg) { + ret some[doc](rec(data=d.data, start=elt_size._1, end=pos)); + } + } + ret none[doc]; +} + +fn get_doc(doc d, uint tg) -> doc { + alt (maybe_get_doc(d, tg)) { + case (some[doc](?d)) {ret d;} + case (none[doc]) { + log_err "failed to find block with tag " + UInt.to_str(tg, 10u); + fail; + } + } +} + +iter docs(doc d) -> tup(uint, doc) { + auto pos = d.start; + while (pos < d.end) { + auto elt_tag = vint_at(d.data, pos); + auto elt_size = vint_at(d.data, elt_tag._1); + pos = elt_size._1 + elt_size._0; + put tup(elt_tag._0, rec(data=d.data, start=elt_size._1, end=pos)); + } +} + +iter tagged_docs(doc d, uint tg) -> doc { + auto pos = d.start; + while (pos < d.end) { + auto elt_tag = vint_at(d.data, pos); + auto elt_size = vint_at(d.data, elt_tag._1); + pos = elt_size._1 + elt_size._0; + if (elt_tag._0 == tg) { + put rec(data=d.data, start=elt_size._1, end=pos); + } + } +} + +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; + assert (sz <= 4u); + auto val = 0u; + auto pos = start; + while (sz > 0u) { + sz -= 1u; + val += (data.(pos) as uint) << (sz * 8u); + pos += 1u; + } + ret val; +} + +fn doc_as_uint(doc d) -> uint { + ret be_uint_from_bytes(d.data, d.start, d.end - d.start); +} + +// 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 = vec(0x80u8 | (n as u8)); + } + case (2u) { + buf = vec(0x40u8 | ((n >> 8u) as u8), + (n & 0xffu) as u8); + } + case (3u) { + buf = vec(0x20u8 | ((n >> 16u) as u8), + ((n >> 8u) & 0xffu) as u8, + (n & 0xffu) as u8); + } + case (4u) { + buf = vec(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; } + log_err "vint to write too big"; + fail; +} + +fn create_writer(&IO.buf_writer w) -> writer { + let vec[uint] size_positions = vec(); + ret rec(writer=w, mutable size_positions=size_positions); +} + +// 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 a placeholder four-byte size. + w.size_positions += vec(w.writer.tell()); + let vec[u8] zeroes = vec(0u8, 0u8, 0u8, 0u8); + w.writer.write(zeroes); +} + +fn end_tag(&writer w) { + auto last_size_pos = Vec.pop[uint](w.size_positions); + auto cur_pos = w.writer.tell(); + w.writer.seek(last_size_pos as int, IO.seek_set); + 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 diff --git a/src/lib/ExtFmt.rs b/src/lib/ExtFmt.rs index c71e49a3..0510a2a8 100644 --- a/src/lib/ExtFmt.rs +++ b/src/lib/ExtFmt.rs @@ -13,8 +13,8 @@ * combinations at the moment. */ -import option.none; -import option.some; +import Option.none; +import Option.some; /* * We have a CT (compile-time) module that parses format strings into a @@ -66,7 +66,7 @@ mod CT { } // A formatted conversion from an expression to a string - type conv = rec(option.t[int] param, + type conv = rec(Option.t[int] param, vec[flag] flags, count width, count precision, @@ -80,11 +80,11 @@ mod CT { fn parse_fmt_string(str s) -> vec[piece] { let vec[piece] pieces = vec(); - auto lim = _str.byte_len(s); + auto lim = Str.byte_len(s); auto buf = ""; fn flush_buf(str buf, &vec[piece] pieces) -> str { - if (_str.byte_len(buf) > 0u) { + if (Str.byte_len(buf) > 0u) { auto piece = piece_string(buf); pieces += vec(piece); } @@ -93,15 +93,15 @@ mod CT { auto i = 0u; while (i < lim) { - auto curr = _str.substr(s, i, 1u); - if (_str.eq(curr, "%")) { + auto curr = Str.substr(s, i, 1u); + if (Str.eq(curr, "%")) { i += 1u; if (i >= lim) { log_err "unterminated conversion at end of string"; fail; } - auto curr2 = _str.substr(s, i, 1u); - if (_str.eq(curr2, "%")) { + auto curr2 = Str.substr(s, i, 1u); + if (Str.eq(curr2, "%")) { i += 1u; } else { buf = flush_buf(buf, pieces); @@ -118,14 +118,14 @@ mod CT { ret pieces; } - fn peek_num(str s, uint i, uint lim) -> option.t[tup(uint, uint)] { + fn peek_num(str s, uint i, uint lim) -> Option.t[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)]; + ret Option.none[tup(uint, uint)]; } auto n = (c - ('0' as u8)) as uint; @@ -156,7 +156,7 @@ mod CT { ty._1); } - fn parse_parameter(str s, uint i, uint lim) -> tup(option.t[int], uint) { + fn parse_parameter(str s, uint i, uint lim) -> tup(Option.t[int], uint) { if (i >= lim) { ret tup(none[int], i); } @@ -270,27 +270,27 @@ mod CT { } auto t; - auto tstr = _str.substr(s, i, 1u); - if (_str.eq(tstr, "b")) { + auto tstr = Str.substr(s, i, 1u); + if (Str.eq(tstr, "b")) { t = ty_bool; - } else if (_str.eq(tstr, "s")) { + } else if (Str.eq(tstr, "s")) { t = ty_str; - } else if (_str.eq(tstr, "c")) { + } else if (Str.eq(tstr, "c")) { t = ty_char; - } else if (_str.eq(tstr, "d") - || _str.eq(tstr, "i")) { + } 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? t = ty_int(signed); - } else if (_str.eq(tstr, "u")) { + } else if (Str.eq(tstr, "u")) { t = ty_int(unsigned); - } else if (_str.eq(tstr, "x")) { + } else if (Str.eq(tstr, "x")) { t = ty_hex(case_lower); - } else if (_str.eq(tstr, "X")) { + } else if (Str.eq(tstr, "X")) { t = ty_hex(case_upper); - } else if (_str.eq(tstr, "t")) { + } else if (Str.eq(tstr, "t")) { t = ty_bits; - } else if (_str.eq(tstr, "o")) { + } else if (Str.eq(tstr, "o")) { t = ty_octal; } else { log_err "unknown type in conversion"; @@ -364,7 +364,7 @@ mod RT { res = uint_to_str_prec(u, 16u, prec); } case (ty_hex_upper) { - res = _str.to_upper(uint_to_str_prec(u, 16u, prec)); + res = Str.to_upper(uint_to_str_prec(u, 16u, prec)); } case (ty_bits) { res = uint_to_str_prec(u, 2u, prec); @@ -389,7 +389,7 @@ mod RT { } fn conv_char(&conv cv, char c) -> str { - ret pad(cv, _str.from_char(c), pad_nozero); + ret pad(cv, Str.from_char(c), pad_nozero); } fn conv_str(&conv cv, str s) -> str { @@ -399,9 +399,9 @@ mod RT { } case (count_is(?max)) { // For strings, precision is the maximum characters displayed - if (max as uint < _str.char_len(s)) { + if (max as uint < Str.char_len(s)) { // FIXME: substr works on bytes, not chars! - unpadded = _str.substr(s, 0u, max as uint); + unpadded = Str.substr(s, 0u, max as uint); } } } @@ -420,15 +420,15 @@ mod RT { // Convert a uint to string with a minimum number of digits. If precision // is 0 and num is 0 then the result is the empty string. Could move this - // to _uint, but it doesn't seem all that useful. + // to UInt. but it doesn't seem all that useful. fn uint_to_str_prec(uint num, uint radix, uint prec) -> str { auto s; if (prec == 0u && num == 0u) { s = ""; } else { - s = _uint.to_str(num, radix); - auto len = _str.char_len(s); + 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); @@ -450,12 +450,12 @@ mod RT { } } - // FIXME: This might be useful in _str, but needs to be utf8 safe first + // FIXME: This might be useful in Str. but needs to be utf8 safe first fn str_init_elt(char c, uint n_elts) -> str { - auto svec = _vec.init_elt[u8](c as u8, n_elts); + 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); + ret Str.unsafe_from_bytes(svec); } tag pad_mode { @@ -476,7 +476,7 @@ mod RT { } } - auto strlen = _str.char_len(s); + auto strlen = Str.char_len(s); if (uwidth <= strlen) { ret s; } @@ -532,16 +532,16 @@ mod RT { // instead. if (signed && zero_padding - && _str.byte_len(s) > 0u) { + && Str.byte_len(s) > 0u) { auto head = s.(0); if (head == '+' as u8 || head == '-' as u8 || head == ' ' as u8) { - auto headstr = _str.unsafe_from_bytes(vec(head)); - auto bytelen = _str.byte_len(s); - auto numpart = _str.substr(s, 1u, bytelen - 1u); + auto headstr = Str.unsafe_from_bytes(vec(head)); + auto bytelen = Str.byte_len(s); + auto numpart = Str.substr(s, 1u, bytelen - 1u); ret headstr + padstr + numpart; } } diff --git a/src/lib/FS.rs b/src/lib/FS.rs new file mode 100644 index 00000000..69edf247 --- /dev/null +++ b/src/lib/FS.rs @@ -0,0 +1,56 @@ +native "rust" mod rustrt { + fn rust_file_is_dir(str path) -> int; +} + +fn path_sep() -> str { + ret Str.from_char(OS_FS.path_sep); +} + +type path = str; + +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; + } + } + ret Str.substr(p, 0u, i as uint); +} + +fn connect(path pre, path post) -> path { + auto len = Str.byte_len(pre); + if (pre.(len - 1u) == (OS_FS.path_sep as u8)) { // Trailing '/'? + ret pre + post; + } + ret pre + path_sep() + post; +} + +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 = vec(); + 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; +// indent-tabs-mode: nil +// c-basic-offset: 4 +// buffer-file-coding-system: utf-8-unix +// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; +// End: diff --git a/src/lib/GenericOS.rs b/src/lib/GenericOS.rs index 2d375652..c60fa2b8 100644 --- a/src/lib/GenericOS.rs +++ b/src/lib/GenericOS.rs @@ -1,4 +1,4 @@ fn getenv(str n) -> str { - ret _str.str_from_cstr(os.libc.getenv(_str.buf(n))); + ret Str.str_from_cstr(OS.libc.getenv(Str.buf(n))); } diff --git a/src/lib/GetOpts.rs b/src/lib/GetOpts.rs index f85ce85c..0cacf3ff 100644 --- a/src/lib/GetOpts.rs +++ b/src/lib/GetOpts.rs @@ -7,8 +7,8 @@ * argument values out of the match object. */ -import option.some; -import option.none; +import Option.some; +import Option.none; tag name { long(str); short(char); } tag hasarg { yes; no; maybe; } @@ -17,7 +17,7 @@ tag occur { req; optional; multi; } type opt = rec(name name, hasarg hasarg, occur occur); fn mkname(str nm) -> name { - if (_str.char_len(nm) == 1u) { ret short(_str.char_at(nm, 0u)); } + if (Str.char_len(nm) == 1u) { ret short(Str.char_at(nm, 0u)); } else { ret long(nm); } } fn reqopt(str name) -> opt { @@ -41,11 +41,11 @@ tag optval { 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; + ret Str.byte_len(arg) > 1u && arg.(0) == '-' as u8; } fn name_str(name nm) -> str { alt (nm) { - case (short(?ch)) {ret _str.from_char(ch);} + case (short(?ch)) {ret Str.from_char(ch);} case (long(?s)) {ret s;} } } @@ -55,16 +55,16 @@ fn name_eq(name a, name b) -> bool { alt (a) { case (long(?a)) { alt (b) { - case (long(?b)) { ret _str.eq(a, b); } + case (long(?b)) { ret Str.eq(a, b); } case (_) { ret false; } } } case (_) { if (a == b) { ret true; } else {ret false; } } } } -fn find_opt(vec[opt] opts, name nm) -> option.t[uint] { +fn find_opt(vec[opt] opts, name nm) -> Option.t[uint] { auto i = 0u; - auto l = _vec.len[opt](opts); + auto l = Vec.len[opt](opts); while (i < l) { if (name_eq(opts.(i).name, nm)) { ret some[uint](i); } i += 1u; @@ -102,41 +102,41 @@ tag result { } 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]();} + auto n_opts = Vec.len[opt](opts); + fn empty_(uint x) -> vec[optval]{ret Vec.empty[optval]();} auto f = empty_; - auto vals = _vec.init_fn_mut[vec[optval]](f, n_opts); + auto vals = Vec.init_fn_mut[vec[optval]](f, n_opts); let vec[str] free = vec(); - auto l = _vec.len[str](args); + auto l = Vec.len[str](args); auto i = 0u; while (i < l) { auto cur = args.(i); - auto curlen = _str.byte_len(cur); + auto curlen = Str.byte_len(cur); if (!is_arg(cur)) { - _vec.push[str](free, cur); - } else if (_str.eq(cur, "--")) { - free += _vec.slice[str](args, i + 1u, l); + Vec.push[str](free, cur); + } else if (Str.eq(cur, "--")) { + free += Vec.slice[str](args, i + 1u, l); break; } else { auto names; - auto i_arg = option.none[str]; + auto i_arg = Option.none[str]; if (cur.(1) == '-' as u8) { - auto tail = _str.slice(cur, 2u, curlen); - auto eq = _str.index(tail, '=' as u8); + auto tail = Str.slice(cur, 2u, curlen); + auto eq = Str.index(tail, '=' as u8); if (eq == -1) { names = vec(long(tail)); } else { - names = vec(long(_str.slice(tail, 0u, eq as uint))); - i_arg = option.some[str] - (_str.slice(tail, (eq as uint) + 1u, curlen - 2u)); + names = vec(long(Str.slice(tail, 0u, eq as uint))); + i_arg = Option.some[str] + (Str.slice(tail, (eq as uint) + 1u, curlen - 2u)); } } else { auto j = 1u; names = vec(); while (j < curlen) { - auto range = _str.char_range_at(cur, j); - _vec.push[name](names, short(range._0)); + auto range = Str.char_range_at(cur, j); + Vec.push[name](names, short(range._0)); j = range._1; } } @@ -152,29 +152,29 @@ fn getopts(vec[str] args, vec[opt] opts) -> result { } alt (opts.(optid).hasarg) { case (no) { - _vec.push[optval](vals.(optid), given); + Vec.push[optval](vals.(optid), given); } case (maybe) { - if (!option.is_none[str](i_arg)) { - _vec.push[optval](vals.(optid), - val(option.get[str](i_arg))); - } else if (name_pos < _vec.len[name](names) || + if (!Option.is_none[str](i_arg)) { + 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))) { - _vec.push[optval](vals.(optid), given); + Vec.push[optval](vals.(optid), given); } else { i += 1u; - _vec.push[optval](vals.(optid), val(args.(i))); + Vec.push[optval](vals.(optid), val(args.(i))); } } case (yes) { - if (!option.is_none[str](i_arg)) { - _vec.push[optval](vals.(optid), - val(option.get[str](i_arg))); + if (!Option.is_none[str](i_arg)) { + Vec.push[optval](vals.(optid), + val(Option.get[str](i_arg))); } else if (i + 1u == l) { ret failure(argument_missing(name_str(nm))); } else { i += 1u; - _vec.push[optval](vals.(optid), val(args.(i))); + Vec.push[optval](vals.(optid), val(args.(i))); } } } @@ -185,7 +185,7 @@ fn getopts(vec[str] args, vec[opt] opts) -> result { i = 0u; while (i < n_opts) { - auto n = _vec.len[optval](vals.(i)); + 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))); @@ -212,7 +212,7 @@ 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; + ret Vec.len[optval](opt_vals(m, nm)) > 0u; } fn opt_str(match m, str nm) -> str { alt (opt_val(m, nm)) { @@ -224,15 +224,15 @@ fn opt_strs(match m, str nm) -> vec[str] { let vec[str] acc = vec(); for (optval v in opt_vals(m, nm)) { alt (v) { - case (val(?s)) { _vec.push[str](acc, s); } + case (val(?s)) { Vec.push[str](acc, s); } case (_) {} } } ret acc; } -fn opt_maybe_str(match m, str nm) -> option.t[str] { +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]; } + if (Vec.len[optval](vals) == 0u) { ret none[str]; } alt (vals.(0)) { case (val(?s)) { ret some[str](s); } case (_) { ret none[str]; } diff --git a/src/lib/IO.rs b/src/lib/IO.rs new file mode 100644 index 00000000..60416ab1 --- /dev/null +++ b/src/lib/IO.rs @@ -0,0 +1,531 @@ +import OS.libc; + +native "rust" mod rustrt { + 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;} + +// 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; + + // FIXME: Seekable really should be orthogonal. We will need + // inheritance. + fn seek(int offset, seek_style whence); + fn tell() -> uint; + }; + +// Convenience methods for reading. +type reader = + state obj { + // FIXME: This should inherit from buf_reader. + fn get_buf_reader() -> buf_reader; + + 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]; + + fn seek(int offset, seek_style whence); + fn tell() -> uint; // FIXME: eventually u64 + }; + +fn convert_whence(seek_style whence) -> int { + alt (whence) { + case (seek_set) {ret 0;} + case (seek_cur) {ret 1;} + case (seek_end) {ret 2;} + } +} + +state 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 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); } + } +} + +// 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); + } + fn read_char() -> char { + auto c0 = rdr.read_byte(); + 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;} + auto val = 0u; + while (w > 1u) { + w -= 1u; + auto next = rdr.read_byte(); + assert (next > -1); + assert (next & 0xc0 == 0x80); + val <<= 6u; + val += (next & 0x3f) as uint; + } + // See Str.char_at + val += ((b0 << ((w + 1u) as u8)) as uint) << ((w - 1u) * 6u - w - 1u); + ret val as char; + } + fn eof() -> bool { + ret rdr.eof(); + } + fn read_line() -> str { + let vec[u8] buf = vec(); + // 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);} + } + ret Str.unsafe_from_bytes(buf); + } + fn read_c_str() -> str { + let vec[u8] buf = vec(); + 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);} + } + ret Str.unsafe_from_bytes(buf); + } + // FIXME deal with eof? + fn read_le_uint(uint size) -> uint { + auto val = 0u; + auto pos = 0u; + while (size > 0u) { + val += (rdr.read_byte() as uint) << pos; + pos += 8u; + size -= 1u; + } + ret val; + } + fn read_le_int(uint size) -> int { + auto val = 0u; + auto pos = 0u; + while (size > 0u) { + val += (rdr.read_byte() as uint) << pos; + pos += 8u; + size -= 1u; + } + 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); + } + ret val; + } + fn read_whole_stream() -> vec[u8] { + let vec[u8] buf = vec(); + 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 stdin() -> reader { + ret new_reader(FILE_buf_reader(rustrt.rust_get_stdin(), false)); +} + +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; + } + 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); +} + + +// Byte buffer readers + +// 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) { + 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; + } + 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;} + 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 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; } +} + +fn new_byte_buf_reader(vec[u8] buf) -> byte_buf_reader { + ret byte_buf_reader(@rec(buf=buf, mutable pos=0u)); +} + + +// Writing + +tag fileflag { + append; + create; + truncate; + none; +} + +type buf_writer = state obj { + fn write(vec[u8] v); + + // 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) { + 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"; + } + } + + 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);} + } +} + +state obj fd_buf_writer(int fd, bool must_close) { + fn write(vec[u8] v) { + auto len = Vec.len[u8](v); + auto count = 0u; + auto vbuf; + while (count < len) { + vbuf = Vec.buf_off[u8](v, count); + auto nout = OS.libc.write(fd, vbuf, len); + if (nout < 0) { + log_err "error dumping buffer"; + log_err Sys.rustrt.last_os_error(); + fail; + } + 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);} + } +} + +fn file_buf_writer(str path, vec[fileflag] flags) -> buf_writer { + let int fflags = + 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 (truncate) { fflags |= OS.libc_constants.O_TRUNC(); } + case (none) {} + } + } + + 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(); + fail; + } + ret fd_buf_writer(fd, true); +} + +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_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); + }; + +fn uint_to_le_bytes(uint n, uint size) -> vec[u8] { + let vec[u8] bytes = vec(); + while (size > 0u) { + bytes += vec((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 = vec(); + auto i = (size - 1u) as int; + while (i >= 0) { + bytes += vec(((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)); + } + 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_le_uint(uint n, uint size) { + out.write(uint_to_le_bytes(n, size)); + } + fn write_le_int(int n, uint size) { + out.write(uint_to_le_bytes(n as uint, size)); + } + fn write_be_uint(uint n, uint size) { + out.write(uint_to_be_bytes(n, size)); + } +} + +// FIXME: Remove me once objects are exported. +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; + } + 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)); +} + +type str_writer = + state 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) { + 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 += vec(mutable 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 = vec(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_mutable_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_end) { bpos = blen + offset; } + } + + if (bpos < 0) { + bpos = 0; + } else if (bpos > blen) { + bpos = blen; + } + + ret bpos as uint; +} + + +// +// Local Variables: +// mode: rust +// fill-column: 78; +// indent-tabs-mode: nil +// c-basic-offset: 4 +// buffer-file-coding-system: utf-8-unix +// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; +// End: +// diff --git a/src/lib/Int.rs b/src/lib/Int.rs new file mode 100644 index 00000000..59fb507f --- /dev/null +++ b/src/lib/Int.rs @@ -0,0 +1,62 @@ + +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; } + +iter range(int lo, int hi) -> int { + let int lo_ = lo; + while (lo_ < hi) { + put lo_; + lo_ += 1; + } +} + +fn to_str(int n, uint radix) -> str +{ + assert (0u < radix && radix <= 16u); + if (n < 0) { + ret "-" + UInt.to_str((-n) as uint, radix); + } else { + ret UInt.to_str(n as uint, radix); + } +} + +fn pow(int base, uint exponent) -> int { + + if (exponent == 0u) { + ret 1; + } else if (base == 0) { + ret 0; + } else { + auto accum = base; + auto count = exponent; + while (count > 1u) { + accum *= base; + count -= 1u; + } + ret accum; + } +} + +// Local Variables: +// mode: rust; +// fill-column: 78; +// indent-tabs-mode: nil +// c-basic-offset: 4 +// buffer-file-coding-system: utf-8-unix +// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; +// End: diff --git a/src/lib/List.rs b/src/lib/List.rs new file mode 100644 index 00000000..58ea29f2 --- /dev/null +++ b/src/lib/List.rs @@ -0,0 +1,66 @@ +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; +} + +fn foldl[T,U](&list[T] ls, &U u, fn(&T t, &U u) -> U f) -> U { + alt(ls) { + case (cons[T](?hd, ?tl)) { + auto u_ = f(hd, u); + // FIXME: should use 'be' here, not 'ret'. But parametric + // tail calls currently don't work. + ret foldl[T,U](*tl, u_, f); + } + case (nil[T]) { + ret u; + } + } + + fail; // TODO: remove me when exhaustiveness checking works +} + +fn find[T,U](&list[T] ls, + (fn(&T) -> Option.t[U]) f) -> Option.t[U] { + alt(ls) { + case (cons[T](?hd, ?tl)) { + alt (f(hd)) { + case (none[U]) { + // FIXME: should use 'be' here, not 'ret'. But parametric tail + // calls currently don't work. + ret find[T,U](*tl, f); + } + case (some[U](?res)) { + ret some[U](res); + } + } + } + case (nil[T]) { + ret none[U]; + } + } + + fail; // TODO: remove me when exhaustiveness checking works +} + +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](_, _)); +} + +// Local Variables: +// mode: rust; +// fill-column: 78; +// indent-tabs-mode: nil +// c-basic-offset: 4 +// buffer-file-coding-system: utf-8-unix +// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; +// End: diff --git a/src/lib/Map.rs b/src/lib/Map.rs new file mode 100644 index 00000000..6f1ad6d7 --- /dev/null +++ b/src/lib/Map.rs @@ -0,0 +1,246 @@ +/** + * 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 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); +}; + +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); + } + + 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 + // + // hash(key, i) := hashl(key) * i + hashr(key) for i = 0, 1, 2, ... + // + // Tearing the hash function apart this way is kosher in practice + // as, assuming 32-bit uints, the table would have to be at 2^32 + // buckets before the resulting pair of hash functions no longer + // probes all buckets for a fixed key. Note that hashl is made to + // output odd numbers (hence coprime to the number of nbkts, which + // 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 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 + { + 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](?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](?k, ?v)) { + if (eqer(key, k)) { + ret Option.some[V](v); + } + } + case (nil[K, V]) { + 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](?k, ?v)) { + insert_common[K, V](hasher, eqer, newbkts, + nnewbkts, 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 { + alt (find_common[K, V](hasher, eqer, bkts, nbkts, key)) { + case (Option.some[V](_)) { ret true; } + case (_) { ret false; } + } + fail; // FIXME: remove me when exhaustiveness checking works + } + + fn get(&K key) -> V { + alt (find_common[K, V](hasher, eqer, bkts, nbkts, key)) { + case (Option.some[V](?val)) { ret val; } + case (_) { fail; } + } + fail; // FIXME: remove me when exhaustiveness checking works + } + + fn find(&K key) -> Option.t[V] { + // FIXME: should be 'be' but parametric tail-calls don't + // work at the moment. + ret 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](?k, ?v)) { + if (eqer(key, k)) { + bkts.(j) = deleted[K, V]; + nelts -= 1u; + ret Option.some[V](v); + } + } + case (deleted[K, V]) { } + case (nil[K, V]) { + 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](?k,?v)) { + put @tup(k,v); + } + case (_) { } + } + } + } + } + + 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; +// indent-tabs-mode: nil +// c-basic-offset: 4 +// buffer-file-coding-system: utf-8-unix +// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; +// End: diff --git a/src/lib/Option.rs b/src/lib/Option.rs new file mode 100644 index 00000000..3fb9aa3b --- /dev/null +++ b/src/lib/Option.rs @@ -0,0 +1,60 @@ +// lib/Option.rs + +tag t[T] { + none; + some(T); +} + +type operator[T, U] = fn(&T) -> U; + +fn get[T](&t[T] opt) -> T { + alt (opt) { + case (some[T](?x)) { + ret x; + } + case (none[T]) { + fail; + } + } + fail; // FIXME: remove me when exhaustiveness checking works +} + +fn map[T, U](&operator[T, U] f, &t[T] opt) -> t[U] { + alt (opt) { + case (some[T](?x)) { + ret some[U](f(x)); + } + case (none[T]) { + ret none[U]; + } + } + fail; // FIXME: remove me when exhaustiveness checking works +} + +fn is_none[T](&t[T] opt) -> bool { + alt (opt) { + case (none[T]) { ret true; } + case (some[T](_)) { ret false; } + } +} + +fn from_maybe[T](&T def, &t[T] opt) -> T { + auto f = bind Util.id[T](_); + ret maybe[T, T](def, f, opt); +} + +fn maybe[T, U](&U def, fn(&T) -> U f, &t[T] opt) -> U { + alt (opt) { + case (none[T]) { ret def; } + case (some[T](?t)) { ret f(t); } + } +} +// Local Variables: +// mode: rust; +// fill-column: 78; +// indent-tabs-mode: nil +// c-basic-offset: 4 +// buffer-file-coding-system: utf-8-unix +// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; +// End: + diff --git a/src/lib/Rand.rs b/src/lib/Rand.rs new file mode 100644 index 00000000..06eb2f06 --- /dev/null +++ b/src/lib/Rand.rs @@ -0,0 +1,34 @@ +/** + * Bindings the runtime's random number generator (ISAAC). + */ + +native "rust" mod rustrt { + type rctx; + fn rand_new() -> rctx; + fn rand_next(rctx c) -> u32; + fn rand_free(rctx c); +} + +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); + } + } + + ret rt_rng(rustrt.rand_new()); +} + +// Local Variables: +// mode: rust; +// fill-column: 78; +// indent-tabs-mode: nil +// c-basic-offset: 4 +// buffer-file-coding-system: utf-8-unix +// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; +// End: diff --git a/src/lib/Run_Program.rs b/src/lib/Run_Program.rs new file mode 100644 index 00000000..30c0ee9c --- /dev/null +++ b/src/lib/Run_Program.rs @@ -0,0 +1,96 @@ +import Str.sbuf; +import Vec.vbuf; + +native "rust" mod rustrt { + fn rust_run_program(vbuf argv, int in_fd, int out_fd, int err_fd) -> int; +} + +fn argvec(str prog, vec[str] args) -> vec[sbuf] { + auto argptrs = vec(Str.buf(prog)); + 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](argvec(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; + }; + +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](argvec(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;} + 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 finish() -> int { + 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); + } + } + 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) { + auto pr = start_program(prog, args); + pr.close_input(); + auto out = pr.output(); + auto buf = ""; + while (!out.eof()) { + auto bytes = out.read_bytes(4096u); + buf += Str.unsafe_from_bytes(bytes); + } + ret rec(status=pr.finish(), out=buf); +} + + +// Local Variables: +// mode: rust +// fill-column: 78; +// indent-tabs-mode: nil +// c-basic-offset: 4 +// buffer-file-coding-system: utf-8-unix +// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; +// End: diff --git a/src/lib/SHA1.rs b/src/lib/SHA1.rs new file mode 100644 index 00000000..b6ac0521 --- /dev/null +++ b/src/lib/SHA1.rs @@ -0,0 +1,294 @@ +/* + * 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]); + + // Provide message input as string + fn input_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(); +}; + +// Some unexported constants +const uint digest_buf_len = 5; +const uint msg_block_len = 64; + +// 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); + + fn add_input(&sha1state st, &vec[u8] msg) { + // FIXME: Should be typestate precondition + 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); + } + } + } + + fn process_msg_block(&sha1state st) { + + // FIXME: Make precondition + assert (Vec.len(st.h) == digest_buf_len); + + // Constants + auto k = vec(0x5A827999u32, + 0x6ED9EBA1u32, + 0x8F1BBCDCu32, + 0xCA62C1D6u32); + + let int t; // Loop counter + let vec[mutable u32] w = Vec.init_elt_mut[u32](0u32, 80u); + + // Initialize the first 16 words of the vector w + t = 0; + while (t < 16) { + w.(t) = (st.msg_block.(t * 4) as u32) << 24u32; + w.(t) = w.(t) | ((st.msg_block.(t * 4 + 1) as u32) << 16u32); + w.(t) = w.(t) | ((st.msg_block.(t * 4 + 2) as u32) << 8u32); + w.(t) = w.(t) | (st.msg_block.(t * 4 + 3) as u32); + 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); + 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) + k.(0); + e = d; + d = c; + c = circular_shift(30u32, b); + b = a; + a = temp; + t += 1; + } + + while (t < 40) { + temp = circular_shift(5u32, a) + + (b ^ c ^ d) + e + w.(t) + k.(1); + e = d; + d = c; + c = circular_shift(30u32, b); + b = a; + a = temp; + t += 1; + } + + while (t < 60) { + temp = circular_shift(5u32, a) + + ((b & c) | (b & d) | (c & d)) + e + w.(t) + k.(2); + e = d; + d = c; + c = circular_shift(30u32, b); + b = a; + a = temp; + t += 1; + } + + while (t < 80) { + temp = circular_shift(5u32, a) + + (b ^ c ^ d) + e + w.(t) + k.(3); + e = d; + d = c; + c = circular_shift(30u32, b); + b = a; + 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)); + } + + fn mk_result(&sha1state st) -> vec[u8] { + if (!st.computed) { + pad_msg(st); + st.computed = true; + } + + let vec[u8] res = vec(); + 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 += vec(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 + * represent the length of the original message. All bits in between + * should be 0. This function will pad the message according to those + * rules by filling the msg_block vector accordingly. It will also + * 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); + + /* + * 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; + + process_msg_block(st); + } + + state obj sha1(sha1state st) { + + fn reset() { + // FIXME: Should be typestate precondition + 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 result_str() -> str { + auto r = mk_result(st); + auto s = ""; + 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); + auto sh = sha1(st); + sh.reset(); + ret sh; +} + +// Local Variables: +// mode: rust; +// fill-column: 78; +// indent-tabs-mode: nil +// c-basic-offset: 4 +// buffer-file-coding-system: utf-8-unix +// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; +// End: diff --git a/src/lib/Sort.rs b/src/lib/Sort.rs new file mode 100644 index 00000000..7ecaaaba --- /dev/null +++ b/src/lib/Sort.rs @@ -0,0 +1,101 @@ +import Vec.len; +import Vec.slice; + +type lteq[T] = fn(&T a, &T b) -> 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 = vec(); + let uint a_len = len[T](a); + let uint a_ix = 0u; + let uint b_len = len[T](b); + let uint b_ix = 0u; + while (a_ix < a_len && b_ix < b_len) { + if (le(a.(a_ix), b.(b_ix))) { + res += vec(a.(a_ix)); + a_ix += 1u; + } else { + res += vec(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; + } + + 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)); +} + +fn swap[T](vec[mutable T] arr, uint x, uint y) { + auto a = arr.(x); + arr.(x) = arr.(y); + arr.(y) = a; +} + +fn part[T](lteq[T] compare_func, vec[mutable T] arr, uint left, + uint right, uint pivot) -> uint { + + fn compare[T](lteq[T] compare_func, vec[mutable T]arr, + uint arr_idx, &T arr_value) -> bool { + + ret compare_func(arr.(arr_idx),arr_value); + } + + auto pivot_value = arr.(pivot); + swap[T](arr, pivot, right); + let uint storage_index = left; + let uint i = left; + while (i left) { + auto pivot = (left+right)/2u; + auto new_pivot = part[T](compare_func, arr, left, right, pivot); + 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); +} + +// Local Variables: +// mode: rust; +// fill-column: 78; +// indent-tabs-mode: nil +// c-basic-offset: 4 +// buffer-file-coding-system: utf-8-unix +// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; +// End: diff --git a/src/lib/Str.rs b/src/lib/Str.rs new file mode 100644 index 00000000..3886ee19 --- /dev/null +++ b/src/lib/Str.rs @@ -0,0 +1,501 @@ +import rustrt.sbuf; + +import Vec.rustrt.vbuf; + +native "rust" mod rustrt { + type sbuf; + fn str_buf(str s) -> sbuf; + fn str_vec(str s) -> vec[u8]; + fn str_byte_len(str s) -> uint; + fn str_alloc(uint n_bytes) -> str; + fn str_from_vec(vec[mutable? u8] b) -> str; + fn str_from_cstr(sbuf cstr) -> str; + fn str_from_buf(sbuf buf, uint len) -> str; + fn str_push_byte(str s, uint byte) -> str; + fn refcount[T](str s) -> uint; +} + +fn eq(&str a, &str b) -> bool { + let uint i = byte_len(a); + 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; + } + } + ret true; +} + +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; + } + + 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; + } + 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); + } + 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; + +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;} + i += 1u; + while (chsize > 1u) { + if (v.(i) & 0xc0_u8 != tag_cont_u8) {ret false;} + i += 1u; + chsize -= 1u; + } + } + ret true; +} + +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; + } + } + ret true; +} + +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 buf(str s) -> sbuf { + ret rustrt.str_buf(s); +} + +fn bytes(str s) -> vec[u8] { + ret rustrt.str_vec(s); +} + +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); +} + +// FIXME even temp-er thing; rustc can use "unsafe_from_bytes" above +fn unsafe_from_mutable_bytes(vec[mutable u8] mv) -> str { + let vec[u8] v = vec(); + for (u8 b in mv) { + v += vec(b); + } + ret rustrt.str_from_vec(v); +} + +fn unsafe_from_byte(u8 u) -> str { + ret rustrt.str_from_vec(vec(u)); +} + +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); +} + +fn push_utf8_bytes(&mutable str s, char ch) { + auto code = ch as uint; + 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); + } 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); + } 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); + } 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); + } 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); + } +} + +fn from_char(char ch) -> str { + auto buf = ""; + push_utf8_bytes(buf, ch); + ret buf; +} + +fn from_chars(vec[char] chs) -> str { + auto buf = ""; + 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;} + ret 6u; +} + +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);} + auto val = 0u; + auto end = i + w; + i += 1u; + while (i < end) { + auto byte = s.(i); + assert (byte & 0xc0_u8 == tag_cont_u8); + val <<= 6u; + val += (byte & 0x3f_u8) 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); + ret tup(val as char, i); +} + +fn char_at(str s, uint i) -> char { + ret char_range_at(s, i)._0; +} + +fn char_len(str s) -> uint { + auto i = 0u; + auto len = 0u; + auto total = byte_len(s); + while (i < total) { + auto chsize = utf8_char_width(s.(i)); + assert (chsize > 0u); + len += 1u; + i += chsize; + } + assert (i == total); + ret len; +} + +fn to_chars(str s) -> vec[char] { + let vec[char] buf = vec(); + auto i = 0u; + auto len = byte_len(s); + while (i < len) { + auto cur = char_range_at(s, i); + Vec.push[char](buf, cur._0); + i = cur._1; + } + ret buf; +} + +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;} + assert (end > 0u); + auto ch = char_at(s, end - 1u); + s = substr(s, 0u, end - 1u); + ret ch; +} + +fn shift_char(&mutable str s) -> char { + auto r = char_range_at(s, 0u); + s = substr(s, r._1, byte_len(s) - r._1); + ret r._0; +} + +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; +} + +fn refcount(str s) -> uint { + auto r = rustrt.refcount[u8](s); + if (r == Dbg.const_refcount) { + ret r; + } else { + // -1 because calling this function incremented the refcount. + ret r - 1u; + } +} + + +// 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; + } + 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; + } + 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 { + let int j = i; + 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; + } + i += 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; + } + ret eq(substr(haystack, 0u, needle_len), needle); +} + +fn ends_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; + } + ret eq(substr(haystack, + haystack_len - needle_len, + needle_len), + needle); +} + +fn substr(str s, uint begin, uint len) -> str { + ret slice(s, begin, begin + len); +} + +fn slice(str s, uint begin, uint end) -> str { + let str accum = ""; + let uint i = begin; + while (i < end) { + push_byte(accum, s.(i)); + i += 1u; + } + ret accum; +} + +fn shift_byte(&mutable str s) -> u8 { + auto len = byte_len(s); + assert (len > 0u); + auto b = s.(0); + s = substr(s, 1u, len - 1u); + ret b; +} + +fn pop_byte(&mutable str s) -> u8 { + auto len = byte_len(s); + assert (len > 0u); + auto b = s.(len - 1u); + s = substr(s, 0u, len - 1u); + ret b; +} + +fn push_byte(&mutable str s, u8 b) { + s = rustrt.str_push_byte(s, b as uint); +} + +fn unshift_byte(&mutable str s, u8 b) { + auto res = alloc(byte_len(s) + 1u); + res += unsafe_from_byte(b); + res += s; + s = res; +} + +fn split(str s, u8 sep) -> vec[str] { + let vec[str] v = vec(); + let str accum = ""; + let bool ends_with_sep = false; + for (u8 c in s) { + if (c == sep) { + v += vec(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 += vec(accum); + } + ret v; +} + +fn concat(vec[str] v) -> str { + let str s = ""; + for (str ss in v) { + s += ss; + } + ret s; +} + +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; + } + s += ss; + } + ret s; +} + +// FIXME: This only handles ASCII +fn to_upper(str s) -> str { + auto outstr = ""; + auto ascii_a = 'a' as u8; + auto ascii_z = 'z' as u8; + auto diff = 32u8; + for (u8 byte in s) { + auto next; + if (ascii_a <= byte && byte <= ascii_z) { + next = byte - diff; + } else { + next = byte; + } + push_byte(outstr, next); + } + ret outstr; +} + + +// Local Variables: +// mode: rust; +// fill-column: 78; +// indent-tabs-mode: nil +// c-basic-offset: 4 +// buffer-file-coding-system: utf-8-unix +// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; +// End: diff --git a/src/lib/Sys.rs b/src/lib/Sys.rs new file mode 100644 index 00000000..77eab003 --- /dev/null +++ b/src/lib/Sys.rs @@ -0,0 +1,30 @@ +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; + 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; +// indent-tabs-mode: nil +// c-basic-offset: 4 +// buffer-file-coding-system: utf-8-unix +// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; +// End: diff --git a/src/lib/Task.rs b/src/lib/Task.rs new file mode 100644 index 00000000..8eece16b --- /dev/null +++ b/src/lib/Task.rs @@ -0,0 +1,21 @@ +native "rust" mod rustrt { + fn task_sleep(uint time_in_us); +} + +/** + * Hints the scheduler to yield this task for a specified ammount of time. + * + * arg: time_in_us maximum number of microseconds to yield control for + */ +fn sleep(uint time_in_us) { + ret rustrt.task_sleep(time_in_us); +} + +// Local Variables: +// mode: rust; +// fill-column: 78; +// indent-tabs-mode: nil +// c-basic-offset: 4 +// buffer-file-coding-system: utf-8-unix +// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; +// End: diff --git a/src/lib/Term.rs b/src/lib/Term.rs index 368fe217..fca04bff 100644 --- a/src/lib/Term.rs +++ b/src/lib/Term.rs @@ -21,20 +21,20 @@ const u8 color_bright_magenta = 13u8; const u8 color_bright_cyan = 14u8; const u8 color_bright_white = 15u8; -fn esc(io.buf_writer writer) { +fn esc(IO.buf_writer writer) { writer.write(vec(0x1bu8, '[' as u8)); } -fn reset(io.buf_writer writer) { +fn reset(IO.buf_writer writer) { esc(writer); writer.write(vec('0' as u8, 'm' as u8)); } fn color_supported() -> bool { - ret _str.eq(GenericOS.getenv("TERM"), "xterm-color"); + ret Str.eq(GenericOS.getenv("TERM"), "xterm-color"); } -fn set_color(io.buf_writer writer, u8 first_char, u8 color) { +fn set_color(IO.buf_writer writer, u8 first_char, u8 color) { assert (color < 16u8); esc(writer); @@ -45,11 +45,11 @@ fn set_color(io.buf_writer writer, u8 first_char, u8 color) { writer.write(vec(first_char, ('0' as u8) + color, 'm' as u8)); } -fn fg(io.buf_writer writer, u8 color) { +fn fg(IO.buf_writer writer, u8 color) { ret set_color(writer, '3' as u8, color); } -fn bg(io.buf_writer writer, u8 color) { +fn bg(IO.buf_writer writer, u8 color) { ret set_color(writer, '4' as u8, color); } diff --git a/src/lib/U8.rs b/src/lib/U8.rs new file mode 100644 index 00000000..e094e581 --- /dev/null +++ b/src/lib/U8.rs @@ -0,0 +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; + } +} + +// Local Variables: +// mode: rust; +// fill-column: 78; +// indent-tabs-mode: nil +// c-basic-offset: 4 +// buffer-file-coding-system: utf-8-unix +// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; +// End: diff --git a/src/lib/UFind.rs b/src/lib/UFind.rs index 9593e787..0bb06d7c 100644 --- a/src/lib/UFind.rs +++ b/src/lib/UFind.rs @@ -1,19 +1,19 @@ -import option.none; -import option.some; +import Option.none; +import Option.some; // A very naive implementation of union-find with unsigned integer nodes. -type node = option.t[uint]; +type node = Option.t[uint]; type ufind = rec(mutable vec[mutable node] nodes); fn make() -> ufind { let vec[mutable node] v = vec(mutable none[uint]); - _vec.pop(v); // FIXME: botch + Vec.pop(v); // FIXME: botch ret rec(mutable nodes=v); } fn make_set(&ufind ufnd) -> uint { - auto idx = _vec.len(ufnd.nodes); + auto idx = Vec.len(ufnd.nodes); ufnd.nodes += vec(mutable none[uint]); ret idx; } diff --git a/src/lib/UInt.rs b/src/lib/UInt.rs new file mode 100644 index 00000000..eea52325 --- /dev/null +++ b/src/lib/UInt.rs @@ -0,0 +1,107 @@ + +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; } + +iter range(uint lo, uint hi) -> uint { + auto lo_ = lo; + 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; + } + ret tmp + 1u; +} + +fn parse_buf(vec[u8] buf, uint radix) -> uint { + if (Vec.len[u8](buf) == 0u) { + 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; + power *= radix; + if (i == 0u) { ret n; } + i -= 1u; + } + + fail; +} + +fn to_str(uint num, uint radix) -> str +{ + auto n = num; + + assert (0u < radix && radix <= 16u); + fn digit(uint n) -> char { + alt (n) { + case (0u) { ret '0'; } + case (1u) { ret '1'; } + case (2u) { ret '2'; } + case (3u) { ret '3'; } + case (4u) { ret '4'; } + case (5u) { ret '5'; } + case (6u) { ret '6'; } + case (7u) { ret '7'; } + case (8u) { ret '8'; } + case (9u) { ret '9'; } + case (10u) { ret 'a'; } + case (11u) { ret 'b'; } + case (12u) { ret 'c'; } + case (13u) { ret 'd'; } + case (14u) { ret 'e'; } + case (15u) { ret 'f'; } + } + 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)); + } + ret s1; + +} + +// Local Variables: +// mode: rust; +// fill-column: 78; +// indent-tabs-mode: nil +// c-basic-offset: 4 +// buffer-file-coding-system: utf-8-unix +// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; +// End: diff --git a/src/lib/Util.rs b/src/lib/Util.rs new file mode 100644 index 00000000..a385aafd --- /dev/null +++ b/src/lib/Util.rs @@ -0,0 +1,33 @@ +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); + +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 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; +// indent-tabs-mode: nil +// c-basic-offset: 4 +// buffer-file-coding-system: utf-8-unix +// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; +// End: diff --git a/src/lib/Vec.rs b/src/lib/Vec.rs new file mode 100644 index 00000000..28b5d018 --- /dev/null +++ b/src/lib/Vec.rs @@ -0,0 +1,318 @@ +import Option.none; +import Option.some; +import Util.orb; + +type vbuf = rustrt.vbuf; + +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]; + 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]; +} + +fn alloc[T](uint n_elts) -> vec[T] { + ret rustrt.vec_alloc[vec[T], T](n_elts); +} + +fn alloc_mut[T](uint n_elts) -> vec[mutable T] { + ret rustrt.vec_alloc_mut[vec[mutable T], T](n_elts); +} + +fn refcount[T](array[T] v) -> uint { + auto r = rustrt.refcount[T](v); + if (r == Dbg.const_refcount) { + ret r; + } else { + // -1 because calling this function incremented the refcount. + ret r - 1u; + } +} + +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); +} + +type init_op[T] = fn(uint i) -> 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 += vec(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 += vec(mutable op(i)); + i += 1u; + } + ret v; +} + +fn init_elt[T](&T t, uint n_elts) -> vec[T] { + /** + * FIXME (issue #81): should be: + * + * fn elt_op[T](&T x, uint i) -> T { ret x; } + * 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 += vec(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 += vec(mutable t); + } + ret v; +} + +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_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)); + ret rustrt.vec_buf[T](v, offset); +} + +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]; + } + ret some[T](v.(l - 1u)); +} + +// 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 += vec(v.(i)); + i += 1u; + } + ret result; +} + +fn shift[T](&mutable array[T] v) -> T { + auto ln = len[T](v); + assert (ln > 0u); + auto e = v.(0); + v = slice[T](v, 1u, ln); + ret e; +} + +fn pop[T](&mutable array[T] v) -> T { + auto ln = len[T](v); + assert (ln > 0u); + ln -= 1u; + auto e = v.(ln); + v = slice[T](v, 0u, ln); + ret e; +} + +fn push[T](&mutable array[T] v, &T t) { + v += vec(t); +} + +fn unshift[T](&mutable array[T] v, &T t) { + auto res = alloc[T](len[T](v) + 1u); + res += vec(t); + res += v; + v = res; +} + +fn grow[T](&array[T] v, uint n, &T initval) { + let uint i = n; + while (i > 0u) { + i -= 1u; + v += vec(initval); + } +} + +fn grow_set[T](&vec[mutable T] v, uint index, &T initval, &T val) { + auto length = Vec.len(v); + if (index >= length) { + grow(v, index - length + 1u, initval); + } + v.(index) = val; +} + +fn map[T, U](&Option.operator[T,U] f, &array[T] v) -> vec[U] { + let vec[U] u = alloc[U](len[T](v)); + for (T ve in v) { + u += vec(f(ve)); + } + ret u; +} + +fn map2[T,U,V](&operator2[T,U,V] f, &array[T] v0, &array[U] v1) -> vec[V] { + auto v0_len = len[T](v0); + if (v0_len != len[U](v1)) { + fail; + } + + let vec[V] u = alloc[V](v0_len); + auto i = 0u; + while (i < v0_len) { + u += vec(f(v0.(i), v1.(i))); + i += 1u; + } + + ret u; +} + +fn find[T](fn (&T) -> bool f, &array[T] v) -> Option.t[T] { + for (T elt in v) { + if (f(elt)) { + ret some[T](elt); + } + } + + ret none[T]; +} + +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 { + auto rest = slice[T](v, 1u, sz); + + 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 { + auto rest = slice[tup(T, U)](v, 1u, sz); + auto tl = unzip[T, U](rest); + auto a = vec(v.(0)._0); + auto b = vec(v.(0)._1); + ret tup(a + tl._0, b + tl._1); + } +} + +fn or(&vec[bool] v) -> bool { + auto f = orb; + 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 plus_option[T](&vec[T] v, &Option.t[T] o) -> () { + alt (o) { + case (none[T]) {} + case (some[T](?x)) { v += vec(x); } + } +} + +fn cat_options[T](&vec[Option.t[T]] v) -> vec[T] { + let vec[T] res = vec(); + + for (Option.t[T] o in v) { + alt (o) { + case (none[T]) { } + case (some[T](?t)) { + res += vec(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 = vec(); + for (T elem in v) { + result += vec(elem); + } + ret result; +} + +// Local Variables: +// mode: rust; +// fill-column: 78; +// indent-tabs-mode: nil +// c-basic-offset: 4 +// buffer-file-coding-system: utf-8-unix +// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; +// End: diff --git a/src/lib/_int.rs b/src/lib/_int.rs deleted file mode 100644 index 1824d142..00000000 --- a/src/lib/_int.rs +++ /dev/null @@ -1,62 +0,0 @@ - -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; } - -iter range(int lo, int hi) -> int { - let int lo_ = lo; - while (lo_ < hi) { - put lo_; - lo_ += 1; - } -} - -fn to_str(int n, uint radix) -> str -{ - assert (0u < radix && radix <= 16u); - if (n < 0) { - ret "-" + _uint.to_str((-n) as uint, radix); - } else { - ret _uint.to_str(n as uint, radix); - } -} - -fn pow(int base, uint exponent) -> int { - - if (exponent == 0u) { - ret 1; - } else if (base == 0) { - ret 0; - } else { - auto accum = base; - auto count = exponent; - while (count > 1u) { - accum *= base; - count -= 1u; - } - ret accum; - } -} - -// Local Variables: -// mode: rust; -// fill-column: 78; -// indent-tabs-mode: nil -// c-basic-offset: 4 -// buffer-file-coding-system: utf-8-unix -// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; -// End: diff --git a/src/lib/_str.rs b/src/lib/_str.rs deleted file mode 100644 index 5239afb1..00000000 --- a/src/lib/_str.rs +++ /dev/null @@ -1,501 +0,0 @@ -import rustrt.sbuf; - -import _vec.rustrt.vbuf; - -native "rust" mod rustrt { - type sbuf; - fn str_buf(str s) -> sbuf; - fn str_vec(str s) -> vec[u8]; - fn str_byte_len(str s) -> uint; - fn str_alloc(uint n_bytes) -> str; - fn str_from_vec(vec[mutable? u8] b) -> str; - fn str_from_cstr(sbuf cstr) -> str; - fn str_from_buf(sbuf buf, uint len) -> str; - fn str_push_byte(str s, uint byte) -> str; - fn refcount[T](str s) -> uint; -} - -fn eq(&str a, &str b) -> bool { - let uint i = byte_len(a); - 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; - } - } - ret true; -} - -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; - } - - 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; - } - 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); - } - 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; - -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;} - i += 1u; - while (chsize > 1u) { - if (v.(i) & 0xc0_u8 != tag_cont_u8) {ret false;} - i += 1u; - chsize -= 1u; - } - } - ret true; -} - -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; - } - } - ret true; -} - -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 buf(str s) -> sbuf { - ret rustrt.str_buf(s); -} - -fn bytes(str s) -> vec[u8] { - ret rustrt.str_vec(s); -} - -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); -} - -// FIXME even temp-er thing; rustc can use "unsafe_from_bytes" above -fn unsafe_from_mutable_bytes(vec[mutable u8] mv) -> str { - let vec[u8] v = vec(); - for (u8 b in mv) { - v += vec(b); - } - ret rustrt.str_from_vec(v); -} - -fn unsafe_from_byte(u8 u) -> str { - ret rustrt.str_from_vec(vec(u)); -} - -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); -} - -fn push_utf8_bytes(&mutable str s, char ch) { - auto code = ch as uint; - 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); - } 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); - } 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); - } 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); - } 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); - } -} - -fn from_char(char ch) -> str { - auto buf = ""; - push_utf8_bytes(buf, ch); - ret buf; -} - -fn from_chars(vec[char] chs) -> str { - auto buf = ""; - 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;} - ret 6u; -} - -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);} - auto val = 0u; - auto end = i + w; - i += 1u; - while (i < end) { - auto byte = s.(i); - assert (byte & 0xc0_u8 == tag_cont_u8); - val <<= 6u; - val += (byte & 0x3f_u8) 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); - ret tup(val as char, i); -} - -fn char_at(str s, uint i) -> char { - ret char_range_at(s, i)._0; -} - -fn char_len(str s) -> uint { - auto i = 0u; - auto len = 0u; - auto total = byte_len(s); - while (i < total) { - auto chsize = utf8_char_width(s.(i)); - assert (chsize > 0u); - len += 1u; - i += chsize; - } - assert (i == total); - ret len; -} - -fn to_chars(str s) -> vec[char] { - let vec[char] buf = vec(); - auto i = 0u; - auto len = byte_len(s); - while (i < len) { - auto cur = char_range_at(s, i); - _vec.push[char](buf, cur._0); - i = cur._1; - } - ret buf; -} - -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;} - assert (end > 0u); - auto ch = char_at(s, end - 1u); - s = substr(s, 0u, end - 1u); - ret ch; -} - -fn shift_char(&mutable str s) -> char { - auto r = char_range_at(s, 0u); - s = substr(s, r._1, byte_len(s) - r._1); - ret r._0; -} - -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; -} - -fn refcount(str s) -> uint { - auto r = rustrt.refcount[u8](s); - if (r == dbg.const_refcount) { - ret r; - } else { - // -1 because calling this function incremented the refcount. - ret r - 1u; - } -} - - -// 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; - } - 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; - } - 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 { - let int j = i; - 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; - } - i += 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; - } - ret eq(substr(haystack, 0u, needle_len), needle); -} - -fn ends_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; - } - ret eq(substr(haystack, - haystack_len - needle_len, - needle_len), - needle); -} - -fn substr(str s, uint begin, uint len) -> str { - ret slice(s, begin, begin + len); -} - -fn slice(str s, uint begin, uint end) -> str { - let str accum = ""; - let uint i = begin; - while (i < end) { - push_byte(accum, s.(i)); - i += 1u; - } - ret accum; -} - -fn shift_byte(&mutable str s) -> u8 { - auto len = byte_len(s); - assert (len > 0u); - auto b = s.(0); - s = substr(s, 1u, len - 1u); - ret b; -} - -fn pop_byte(&mutable str s) -> u8 { - auto len = byte_len(s); - assert (len > 0u); - auto b = s.(len - 1u); - s = substr(s, 0u, len - 1u); - ret b; -} - -fn push_byte(&mutable str s, u8 b) { - s = rustrt.str_push_byte(s, b as uint); -} - -fn unshift_byte(&mutable str s, u8 b) { - auto res = alloc(byte_len(s) + 1u); - res += unsafe_from_byte(b); - res += s; - s = res; -} - -fn split(str s, u8 sep) -> vec[str] { - let vec[str] v = vec(); - let str accum = ""; - let bool ends_with_sep = false; - for (u8 c in s) { - if (c == sep) { - v += vec(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 += vec(accum); - } - ret v; -} - -fn concat(vec[str] v) -> str { - let str s = ""; - for (str ss in v) { - s += ss; - } - ret s; -} - -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; - } - s += ss; - } - ret s; -} - -// FIXME: This only handles ASCII -fn to_upper(str s) -> str { - auto outstr = ""; - auto ascii_a = 'a' as u8; - auto ascii_z = 'z' as u8; - auto diff = 32u8; - for (u8 byte in s) { - auto next; - if (ascii_a <= byte && byte <= ascii_z) { - next = byte - diff; - } else { - next = byte; - } - push_byte(outstr, next); - } - ret outstr; -} - - -// Local Variables: -// mode: rust; -// fill-column: 78; -// indent-tabs-mode: nil -// c-basic-offset: 4 -// buffer-file-coding-system: utf-8-unix -// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; -// End: diff --git a/src/lib/_task.rs b/src/lib/_task.rs deleted file mode 100644 index 8eece16b..00000000 --- a/src/lib/_task.rs +++ /dev/null @@ -1,21 +0,0 @@ -native "rust" mod rustrt { - fn task_sleep(uint time_in_us); -} - -/** - * Hints the scheduler to yield this task for a specified ammount of time. - * - * arg: time_in_us maximum number of microseconds to yield control for - */ -fn sleep(uint time_in_us) { - ret rustrt.task_sleep(time_in_us); -} - -// Local Variables: -// mode: rust; -// fill-column: 78; -// indent-tabs-mode: nil -// c-basic-offset: 4 -// buffer-file-coding-system: utf-8-unix -// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; -// End: diff --git a/src/lib/_u8.rs b/src/lib/_u8.rs deleted file mode 100644 index e094e581..00000000 --- a/src/lib/_u8.rs +++ /dev/null @@ -1,28 +0,0 @@ -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; - } -} - -// Local Variables: -// mode: rust; -// fill-column: 78; -// indent-tabs-mode: nil -// c-basic-offset: 4 -// buffer-file-coding-system: utf-8-unix -// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; -// End: diff --git a/src/lib/_uint.rs b/src/lib/_uint.rs deleted file mode 100644 index 2d373cdd..00000000 --- a/src/lib/_uint.rs +++ /dev/null @@ -1,107 +0,0 @@ - -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; } - -iter range(uint lo, uint hi) -> uint { - auto lo_ = lo; - 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; - } - ret tmp + 1u; -} - -fn parse_buf(vec[u8] buf, uint radix) -> uint { - if (_vec.len[u8](buf) == 0u) { - 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; - power *= radix; - if (i == 0u) { ret n; } - i -= 1u; - } - - fail; -} - -fn to_str(uint num, uint radix) -> str -{ - auto n = num; - - assert (0u < radix && radix <= 16u); - fn digit(uint n) -> char { - alt (n) { - case (0u) { ret '0'; } - case (1u) { ret '1'; } - case (2u) { ret '2'; } - case (3u) { ret '3'; } - case (4u) { ret '4'; } - case (5u) { ret '5'; } - case (6u) { ret '6'; } - case (7u) { ret '7'; } - case (8u) { ret '8'; } - case (9u) { ret '9'; } - case (10u) { ret 'a'; } - case (11u) { ret 'b'; } - case (12u) { ret 'c'; } - case (13u) { ret 'd'; } - case (14u) { ret 'e'; } - case (15u) { ret 'f'; } - } - 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)); - } - ret s1; - -} - -// Local Variables: -// mode: rust; -// fill-column: 78; -// indent-tabs-mode: nil -// c-basic-offset: 4 -// buffer-file-coding-system: utf-8-unix -// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; -// End: diff --git a/src/lib/_vec.rs b/src/lib/_vec.rs deleted file mode 100644 index 3a197ac2..00000000 --- a/src/lib/_vec.rs +++ /dev/null @@ -1,318 +0,0 @@ -import option.none; -import option.some; -import util.orb; - -type vbuf = rustrt.vbuf; - -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]; - 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]; -} - -fn alloc[T](uint n_elts) -> vec[T] { - ret rustrt.vec_alloc[vec[T], T](n_elts); -} - -fn alloc_mut[T](uint n_elts) -> vec[mutable T] { - ret rustrt.vec_alloc_mut[vec[mutable T], T](n_elts); -} - -fn refcount[T](array[T] v) -> uint { - auto r = rustrt.refcount[T](v); - if (r == dbg.const_refcount) { - ret r; - } else { - // -1 because calling this function incremented the refcount. - ret r - 1u; - } -} - -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); -} - -type init_op[T] = fn(uint i) -> 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 += vec(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 += vec(mutable op(i)); - i += 1u; - } - ret v; -} - -fn init_elt[T](&T t, uint n_elts) -> vec[T] { - /** - * FIXME (issue #81): should be: - * - * fn elt_op[T](&T x, uint i) -> T { ret x; } - * 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 += vec(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 += vec(mutable t); - } - ret v; -} - -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_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)); - ret rustrt.vec_buf[T](v, offset); -} - -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]; - } - ret some[T](v.(l - 1u)); -} - -// 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 += vec(v.(i)); - i += 1u; - } - ret result; -} - -fn shift[T](&mutable array[T] v) -> T { - auto ln = len[T](v); - assert (ln > 0u); - auto e = v.(0); - v = slice[T](v, 1u, ln); - ret e; -} - -fn pop[T](&mutable array[T] v) -> T { - auto ln = len[T](v); - assert (ln > 0u); - ln -= 1u; - auto e = v.(ln); - v = slice[T](v, 0u, ln); - ret e; -} - -fn push[T](&mutable array[T] v, &T t) { - v += vec(t); -} - -fn unshift[T](&mutable array[T] v, &T t) { - auto res = alloc[T](len[T](v) + 1u); - res += vec(t); - res += v; - v = res; -} - -fn grow[T](&array[T] v, uint n, &T initval) { - let uint i = n; - while (i > 0u) { - i -= 1u; - v += vec(initval); - } -} - -fn grow_set[T](&vec[mutable T] v, uint index, &T initval, &T val) { - auto length = _vec.len(v); - if (index >= length) { - grow(v, index - length + 1u, initval); - } - v.(index) = val; -} - -fn map[T, U](&option.operator[T,U] f, &array[T] v) -> vec[U] { - let vec[U] u = alloc[U](len[T](v)); - for (T ve in v) { - u += vec(f(ve)); - } - ret u; -} - -fn map2[T,U,V](&operator2[T,U,V] f, &array[T] v0, &array[U] v1) -> vec[V] { - auto v0_len = len[T](v0); - if (v0_len != len[U](v1)) { - fail; - } - - let vec[V] u = alloc[V](v0_len); - auto i = 0u; - while (i < v0_len) { - u += vec(f(v0.(i), v1.(i))); - i += 1u; - } - - ret u; -} - -fn find[T](fn (&T) -> bool f, &array[T] v) -> option.t[T] { - for (T elt in v) { - if (f(elt)) { - ret some[T](elt); - } - } - - ret none[T]; -} - -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 { - auto rest = slice[T](v, 1u, sz); - - 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 { - auto rest = slice[tup(T, U)](v, 1u, sz); - auto tl = unzip[T, U](rest); - auto a = vec(v.(0)._0); - auto b = vec(v.(0)._1); - ret tup(a + tl._0, b + tl._1); - } -} - -fn or(&vec[bool] v) -> bool { - auto f = orb; - 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 plus_option[T](&vec[T] v, &option.t[T] o) -> () { - alt (o) { - case (none[T]) {} - case (some[T](?x)) { v += vec(x); } - } -} - -fn cat_options[T](&vec[option.t[T]] v) -> vec[T] { - let vec[T] res = vec(); - - for (option.t[T] o in v) { - alt (o) { - case (none[T]) { } - case (some[T](?t)) { - res += vec(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 = vec(); - for (T elem in v) { - result += vec(elem); - } - ret result; -} - -// Local Variables: -// mode: rust; -// fill-column: 78; -// indent-tabs-mode: nil -// c-basic-offset: 4 -// buffer-file-coding-system: utf-8-unix -// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; -// End: diff --git a/src/lib/bitv.rs b/src/lib/bitv.rs deleted file mode 100644 index 1002abc8..00000000 --- a/src/lib/bitv.rs +++ /dev/null @@ -1,222 +0,0 @@ -// 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 -// for the case where nbits <= 32. - -// 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); - -// FIXME: this should be a constant once they work -fn uint_bits() -> uint { - ret 32u + ((1u << 32u) >> 27u); -} - -fn create(uint nbits, bool init) -> t { - auto elt; - if (init) { - elt = ~0u; - } else { - elt = 0u; - } - - auto storage = _vec.init_elt_mut[uint](elt, nbits / uint_bits() + 1u); - ret rec(storage = storage, nbits = nbits); -} - -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; - } - } - - ret changed; -} - -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 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 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); -} - -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); - 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; - } - i = i + 1u; - } - ret true; -} - -fn clear(&t v) { - for each (uint i in _uint.range(0u, _vec.len(v.storage))) { - v.storage.(i) = 0u; - } -} - -fn invert(&t v) { - for each (uint i in _uint.range(0u, _vec.len(v.storage))) { - v.storage.(i) = ~v.storage.(i); - } -} - -/* v0 = v0 - v1 */ -fn difference(&t v0, &t v1) -> bool { - invert(v1); - auto b = intersect(v0, v1); - invert(v1); - ret b; -} - -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; - if (x) { - v.storage.(w) = v.storage.(w) | flag; - } else { - v.storage.(w) = 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; - } - } - - 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; - } - } - - ret true; -} - -fn init_to_vec(t v, uint i) -> uint { - if (get(v, i)) { - ret 1u; - } else { - ret 0u; - } -} - -fn to_vec(&t v) -> vec[uint] { - auto sub = bind init_to_vec(v, _); - ret _vec.init_fn[uint](sub, v.nbits); -} - -fn to_str(&t v) -> str { - auto res = ""; - - for (uint i in bitv.to_vec(v)) { - 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)); - auto len = v0.nbits; - auto i = 0u; - while (i < len) { - auto w0 = get(v0, i); - auto w1 = v1.(i); - if ((!w0 && w1 != 0u) || (w0 && w1 == 0u)) { - ret false; - } - i = i + 1u; - } - ret true; -} - -// -// Local Variables: -// mode: rust -// fill-column: 78; -// indent-tabs-mode: nil -// c-basic-offset: 4 -// buffer-file-coding-system: utf-8-unix -// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; -// End: -// diff --git a/src/lib/dbg.rs b/src/lib/dbg.rs deleted file mode 100644 index b63f363e..00000000 --- a/src/lib/dbg.rs +++ /dev/null @@ -1,74 +0,0 @@ -/** - * Unsafe debugging functions for inspecting values. - * - * Your RUST_LOG environment variable must contain "stdlib" for any debug - * logging. - */ - -// FIXME: handle 64-bit case. -const uint const_refcount = 0x7bad_face_u; - -native "rust" mod rustrt { - fn debug_tydesc[T](); - fn debug_opaque[T](&T x); - fn debug_box[T](@T x); - fn debug_tag[T](&T x); - fn debug_obj[T](&T x, uint nmethods, uint nbytes); - fn debug_fn[T](&T x); - fn debug_ptrcast[T, U](@T x) -> @U; - fn debug_trap(str msg); -} - -fn debug_vec[T](vec[T] v) { - _vec.print_debug_info[T](v); -} - -fn debug_tydesc[T]() { - rustrt.debug_tydesc[T](); -} - -fn debug_opaque[T](&T x) { - rustrt.debug_opaque[T](x); -} - -fn debug_box[T](@T x) { - rustrt.debug_box[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 - * runtime will print this many words of the obj vtbl). - * - * `nbytes` is the number of bytes of body data we expect the object to have. - * The runtime will print this many bytes of the obj body. You probably want - * this to at least be 4u, since an implicit captured tydesc pointer sits in - * the front of any obj's data tuple.x - */ -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 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; -// indent-tabs-mode: nil -// c-basic-offset: 4 -// buffer-file-coding-system: utf-8-unix -// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; -// End: diff --git a/src/lib/deque.rs b/src/lib/deque.rs deleted file mode 100644 index b8404a7d..00000000 --- a/src/lib/deque.rs +++ /dev/null @@ -1,145 +0,0 @@ -/** - * 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; -}; - -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. - */ - fn grow[T](uint nelts, uint lo, vec[cell[T]] elts) -> vec[cell[T]] { - assert (nelts == _vec.len[cell[T]](elts)); - - fn fill[T](uint i, uint nelts, uint lo, - vec[cell[T]] old) -> cell[T] { - if (i < nelts) { - ret old.((lo + i) % nelts); - } else { - ret option.none[T]; - } - } - - 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[cell[T]](copy_op, nalloc); - } - - fn get[T](vec[cell[T]] elts, uint i) -> T { - alt (elts.(i)) { - case (option.some[T](?t)) { ret t; } - case (_) { fail; } - } - fail; // FIXME: remove me when exhaustiveness checking works - } - - obj deque[T](mutable uint nelts, - mutable uint lo, - mutable uint hi, - mutable vec[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; - } - - 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); - } - - } - let vec[cell[T]] v = _vec.init_elt[cell[T]](option.none[T], - initial_capacity); - - ret deque[T](0u, 0u, 0u, v); -} - -// Local Variables: -// mode: rust; -// fill-column: 78; -// indent-tabs-mode: nil -// c-basic-offset: 4 -// buffer-file-coding-system: utf-8-unix -// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; -// End: diff --git a/src/lib/ebml.rs b/src/lib/ebml.rs deleted file mode 100644 index 9bad0f33..00000000 --- a/src/lib/ebml.rs +++ /dev/null @@ -1,186 +0,0 @@ -// 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); - -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 & 0x40u8 != 0u8) { - 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); - } 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; - } -} - -fn new_doc(vec[u8] data) -> doc { - ret rec(data=data, start=0u, end=_vec.len[u8](data)); -} - -fn doc_at(vec[u8] data, uint start) -> doc { - auto elt_tag = vint_at(data, start); - auto elt_size = vint_at(data, elt_tag._1); - auto end = elt_size._1 + elt_size._0; - ret rec(data=data, start=elt_size._1, end=end); -} - -fn maybe_get_doc(doc d, uint tg) -> option.t[doc] { - auto pos = d.start; - while (pos < d.end) { - auto elt_tag = vint_at(d.data, pos); - auto elt_size = vint_at(d.data, elt_tag._1); - pos = elt_size._1 + elt_size._0; - if (elt_tag._0 == tg) { - ret some[doc](rec(data=d.data, start=elt_size._1, end=pos)); - } - } - ret none[doc]; -} - -fn get_doc(doc d, uint tg) -> doc { - alt (maybe_get_doc(d, tg)) { - case (some[doc](?d)) {ret d;} - case (none[doc]) { - log_err "failed to find block with tag " + _uint.to_str(tg, 10u); - fail; - } - } -} - -iter docs(doc d) -> tup(uint, doc) { - auto pos = d.start; - while (pos < d.end) { - auto elt_tag = vint_at(d.data, pos); - auto elt_size = vint_at(d.data, elt_tag._1); - pos = elt_size._1 + elt_size._0; - put tup(elt_tag._0, rec(data=d.data, start=elt_size._1, end=pos)); - } -} - -iter tagged_docs(doc d, uint tg) -> doc { - auto pos = d.start; - while (pos < d.end) { - auto elt_tag = vint_at(d.data, pos); - auto elt_size = vint_at(d.data, elt_tag._1); - pos = elt_size._1 + elt_size._0; - if (elt_tag._0 == tg) { - put rec(data=d.data, start=elt_size._1, end=pos); - } - } -} - -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; - assert (sz <= 4u); - auto val = 0u; - auto pos = start; - while (sz > 0u) { - sz -= 1u; - val += (data.(pos) as uint) << (sz * 8u); - pos += 1u; - } - ret val; -} - -fn doc_as_uint(doc d) -> uint { - ret be_uint_from_bytes(d.data, d.start, d.end - d.start); -} - -// 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 = vec(0x80u8 | (n as u8)); - } - case (2u) { - buf = vec(0x40u8 | ((n >> 8u) as u8), - (n & 0xffu) as u8); - } - case (3u) { - buf = vec(0x20u8 | ((n >> 16u) as u8), - ((n >> 8u) & 0xffu) as u8, - (n & 0xffu) as u8); - } - case (4u) { - buf = vec(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; } - log_err "vint to write too big"; - fail; -} - -fn create_writer(&io.buf_writer w) -> writer { - let vec[uint] size_positions = vec(); - ret rec(writer=w, mutable size_positions=size_positions); -} - -// 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 a placeholder four-byte size. - w.size_positions += vec(w.writer.tell()); - let vec[u8] zeroes = vec(0u8, 0u8, 0u8, 0u8); - w.writer.write(zeroes); -} - -fn end_tag(&writer w) { - auto last_size_pos = _vec.pop[uint](w.size_positions); - auto cur_pos = w.writer.tell(); - w.writer.seek(last_size_pos as int, io.seek_set); - 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 diff --git a/src/lib/fs.rs b/src/lib/fs.rs deleted file mode 100644 index 0a951e5a..00000000 --- a/src/lib/fs.rs +++ /dev/null @@ -1,56 +0,0 @@ -native "rust" mod rustrt { - fn rust_file_is_dir(str path) -> int; -} - -fn path_sep() -> str { - ret _str.from_char(os_fs.path_sep); -} - -type path = str; - -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; - } - } - ret _str.substr(p, 0u, i as uint); -} - -fn connect(path pre, path post) -> path { - auto len = _str.byte_len(pre); - if (pre.(len - 1u) == (os_fs.path_sep as u8)) { // Trailing '/'? - ret pre + post; - } - ret pre + path_sep() + post; -} - -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 = vec(); - 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; -// indent-tabs-mode: nil -// c-basic-offset: 4 -// buffer-file-coding-system: utf-8-unix -// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; -// End: diff --git a/src/lib/io.rs b/src/lib/io.rs deleted file mode 100644 index 364810ba..00000000 --- a/src/lib/io.rs +++ /dev/null @@ -1,531 +0,0 @@ -import os.libc; - -native "rust" mod rustrt { - 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;} - -// 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; - - // FIXME: Seekable really should be orthogonal. We will need - // inheritance. - fn seek(int offset, seek_style whence); - fn tell() -> uint; - }; - -// Convenience methods for reading. -type reader = - state obj { - // FIXME: This should inherit from buf_reader. - fn get_buf_reader() -> buf_reader; - - 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]; - - fn seek(int offset, seek_style whence); - fn tell() -> uint; // FIXME: eventually u64 - }; - -fn convert_whence(seek_style whence) -> int { - alt (whence) { - case (seek_set) {ret 0;} - case (seek_cur) {ret 1;} - case (seek_end) {ret 2;} - } -} - -state 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 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); } - } -} - -// 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); - } - fn read_char() -> char { - auto c0 = rdr.read_byte(); - 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;} - auto val = 0u; - while (w > 1u) { - w -= 1u; - auto next = rdr.read_byte(); - assert (next > -1); - assert (next & 0xc0 == 0x80); - val <<= 6u; - val += (next & 0x3f) as uint; - } - // See _str.char_at - val += ((b0 << ((w + 1u) as u8)) as uint) << ((w - 1u) * 6u - w - 1u); - ret val as char; - } - fn eof() -> bool { - ret rdr.eof(); - } - fn read_line() -> str { - let vec[u8] buf = vec(); - // 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);} - } - ret _str.unsafe_from_bytes(buf); - } - fn read_c_str() -> str { - let vec[u8] buf = vec(); - 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);} - } - ret _str.unsafe_from_bytes(buf); - } - // FIXME deal with eof? - fn read_le_uint(uint size) -> uint { - auto val = 0u; - auto pos = 0u; - while (size > 0u) { - val += (rdr.read_byte() as uint) << pos; - pos += 8u; - size -= 1u; - } - ret val; - } - fn read_le_int(uint size) -> int { - auto val = 0u; - auto pos = 0u; - while (size > 0u) { - val += (rdr.read_byte() as uint) << pos; - pos += 8u; - size -= 1u; - } - 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); - } - ret val; - } - fn read_whole_stream() -> vec[u8] { - let vec[u8] buf = vec(); - 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 stdin() -> reader { - ret new_reader(FILE_buf_reader(rustrt.rust_get_stdin(), false)); -} - -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; - } - 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); -} - - -// Byte buffer readers - -// 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) { - 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; - } - 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;} - 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 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; } -} - -fn new_byte_buf_reader(vec[u8] buf) -> byte_buf_reader { - ret byte_buf_reader(@rec(buf=buf, mutable pos=0u)); -} - - -// Writing - -tag fileflag { - append; - create; - truncate; - none; -} - -type buf_writer = state obj { - fn write(vec[u8] v); - - // 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) { - 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"; - } - } - - 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);} - } -} - -state obj fd_buf_writer(int fd, bool must_close) { - fn write(vec[u8] v) { - auto len = _vec.len[u8](v); - auto count = 0u; - auto vbuf; - while (count < len) { - vbuf = _vec.buf_off[u8](v, count); - auto nout = os.libc.write(fd, vbuf, len); - if (nout < 0) { - log_err "error dumping buffer"; - log_err sys.rustrt.last_os_error(); - fail; - } - 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);} - } -} - -fn file_buf_writer(str path, vec[fileflag] flags) -> buf_writer { - let int fflags = - 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 (truncate) { fflags |= os.libc_constants.O_TRUNC(); } - case (none) {} - } - } - - 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(); - fail; - } - ret fd_buf_writer(fd, true); -} - -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_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); - }; - -fn uint_to_le_bytes(uint n, uint size) -> vec[u8] { - let vec[u8] bytes = vec(); - while (size > 0u) { - bytes += vec((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 = vec(); - auto i = (size - 1u) as int; - while (i >= 0) { - bytes += vec(((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)); - } - 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_le_uint(uint n, uint size) { - out.write(uint_to_le_bytes(n, size)); - } - fn write_le_int(int n, uint size) { - out.write(uint_to_le_bytes(n as uint, size)); - } - fn write_be_uint(uint n, uint size) { - out.write(uint_to_be_bytes(n, size)); - } -} - -// FIXME: Remove me once objects are exported. -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; - } - 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)); -} - -type str_writer = - state 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) { - 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 += vec(mutable 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 = vec(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_mutable_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_end) { bpos = blen + offset; } - } - - if (bpos < 0) { - bpos = 0; - } else if (bpos > blen) { - bpos = blen; - } - - ret bpos as uint; -} - - -// -// Local Variables: -// mode: rust -// fill-column: 78; -// indent-tabs-mode: nil -// c-basic-offset: 4 -// buffer-file-coding-system: utf-8-unix -// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; -// End: -// diff --git a/src/lib/linux_OS.rs b/src/lib/linux_OS.rs new file mode 100644 index 00000000..02c9183b --- /dev/null +++ b/src/lib/linux_OS.rs @@ -0,0 +1,90 @@ +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" { + + 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; + fn fclose(FILE f); + fn fgetc(FILE f) -> int; + fn ungetc(int c, FILE f); + fn feof(FILE f) -> int; + fn fread(vbuf buf, uint size, uint n, FILE f) -> uint; + 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 S_IRUSR() -> uint { ret 0x0100u; } + fn S_IWUSR() -> uint { ret 0x0080u; } +} + +fn exec_suffix() -> str { + ret ""; +} + +fn target_os() -> str { + ret "linux"; +} + +fn dylib_filename(str base) -> str { + ret "lib" + base + ".so"; +} + +fn pipe() -> tup(int, int) { + let vec[mutable int] fds = vec(mutable 0, 0); + assert (OS.libc.pipe(Vec.buf(fds)) == 0); + ret tup(fds.(0), fds.(1)); +} + +fn fd_FILE(int fd) -> libc.FILE { + ret libc.fdopen(fd, Str.buf("r")); +} + +fn waitpid(int pid) -> int { + let vec[mutable int] status = vec(mutable 0); + assert (OS.libc.waitpid(pid, Vec.buf(status), 0) != -1); + ret status.(0); +} + +// Local Variables: +// mode: rust; +// fill-column: 78; +// indent-tabs-mode: nil +// c-basic-offset: 4 +// buffer-file-coding-system: utf-8-unix +// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; +// End: diff --git a/src/lib/linux_os.rs b/src/lib/linux_os.rs deleted file mode 100644 index a37db418..00000000 --- a/src/lib/linux_os.rs +++ /dev/null @@ -1,90 +0,0 @@ -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" { - - 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; - fn fclose(FILE f); - fn fgetc(FILE f) -> int; - fn ungetc(int c, FILE f); - fn feof(FILE f) -> int; - fn fread(vbuf buf, uint size, uint n, FILE f) -> uint; - 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 S_IRUSR() -> uint { ret 0x0100u; } - fn S_IWUSR() -> uint { ret 0x0080u; } -} - -fn exec_suffix() -> str { - ret ""; -} - -fn target_os() -> str { - ret "linux"; -} - -fn dylib_filename(str base) -> str { - ret "lib" + base + ".so"; -} - -fn pipe() -> tup(int, int) { - let vec[mutable int] fds = vec(mutable 0, 0); - assert (os.libc.pipe(_vec.buf(fds)) == 0); - ret tup(fds.(0), fds.(1)); -} - -fn fd_FILE(int fd) -> libc.FILE { - ret libc.fdopen(fd, _str.buf("r")); -} - -fn waitpid(int pid) -> int { - let vec[mutable int] status = vec(mutable 0); - assert (os.libc.waitpid(pid, _vec.buf(status), 0) != -1); - ret status.(0); -} - -// Local Variables: -// mode: rust; -// fill-column: 78; -// indent-tabs-mode: nil -// c-basic-offset: 4 -// buffer-file-coding-system: utf-8-unix -// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; -// End: diff --git a/src/lib/list.rs b/src/lib/list.rs deleted file mode 100644 index 33f7c060..00000000 --- a/src/lib/list.rs +++ /dev/null @@ -1,66 +0,0 @@ -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; -} - -fn foldl[T,U](&list[T] ls, &U u, fn(&T t, &U u) -> U f) -> U { - alt(ls) { - case (cons[T](?hd, ?tl)) { - auto u_ = f(hd, u); - // FIXME: should use 'be' here, not 'ret'. But parametric - // tail calls currently don't work. - ret foldl[T,U](*tl, u_, f); - } - case (nil[T]) { - ret u; - } - } - - fail; // TODO: remove me when exhaustiveness checking works -} - -fn find[T,U](&list[T] ls, - (fn(&T) -> option.t[U]) f) -> option.t[U] { - alt(ls) { - case (cons[T](?hd, ?tl)) { - alt (f(hd)) { - case (none[U]) { - // FIXME: should use 'be' here, not 'ret'. But parametric tail - // calls currently don't work. - ret find[T,U](*tl, f); - } - case (some[U](?res)) { - ret some[U](res); - } - } - } - case (nil[T]) { - ret none[U]; - } - } - - fail; // TODO: remove me when exhaustiveness checking works -} - -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](_, _)); -} - -// Local Variables: -// mode: rust; -// fill-column: 78; -// indent-tabs-mode: nil -// c-basic-offset: 4 -// buffer-file-coding-system: utf-8-unix -// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; -// End: diff --git a/src/lib/macos_OS.rs b/src/lib/macos_OS.rs new file mode 100644 index 00000000..700ac17c --- /dev/null +++ b/src/lib/macos_OS.rs @@ -0,0 +1,87 @@ +import Str.sbuf; +import Vec.vbuf; + +native mod libc = "libc.dylib" { + + 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; + fn fclose(FILE f); + fn fgetc(FILE f) -> int; + fn ungetc(int c, FILE f); + fn feof(FILE f) -> int; + fn fread(vbuf buf, uint size, uint n, FILE f) -> uint; + 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 S_IRUSR() -> uint { ret 0x0400u; } + fn S_IWUSR() -> uint { ret 0x0200u; } +} + +fn exec_suffix() -> str { + ret ""; +} + +fn target_os() -> str { + ret "macos"; +} + +fn dylib_filename(str base) -> str { + ret "lib" + base + ".dylib"; +} + +fn pipe() -> tup(int, int) { + let vec[mutable int] fds = vec(mutable 0, 0); + assert (OS.libc.pipe(Vec.buf[mutable int](fds)) == 0); + ret tup(fds.(0), fds.(1)); +} + +fn fd_FILE(int fd) -> libc.FILE { + ret libc.fdopen(fd, Str.buf("r")); +} + +fn waitpid(int pid) -> int { + let vec[mutable int] status = vec(mutable 0); + assert (OS.libc.waitpid(pid, Vec.buf[mutable int](status), 0) != -1); + ret status.(0); +} + +// Local Variables: +// mode: rust; +// fill-column: 78; +// indent-tabs-mode: nil +// c-basic-offset: 4 +// buffer-file-coding-system: utf-8-unix +// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; +// End: diff --git a/src/lib/macos_os.rs b/src/lib/macos_os.rs deleted file mode 100644 index a52b02c5..00000000 --- a/src/lib/macos_os.rs +++ /dev/null @@ -1,87 +0,0 @@ -import _str.sbuf; -import _vec.vbuf; - -native mod libc = "libc.dylib" { - - 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; - fn fclose(FILE f); - fn fgetc(FILE f) -> int; - fn ungetc(int c, FILE f); - fn feof(FILE f) -> int; - fn fread(vbuf buf, uint size, uint n, FILE f) -> uint; - 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 S_IRUSR() -> uint { ret 0x0400u; } - fn S_IWUSR() -> uint { ret 0x0200u; } -} - -fn exec_suffix() -> str { - ret ""; -} - -fn target_os() -> str { - ret "macos"; -} - -fn dylib_filename(str base) -> str { - ret "lib" + base + ".dylib"; -} - -fn pipe() -> tup(int, int) { - let vec[mutable int] fds = vec(mutable 0, 0); - assert (os.libc.pipe(_vec.buf[mutable int](fds)) == 0); - ret tup(fds.(0), fds.(1)); -} - -fn fd_FILE(int fd) -> libc.FILE { - ret libc.fdopen(fd, _str.buf("r")); -} - -fn waitpid(int pid) -> int { - let vec[mutable int] status = vec(mutable 0); - assert (os.libc.waitpid(pid, _vec.buf[mutable int](status), 0) != -1); - ret status.(0); -} - -// Local Variables: -// mode: rust; -// fill-column: 78; -// indent-tabs-mode: nil -// c-basic-offset: 4 -// buffer-file-coding-system: utf-8-unix -// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; -// End: diff --git a/src/lib/map.rs b/src/lib/map.rs deleted file mode 100644 index 4ab2f076..00000000 --- a/src/lib/map.rs +++ /dev/null @@ -1,246 +0,0 @@ -/** - * 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 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); -}; - -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); - } - - 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 - // - // hash(key, i) := hashl(key) * i + hashr(key) for i = 0, 1, 2, ... - // - // Tearing the hash function apart this way is kosher in practice - // as, assuming 32-bit uints, the table would have to be at 2^32 - // buckets before the resulting pair of hash functions no longer - // probes all buckets for a fixed key. Note that hashl is made to - // output odd numbers (hence coprime to the number of nbkts, which - // 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 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 - { - 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](?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](?k, ?v)) { - if (eqer(key, k)) { - ret option.some[V](v); - } - } - case (nil[K, V]) { - 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](?k, ?v)) { - insert_common[K, V](hasher, eqer, newbkts, - nnewbkts, 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 { - alt (find_common[K, V](hasher, eqer, bkts, nbkts, key)) { - case (option.some[V](_)) { ret true; } - case (_) { ret false; } - } - fail; // FIXME: remove me when exhaustiveness checking works - } - - fn get(&K key) -> V { - alt (find_common[K, V](hasher, eqer, bkts, nbkts, key)) { - case (option.some[V](?val)) { ret val; } - case (_) { fail; } - } - fail; // FIXME: remove me when exhaustiveness checking works - } - - fn find(&K key) -> option.t[V] { - // FIXME: should be 'be' but parametric tail-calls don't - // work at the moment. - ret 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](?k, ?v)) { - if (eqer(key, k)) { - bkts.(j) = deleted[K, V]; - nelts -= 1u; - ret option.some[V](v); - } - } - case (deleted[K, V]) { } - case (nil[K, V]) { - 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](?k,?v)) { - put @tup(k,v); - } - case (_) { } - } - } - } - } - - 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; -// indent-tabs-mode: nil -// c-basic-offset: 4 -// buffer-file-coding-system: utf-8-unix -// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; -// End: diff --git a/src/lib/option.rs b/src/lib/option.rs deleted file mode 100644 index e214c774..00000000 --- a/src/lib/option.rs +++ /dev/null @@ -1,60 +0,0 @@ -// lib/option.rs - -tag t[T] { - none; - some(T); -} - -type operator[T, U] = fn(&T) -> U; - -fn get[T](&t[T] opt) -> T { - alt (opt) { - case (some[T](?x)) { - ret x; - } - case (none[T]) { - fail; - } - } - fail; // FIXME: remove me when exhaustiveness checking works -} - -fn map[T, U](&operator[T, U] f, &t[T] opt) -> t[U] { - alt (opt) { - case (some[T](?x)) { - ret some[U](f(x)); - } - case (none[T]) { - ret none[U]; - } - } - fail; // FIXME: remove me when exhaustiveness checking works -} - -fn is_none[T](&t[T] opt) -> bool { - alt (opt) { - case (none[T]) { ret true; } - case (some[T](_)) { ret false; } - } -} - -fn from_maybe[T](&T def, &t[T] opt) -> T { - auto f = bind util.id[T](_); - ret maybe[T, T](def, f, opt); -} - -fn maybe[T, U](&U def, fn(&T) -> U f, &t[T] opt) -> U { - alt (opt) { - case (none[T]) { ret def; } - case (some[T](?t)) { ret f(t); } - } -} -// Local Variables: -// mode: rust; -// fill-column: 78; -// indent-tabs-mode: nil -// c-basic-offset: 4 -// buffer-file-coding-system: utf-8-unix -// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; -// End: - diff --git a/src/lib/posix_FS.rs b/src/lib/posix_FS.rs new file mode 100644 index 00000000..b1f01a66 --- /dev/null +++ b/src/lib/posix_FS.rs @@ -0,0 +1,32 @@ +native "rust" mod rustrt { + fn rust_dirent_filename(OS.libc.dirent ent) -> str; +} + +fn list_dir(str path) -> vec[str] { + // TODO ensure this is always closed + auto dir = OS.libc.opendir(Str.buf(path)); + assert (dir as uint != 0u); + let vec[str] result = vec(); + 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 = '/'; + +// Local Variables: +// mode: rust; +// fill-column: 78; +// indent-tabs-mode: nil +// c-basic-offset: 4 +// buffer-file-coding-system: utf-8-unix +// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; +// End: diff --git a/src/lib/posix_fs.rs b/src/lib/posix_fs.rs deleted file mode 100644 index 99f411e7..00000000 --- a/src/lib/posix_fs.rs +++ /dev/null @@ -1,32 +0,0 @@ -native "rust" mod rustrt { - fn rust_dirent_filename(os.libc.dirent ent) -> str; -} - -fn list_dir(str path) -> vec[str] { - // TODO ensure this is always closed - auto dir = os.libc.opendir(_str.buf(path)); - assert (dir as uint != 0u); - let vec[str] result = vec(); - 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 = '/'; - -// Local Variables: -// mode: rust; -// fill-column: 78; -// indent-tabs-mode: nil -// c-basic-offset: 4 -// buffer-file-coding-system: utf-8-unix -// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; -// End: diff --git a/src/lib/rand.rs b/src/lib/rand.rs deleted file mode 100644 index 06eb2f06..00000000 --- a/src/lib/rand.rs +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Bindings the runtime's random number generator (ISAAC). - */ - -native "rust" mod rustrt { - type rctx; - fn rand_new() -> rctx; - fn rand_next(rctx c) -> u32; - fn rand_free(rctx c); -} - -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); - } - } - - ret rt_rng(rustrt.rand_new()); -} - -// Local Variables: -// mode: rust; -// fill-column: 78; -// indent-tabs-mode: nil -// c-basic-offset: 4 -// buffer-file-coding-system: utf-8-unix -// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; -// End: diff --git a/src/lib/run_program.rs b/src/lib/run_program.rs deleted file mode 100644 index 31758984..00000000 --- a/src/lib/run_program.rs +++ /dev/null @@ -1,96 +0,0 @@ -import _str.sbuf; -import _vec.vbuf; - -native "rust" mod rustrt { - fn rust_run_program(vbuf argv, int in_fd, int out_fd, int err_fd) -> int; -} - -fn argvec(str prog, vec[str] args) -> vec[sbuf] { - auto argptrs = vec(_str.buf(prog)); - 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](argvec(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; - }; - -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](argvec(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;} - 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 finish() -> int { - 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); - } - } - 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) { - auto pr = start_program(prog, args); - pr.close_input(); - auto out = pr.output(); - auto buf = ""; - while (!out.eof()) { - auto bytes = out.read_bytes(4096u); - buf += _str.unsafe_from_bytes(bytes); - } - ret rec(status=pr.finish(), out=buf); -} - - -// Local Variables: -// mode: rust -// fill-column: 78; -// indent-tabs-mode: nil -// c-basic-offset: 4 -// buffer-file-coding-system: utf-8-unix -// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; -// End: diff --git a/src/lib/sha1.rs b/src/lib/sha1.rs deleted file mode 100644 index e84787a2..00000000 --- a/src/lib/sha1.rs +++ /dev/null @@ -1,294 +0,0 @@ -/* - * 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]); - - // Provide message input as string - fn input_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(); -}; - -// Some unexported constants -const uint digest_buf_len = 5; -const uint msg_block_len = 64; - -// 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); - - fn add_input(&sha1state st, &vec[u8] msg) { - // FIXME: Should be typestate precondition - 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); - } - } - } - - fn process_msg_block(&sha1state st) { - - // FIXME: Make precondition - assert (_vec.len(st.h) == digest_buf_len); - - // Constants - auto k = vec(0x5A827999u32, - 0x6ED9EBA1u32, - 0x8F1BBCDCu32, - 0xCA62C1D6u32); - - let int t; // Loop counter - let vec[mutable u32] w = _vec.init_elt_mut[u32](0u32, 80u); - - // Initialize the first 16 words of the vector w - t = 0; - while (t < 16) { - w.(t) = (st.msg_block.(t * 4) as u32) << 24u32; - w.(t) = w.(t) | ((st.msg_block.(t * 4 + 1) as u32) << 16u32); - w.(t) = w.(t) | ((st.msg_block.(t * 4 + 2) as u32) << 8u32); - w.(t) = w.(t) | (st.msg_block.(t * 4 + 3) as u32); - 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); - 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) + k.(0); - e = d; - d = c; - c = circular_shift(30u32, b); - b = a; - a = temp; - t += 1; - } - - while (t < 40) { - temp = circular_shift(5u32, a) - + (b ^ c ^ d) + e + w.(t) + k.(1); - e = d; - d = c; - c = circular_shift(30u32, b); - b = a; - a = temp; - t += 1; - } - - while (t < 60) { - temp = circular_shift(5u32, a) - + ((b & c) | (b & d) | (c & d)) + e + w.(t) + k.(2); - e = d; - d = c; - c = circular_shift(30u32, b); - b = a; - a = temp; - t += 1; - } - - while (t < 80) { - temp = circular_shift(5u32, a) - + (b ^ c ^ d) + e + w.(t) + k.(3); - e = d; - d = c; - c = circular_shift(30u32, b); - b = a; - 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)); - } - - fn mk_result(&sha1state st) -> vec[u8] { - if (!st.computed) { - pad_msg(st); - st.computed = true; - } - - let vec[u8] res = vec(); - 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 += vec(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 - * represent the length of the original message. All bits in between - * should be 0. This function will pad the message according to those - * rules by filling the msg_block vector accordingly. It will also - * 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); - - /* - * 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; - - process_msg_block(st); - } - - state obj sha1(sha1state st) { - - fn reset() { - // FIXME: Should be typestate precondition - 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 result_str() -> str { - auto r = mk_result(st); - auto s = ""; - 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); - auto sh = sha1(st); - sh.reset(); - ret sh; -} - -// Local Variables: -// mode: rust; -// fill-column: 78; -// indent-tabs-mode: nil -// c-basic-offset: 4 -// buffer-file-coding-system: utf-8-unix -// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; -// End: diff --git a/src/lib/sort.rs b/src/lib/sort.rs deleted file mode 100644 index f712d22e..00000000 --- a/src/lib/sort.rs +++ /dev/null @@ -1,101 +0,0 @@ -import _vec.len; -import _vec.slice; - -type lteq[T] = fn(&T a, &T b) -> 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 = vec(); - let uint a_len = len[T](a); - let uint a_ix = 0u; - let uint b_len = len[T](b); - let uint b_ix = 0u; - while (a_ix < a_len && b_ix < b_len) { - if (le(a.(a_ix), b.(b_ix))) { - res += vec(a.(a_ix)); - a_ix += 1u; - } else { - res += vec(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; - } - - 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)); -} - -fn swap[T](vec[mutable T] arr, uint x, uint y) { - auto a = arr.(x); - arr.(x) = arr.(y); - arr.(y) = a; -} - -fn part[T](lteq[T] compare_func, vec[mutable T] arr, uint left, - uint right, uint pivot) -> uint { - - fn compare[T](lteq[T] compare_func, vec[mutable T]arr, - uint arr_idx, &T arr_value) -> bool { - - ret compare_func(arr.(arr_idx),arr_value); - } - - auto pivot_value = arr.(pivot); - swap[T](arr, pivot, right); - let uint storage_index = left; - let uint i = left; - while (i left) { - auto pivot = (left+right)/2u; - auto new_pivot = part[T](compare_func, arr, left, right, pivot); - 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); -} - -// Local Variables: -// mode: rust; -// fill-column: 78; -// indent-tabs-mode: nil -// c-basic-offset: 4 -// buffer-file-coding-system: utf-8-unix -// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; -// End: diff --git a/src/lib/std.rc b/src/lib/std.rc index 44a0689c..a317b114 100644 --- a/src/lib/std.rc +++ b/src/lib/std.rc @@ -6,39 +6,38 @@ meta (name = "std", // Built-in types support modules. -mod _int; -mod _uint; -mod _u8; -mod _vec; -mod _str; +mod Int; +mod UInt; +mod U8; +mod Vec; +mod Str; // General IO and system-services modules. -mod io; -mod sys; -mod _task; +mod IO; +mod Sys; +mod Task; // Utility modules. -mod option; -mod util; +mod Option; +mod Util; // Authorize various rule-bendings. -auth io = unsafe; -auth fs = unsafe; -auth os = unsafe; -auth os_fs = unsafe; -auth run = unsafe; -auth _str = unsafe; -auth _vec = unsafe; -auth _task = unsafe; +auth IO = unsafe; +auth FS = unsafe; +auth OS_FS = unsafe; +auth Run = unsafe; +auth Str = unsafe; +auth Vec = unsafe; +auth Task = unsafe; -auth dbg = unsafe; +auth Dbg = unsafe; -auth _uint.next_power_of_two = unsafe; -auth map.mk_hashmap = unsafe; -auth rand.mk_rng = unsafe; +auth UInt.next_power_of_two = unsafe; +auth Map.mk_hashmap = unsafe; +auth Rand.mk_rng = unsafe; // Target-OS module. @@ -47,30 +46,30 @@ mod GenericOS; alt (target_os) { case ("win32") { - mod os = "win32_os.rs"; - mod os_fs = "win32_fs.rs"; + mod OS = "win32_OS.rs"; + mod OS_FS = "win32_FS.rs"; } case ("macos") { - mod os = "macos_os.rs"; - mod os_fs = "posix_fs.rs"; + mod OS = "macos_OS.rs"; + mod OS_FS = "posix_FS.rs"; } else { - mod os = "linux_os.rs"; - mod os_fs = "posix_fs.rs"; + mod OS = "linux_OS.rs"; + mod OS_FS = "posix_FS.rs"; } } -mod run = "run_program.rs"; -mod fs; +mod Run = "Run_Program.rs"; +mod FS; // FIXME: parametric -mod map; -mod deque; -mod list; -mod rand; -mod dbg; -mod bitv; -mod sort; -mod sha1; -mod ebml; +mod Map; +mod Deque; +mod List; +mod Rand; +mod Dbg; +mod BitV; +mod Sort; +mod SHA1; +mod EBML; mod UFind; mod ExtFmt; mod Box; diff --git a/src/lib/sys.rs b/src/lib/sys.rs deleted file mode 100644 index 77eab003..00000000 --- a/src/lib/sys.rs +++ /dev/null @@ -1,30 +0,0 @@ -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; - 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; -// indent-tabs-mode: nil -// c-basic-offset: 4 -// buffer-file-coding-system: utf-8-unix -// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; -// End: diff --git a/src/lib/util.rs b/src/lib/util.rs deleted file mode 100644 index 2f797f69..00000000 --- a/src/lib/util.rs +++ /dev/null @@ -1,33 +0,0 @@ -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); - -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 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; -// indent-tabs-mode: nil -// c-basic-offset: 4 -// buffer-file-coding-system: utf-8-unix -// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; -// End: diff --git a/src/lib/win32_FS.rs b/src/lib/win32_FS.rs new file mode 100644 index 00000000..94599e3c --- /dev/null +++ b/src/lib/win32_FS.rs @@ -0,0 +1,26 @@ +native "rust" mod rustrt { + 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+"*"); +} + +/* FIXME: win32 path handling actually accepts '/' or '\' and has subtly + * different semantics for each. Since we build on mingw, we are usually + * dealing with /-separated paths. But the whole interface to splitting and + * joining pathnames needs a bit more abstraction on win32. Possibly a vec or + * tag type. + */ +const char path_sep = '/'; +const char alt_path_sep = '\\'; + +// Local Variables: +// mode: rust; +// fill-column: 78; +// indent-tabs-mode: nil +// c-basic-offset: 4 +// buffer-file-coding-system: utf-8-unix +// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; +// End: diff --git a/src/lib/win32_OS.rs b/src/lib/win32_OS.rs new file mode 100644 index 00000000..b799287c --- /dev/null +++ b/src/lib/win32_OS.rs @@ -0,0 +1,80 @@ +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"; + + type FILE; + fn fopen(sbuf path, sbuf mode) -> FILE; + fn _fdopen(int fd, sbuf mode) -> FILE; + fn fclose(FILE f); + fn fgetc(FILE f) -> int; + fn ungetc(int c, FILE f); + fn feof(FILE f) -> int; + fn fread(vbuf buf, uint size, uint n, FILE f) -> uint; + 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 S_IRUSR() -> uint { ret 0x0100u; } // really _S_IREAD in win32 + fn S_IWUSR() -> uint { ret 0x0080u; } // really _S_IWRITE in win32 +} + +fn exec_suffix() -> str { + ret ".exe"; +} + +fn target_os() -> str { + ret "win32"; +} + +fn dylib_filename(str base) -> str { + ret base + ".dll"; +} + +fn pipe() -> tup(int, int) { + let vec[mutable int] fds = vec(mutable 0, 0); + assert (OS.libc._pipe(Vec.buf[mutable int](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")); +} + +native "rust" mod rustrt { + fn rust_process_wait(int handle) -> int; +} + +fn waitpid(int pid) -> int { + ret rustrt.rust_process_wait(pid); +} + +// Local Variables: +// mode: rust; +// fill-column: 78; +// indent-tabs-mode: nil +// c-basic-offset: 4 +// buffer-file-coding-system: utf-8-unix +// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; +// End: diff --git a/src/lib/win32_fs.rs b/src/lib/win32_fs.rs deleted file mode 100644 index 94599e3c..00000000 --- a/src/lib/win32_fs.rs +++ /dev/null @@ -1,26 +0,0 @@ -native "rust" mod rustrt { - 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+"*"); -} - -/* FIXME: win32 path handling actually accepts '/' or '\' and has subtly - * different semantics for each. Since we build on mingw, we are usually - * dealing with /-separated paths. But the whole interface to splitting and - * joining pathnames needs a bit more abstraction on win32. Possibly a vec or - * tag type. - */ -const char path_sep = '/'; -const char alt_path_sep = '\\'; - -// Local Variables: -// mode: rust; -// fill-column: 78; -// indent-tabs-mode: nil -// c-basic-offset: 4 -// buffer-file-coding-system: utf-8-unix -// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; -// End: diff --git a/src/lib/win32_os.rs b/src/lib/win32_os.rs deleted file mode 100644 index 1c6521e3..00000000 --- a/src/lib/win32_os.rs +++ /dev/null @@ -1,80 +0,0 @@ -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"; - - type FILE; - fn fopen(sbuf path, sbuf mode) -> FILE; - fn _fdopen(int fd, sbuf mode) -> FILE; - fn fclose(FILE f); - fn fgetc(FILE f) -> int; - fn ungetc(int c, FILE f); - fn feof(FILE f) -> int; - fn fread(vbuf buf, uint size, uint n, FILE f) -> uint; - 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 S_IRUSR() -> uint { ret 0x0100u; } // really _S_IREAD in win32 - fn S_IWUSR() -> uint { ret 0x0080u; } // really _S_IWRITE in win32 -} - -fn exec_suffix() -> str { - ret ".exe"; -} - -fn target_os() -> str { - ret "win32"; -} - -fn dylib_filename(str base) -> str { - ret base + ".dll"; -} - -fn pipe() -> tup(int, int) { - let vec[mutable int] fds = vec(mutable 0, 0); - assert (os.libc._pipe(_vec.buf[mutable int](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")); -} - -native "rust" mod rustrt { - fn rust_process_wait(int handle) -> int; -} - -fn waitpid(int pid) -> int { - ret rustrt.rust_process_wait(pid); -} - -// Local Variables: -// mode: rust; -// fill-column: 78; -// indent-tabs-mode: nil -// c-basic-offset: 4 -// buffer-file-coding-system: utf-8-unix -// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; -// End: -- cgit v1.2.3