1
Fork 0

Copy first batch of material from libstd to libcore.

This commit is contained in:
Graydon Hoare 2011-12-13 16:25:51 -08:00
parent 32087f5c2a
commit fa9ad984fb
325 changed files with 5579 additions and 720 deletions

View file

@ -6,13 +6,13 @@ import rustc::syntax::parse::parser;
import std::fs; import std::fs;
import std::generic_os; import std::generic_os;
import std::io; import std::io;
import std::option; import option;
import std::option::{none, some}; import option::{none, some};
import std::os; import std::os;
import std::run; import std::run;
import std::str; import str;
import std::tempfile; import std::tempfile;
import std::vec; import vec;
type cargo = { type cargo = {
root: str, root: str,

View file

@ -5,10 +5,10 @@ import front::attr;
import middle::ty; import middle::ty;
import metadata::{encoder, cstore}; import metadata::{encoder, cstore};
import middle::trans_common::crate_ctxt; import middle::trans_common::crate_ctxt;
import std::str; import str;
import std::fs; import std::fs;
import std::vec; import vec;
import std::option; import option;
import std::run; import std::run;
import option::some; import option::some;
import option::none; import option::none;
@ -32,7 +32,7 @@ tag output_type {
fn llvm_err(sess: session::session, msg: str) unsafe { fn llvm_err(sess: session::session, msg: str) unsafe {
let buf = llvm::LLVMRustGetLastError(); let buf = llvm::LLVMRustGetLastError();
if buf == std::ptr::null() { if buf == ptr::null() {
sess.fatal(msg); sess.fatal(msg);
} else { sess.fatal(msg + ": " + str::str_from_cstr(buf)); } } else { sess.fatal(msg + ": " + str::str_from_cstr(buf)); }
} }

View file

@ -1,11 +1,11 @@
import std::os; import std::os;
import std::fs; import std::fs;
import std::os_fs; import std::os_fs;
import std::vec; import vec;
import std::map; import std::map;
import std::math; import std::math;
import std::str; import str;
import std::uint; import uint;
import metadata::cstore; import metadata::cstore;
import driver::session; import driver::session;
import util::filesearch; import util::filesearch;

View file

@ -10,9 +10,10 @@ import middle::{trans, resolve, freevars, kind, ty, typeck, fn_usage,
import syntax::print::{pp, pprust}; import syntax::print::{pp, pprust};
import util::{ppaux, filesearch}; import util::{ppaux, filesearch};
import back::link; import back::link;
import std::{fs, option, str, vec, int, io, getopts, result}; import core::{option, str, vec, int, result};
import std::option::{some, none}; import std::{fs, io, getopts};
import std::getopts::{optopt, optmulti, optflag, optflagopt, opt_present}; import option::{some, none};
import getopts::{optopt, optmulti, optflag, optflagopt, opt_present};
import back::{x86, x86_64}; import back::{x86, x86_64};
tag pp_mode { ppm_normal; ppm_expanded; ppm_typed; ppm_identified; } tag pp_mode { ppm_normal; ppm_expanded; ppm_typed; ppm_identified; }
@ -104,7 +105,7 @@ fn time<T>(do_it: bool, what: str, thunk: fn@() -> T) -> T {
let rv = thunk(); let rv = thunk();
let end = std::time::precise_time_s(); let end = std::time::precise_time_s();
log_err #fmt["time: %s took %s s", what, log_err #fmt["time: %s took %s s", what,
std::float::to_str(end - start, 3u)]; float::to_str(end - start, 3u)];
ret rv; ret rv;
} }

View file

@ -3,8 +3,8 @@ import syntax::{ast, codemap};
import syntax::ast::node_id; import syntax::ast::node_id;
import codemap::span; import codemap::span;
import syntax::ast::{int_ty, uint_ty, float_ty}; import syntax::ast::{int_ty, uint_ty, float_ty};
import std::{option}; import option;
import std::option::{some, none}; import option::{some, none};
import syntax::parse::parser::parse_sess; import syntax::parse::parser::parse_sess;
import util::filesearch; import util::filesearch;
import back::target_strs; import back::target_strs;

View file

@ -1,6 +1,7 @@
// Functions dealing with attributes and meta_items // Functions dealing with attributes and meta_items
import std::{either, vec, map, option}; import core::{either, vec, option};
import std::map;
import syntax::{ast, ast_util}; import syntax::{ast, ast_util};
import driver::session; import driver::session;

View file

@ -1,4 +1,4 @@
import std::{vec, option}; import core::{vec, option};
import syntax::{ast, fold}; import syntax::{ast, fold};
import attr; import attr;

View file

@ -1,6 +1,6 @@
// Code that generates a test runner to run all the tests in a crate // Code that generates a test runner to run all the tests in a crate
import std::{option, vec}; import core::{option, vec};
import syntax::{ast, ast_util}; import syntax::{ast, ast_util};
import syntax::ast_util::*; import syntax::ast_util::*;
//import syntax::ast_util::dummy_sp; //import syntax::ast_util::dummy_sp;

View file

@ -1,5 +1,5 @@
import std::{vec, str, option}; import core::{vec, str, option};
import std::str::sbuf; import str::sbuf;
import llvm::{TypeRef, MemoryBufferRef, import llvm::{TypeRef, MemoryBufferRef,
PassManagerRef, TargetDataRef, PassManagerRef, TargetDataRef,
@ -960,7 +960,7 @@ fn type_to_str_inner(names: type_names, outer0: [TypeRef], ty: TypeRef) ->
5 { ret "PPC_FP128"; } 5 { ret "PPC_FP128"; }
6 { ret "Label"; } 6 { ret "Label"; }
7 { 7 {
ret "i" + std::int::str(llvm::LLVMGetIntTypeWidth(ty) as int); ret "i" + int::str(llvm::LLVMGetIntTypeWidth(ty) as int);
} }
8 { 8 {
let s = "fn("; let s = "fn(";
@ -996,7 +996,7 @@ fn type_to_str_inner(names: type_names, outer0: [TypeRef], ty: TypeRef) ->
i += 1u; i += 1u;
if tout as int == ty as int { if tout as int == ty as int {
let n: uint = vec::len::<TypeRef>(outer0) - i; let n: uint = vec::len::<TypeRef>(outer0) - i;
ret "*\\" + std::int::str(n as int); ret "*\\" + int::str(n as int);
} }
} }
ret "*" + ret "*" +

View file

@ -1,6 +1,6 @@
// EBML tag definitions and utils shared by the encoder and decoder // EBML tag definitions and utils shared by the encoder and decoder
import std::str; import str;
const tag_paths: uint = 0x01u; const tag_paths: uint = 0x01u;

View file

@ -7,8 +7,9 @@ import front::attr;
import syntax::visit; import syntax::visit;
import syntax::codemap::span; import syntax::codemap::span;
import util::{filesearch}; import util::{filesearch};
import std::{either, vec, str, fs, io, option}; import core::{either, vec, str, option};
import std::option::{none, some}; import std::{io, fs};
import option::{none, some};
import std::map::{hashmap, new_int_hash}; import std::map::{hashmap, new_int_hash};
import syntax::print::pprust; import syntax::print::pprust;
import common::*; import common::*;
@ -206,7 +207,7 @@ fn get_metadata_section(sess: session::session,
let cbuf = llvm::LLVMGetSectionContents(si.llsi); let cbuf = llvm::LLVMGetSectionContents(si.llsi);
let csz = llvm::LLVMGetSectionSize(si.llsi); let csz = llvm::LLVMGetSectionSize(si.llsi);
unsafe { unsafe {
let cvbuf: *u8 = std::unsafe::reinterpret_cast(cbuf); let cvbuf: *u8 = unsafe::reinterpret_cast(cbuf);
ret option::some::<@[u8]>(@vec::unsafe::from_buf(cvbuf, csz)); ret option::some::<@[u8]>(@vec::unsafe::from_buf(cvbuf, csz));
} }
} }

View file

@ -2,7 +2,7 @@
import syntax::ast; import syntax::ast;
import middle::ty; import middle::ty;
import std::option; import option;
import driver::session; import driver::session;
export get_symbol; export get_symbol;

View file

@ -1,7 +1,8 @@
// The crate store - a central repo for information collected about external // The crate store - a central repo for information collected about external
// crates and libraries // crates and libraries
import std::{vec, map, str}; import core::{vec, str};
import std::map;
import syntax::ast; import syntax::ast;
export cstore; export cstore;

View file

@ -1,6 +1,7 @@
// Decoding metadata from a single crate's metadata // Decoding metadata from a single crate's metadata
import std::{ebml, vec, option, str, io}; import core::{vec, option, str};
import std::{ebml, io};
import syntax::{ast, ast_util}; import syntax::{ast, ast_util};
import front::attr; import front::attr;
import middle::ty; import middle::ty;

View file

@ -1,6 +1,7 @@
// Metadata encoding // Metadata encoding
import std::{vec, str, uint, io, ebml, map}; import core::{vec, str, uint};
import std::{io, ebml, map};
import syntax::ast::*; import syntax::ast::*;
import syntax::ast_util; import syntax::ast_util;
import syntax::ast_util::local_def; import syntax::ast_util::local_def;

View file

@ -1,7 +1,7 @@
// Type decoding // Type decoding
import std::{vec, str, uint}; import core::{vec, str, uint};
import std::option::{none, some}; import option::{none, some};
import syntax::ast; import syntax::ast;
import syntax::ast::*; import syntax::ast::*;
import syntax::ast_util; import syntax::ast_util;

View file

@ -1,8 +1,9 @@
// Type encoding // Type encoding
import std::{io, int, uint}; import core::{int, uint};
import std::io;
import std::map::hashmap; import std::map::hashmap;
import std::option::{some, none}; import option::{some, none};
import syntax::ast::*; import syntax::ast::*;
import middle::ty; import middle::ty;
import syntax::print::pprust::*; import syntax::print::pprust::*;

View file

@ -4,8 +4,9 @@ import ast::{ident, fn_ident, node_id};
import syntax::codemap::span; import syntax::codemap::span;
import syntax::visit; import syntax::visit;
import visit::vt; import visit::vt;
import std::{vec, option, list}; import core::{vec, option};
import std::option::{some, none, is_none}; import std::list;
import option::{some, none, is_none};
import list::list; import list::list;
// This is not an alias-analyser (though it would merit from becoming one, or // This is not an alias-analyser (though it would merit from becoming one, or

View file

@ -1,4 +1,5 @@
import std::{smallintmap, option}; import option;
import std::smallintmap;
import syntax::ast::*; import syntax::ast::*;
import syntax::ast_util; import syntax::ast_util;
import syntax::{visit, codemap}; import syntax::{visit, codemap};

View file

@ -2,7 +2,7 @@ import syntax::ast::*;
import syntax::ast_util::{variant_def_ids, dummy_sp, compare_lit_exprs, import syntax::ast_util::{variant_def_ids, dummy_sp, compare_lit_exprs,
lit_expr_eq}; lit_expr_eq};
import syntax::visit; import syntax::visit;
import std::option::{some, none}; import option::{some, none};
fn check_crate(tcx: ty::ctxt, crate: @crate) { fn check_crate(tcx: ty::ctxt, crate: @crate) {
let v = let v =
@ -25,7 +25,7 @@ fn check_arms(tcx: ty::ctxt, arms: [arm]) {
let reachable = true; let reachable = true;
let j = 0; let j = 0;
while j < i { while j < i {
if std::option::is_none(arms[j].guard) { if option::is_none(arms[j].guard) {
for prev_pat: @pat in arms[j].pats { for prev_pat: @pat in arms[j].pats {
if pattern_supersedes(tcx, prev_pat, arm_pat) { if pattern_supersedes(tcx, prev_pat, arm_pat) {
reachable = false; reachable = false;
@ -149,7 +149,7 @@ fn is_refutable(tcx: ty::ctxt, pat: @pat) -> bool {
} }
pat_tag(_, args) { pat_tag(_, args) {
let vdef = variant_def_ids(tcx.def_map.get(pat.id)); let vdef = variant_def_ids(tcx.def_map.get(pat.id));
if std::vec::len(ty::tag_variants(tcx, vdef.tg)) != 1u { ret true; } if vec::len(ty::tag_variants(tcx, vdef.tg)) != 1u { ret true; }
for p: @pat in args { if is_refutable(tcx, p) { ret true; } } for p: @pat in args { if is_refutable(tcx, p) { ret true; } }
false false
} }

View file

@ -1,6 +1,6 @@
import syntax::ast; import syntax::ast;
import syntax::visit; import syntax::visit;
import std::option::some; import option::some;
import syntax::print::pprust::expr_to_str; import syntax::print::pprust::expr_to_str;
export check_crate_fn_usage; export check_crate_fn_usage;

View file

@ -1,9 +1,9 @@
// A pass that annotates for each loops and functions with the free // A pass that annotates for each loops and functions with the free
// variables that they contain. // variables that they contain.
import std::{int}; import int;
import std::map::*; import std::map::*;
import std::option::*; import option::*;
import syntax::{ast, ast_util, visit}; import syntax::{ast, ast_util, visit};
import middle::resolve; import middle::resolve;
import syntax::codemap::span; import syntax::codemap::span;
@ -101,7 +101,7 @@ fn get_freevars(tcx: ty::ctxt, fid: ast::node_id) -> freevar_info {
} }
} }
fn has_freevars(tcx: ty::ctxt, fid: ast::node_id) -> bool { fn has_freevars(tcx: ty::ctxt, fid: ast::node_id) -> bool {
ret std::vec::len(*get_freevars(tcx, fid)) != 0u; ret vec::len(*get_freevars(tcx, fid)) != 0u;
} }
// Local Variables: // Local Variables:

View file

@ -6,8 +6,8 @@ import middle::trans;
import middle::trans::{get_tydesc, tps_normal}; import middle::trans::{get_tydesc, tps_normal};
import middle::trans_common::*; import middle::trans_common::*;
import middle::ty; import middle::ty;
import std::option::none; import option::none;
import std::str; import str;
import lll = lib::llvm::llvm; import lll = lib::llvm::llvm;
import bld = trans_build; import bld = trans_build;

View file

@ -1,4 +1,4 @@
import std::option::{some, none}; import option::{some, none};
import syntax::{visit, ast_util}; import syntax::{visit, ast_util};
import syntax::ast::*; import syntax::ast::*;
import syntax::codemap::span; import syntax::codemap::span;
@ -64,7 +64,7 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) {
let t = ty::expr_ty(cx.tcx, ex); let t = ty::expr_ty(cx.tcx, ex);
let ty_fields = alt ty::struct(cx.tcx, t) { ty::ty_rec(f) { f } }; let ty_fields = alt ty::struct(cx.tcx, t) { ty::ty_rec(f) { f } };
for tf in ty_fields { for tf in ty_fields {
if !std::vec::any({|f| f.node.ident == tf.ident}, fields) && if !vec::any({|f| f.node.ident == tf.ident}, fields) &&
ty::type_kind(cx.tcx, tf.mt.ty) == kind_noncopyable { ty::type_kind(cx.tcx, tf.mt.ty) == kind_noncopyable {
cx.tcx.sess.span_err(ex.span, cx.tcx.sess.span_err(ex.span,
"copying a noncopyable value"); "copying a noncopyable value");

View file

@ -1,7 +1,8 @@
import syntax::{visit, ast_util}; import syntax::{visit, ast_util};
import syntax::ast::*; import syntax::ast::*;
import std::list::{list, nil, cons, tail}; import std::list::{list, nil, cons, tail};
import std::{vec, list, option}; import core::{vec, option};
import std::list;
// Last use analysis pass. // Last use analysis pass.
// //

View file

@ -1,4 +1,4 @@
import std::{vec, str, option}; import core::{vec, str, option};
import option::{some, none}; import option::{some, none};
import syntax::ast::*; import syntax::ast::*;
import syntax::visit; import syntax::visit;

View file

@ -11,10 +11,11 @@ import std::map::{new_int_hash, new_str_hash};
import syntax::codemap::span; import syntax::codemap::span;
import syntax::visit; import syntax::visit;
import visit::vt; import visit::vt;
import std::{vec, list, option, str}; import core::{vec, option, str};
import std::list;
import std::map::hashmap; import std::map::hashmap;
import std::list::{list, nil, cons}; import std::list::{list, nil, cons};
import std::option::{some, none, is_none}; import option::{some, none, is_none};
import syntax::print::pprust::*; import syntax::print::pprust::*;
export resolve_crate; export resolve_crate;

View file

@ -14,9 +14,9 @@ import syntax::ast_util::dummy_sp;
import syntax::util::interner; import syntax::util::interner;
import util::common; import util::common;
import std::{vec, str}; import core::{vec, str};
import std::map::hashmap; import std::map::hashmap;
import std::option::{none, some}; import option::{none, some};
import ty_ctxt = middle::ty::ctxt; import ty_ctxt = middle::ty::ctxt;

View file

@ -12,10 +12,12 @@
// pcwalton). You can, instead, find out its TypeRef by calling val_ty, // pcwalton). You can, instead, find out its TypeRef by calling val_ty,
// but many TypeRefs correspond to one ty::t; for instance, tup(int, int, // but many TypeRefs correspond to one ty::t; for instance, tup(int, int,
// int) and rec(x=int, y=int, z=int) will have the same TypeRef. // int) and rec(x=int, y=int, z=int) will have the same TypeRef.
import std::{either, str, uint, map, option, time, vec};
import core::{either, str, uint, option, vec};
import std::{map, time};
import std::map::hashmap; import std::map::hashmap;
import std::map::{new_int_hash, new_str_hash}; import std::map::{new_int_hash, new_str_hash};
import std::option::{some, none}; import option::{some, none};
import driver::session; import driver::session;
import front::attr; import front::attr;
import middle::{ty, gc}; import middle::{ty, gc};
@ -205,7 +207,7 @@ fn type_of_inner(cx: @crate_ctxt, sp: span, t: ty::t)
fn type_of_tag(cx: @crate_ctxt, sp: span, did: ast::def_id, t: ty::t) fn type_of_tag(cx: @crate_ctxt, sp: span, did: ast::def_id, t: ty::t)
-> TypeRef { -> TypeRef {
let degen = std::vec::len(ty::tag_variants(cx.tcx, did)) == 1u; let degen = vec::len(ty::tag_variants(cx.tcx, did)) == 1u;
if check type_has_static_size(cx, t) { if check type_has_static_size(cx, t) {
let size = static_size_of_tag(cx, sp, t); let size = static_size_of_tag(cx, sp, t);
if !degen { T_tag(cx, size) } if !degen { T_tag(cx, size) }
@ -225,7 +227,7 @@ fn type_of_ty_param_kinds_and_ty(lcx: @local_ctxt, sp: span,
alt ty::struct(cx.tcx, t) { alt ty::struct(cx.tcx, t) {
ty::ty_fn(_, _, _, _, _) | ty::ty_native_fn(_, _) { ty::ty_fn(_, _, _, _, _) | ty::ty_native_fn(_, _) {
check returns_non_ty_var(cx, t); check returns_non_ty_var(cx, t);
ret type_of_fn_from_ty(cx, sp, t, std::vec::len(tpt.kinds)); ret type_of_fn_from_ty(cx, sp, t, vec::len(tpt.kinds));
} }
_ { _ {
// fall through // fall through
@ -328,7 +330,7 @@ fn get_simple_extern_fn(cx: @block_ctxt,
llmod: ModuleRef, llmod: ModuleRef,
name: str, n_args: int) -> ValueRef { name: str, n_args: int) -> ValueRef {
let ccx = cx.fcx.lcx.ccx; let ccx = cx.fcx.lcx.ccx;
let inputs = std::vec::init_elt::<TypeRef>(ccx.int_type, n_args as uint); let inputs = vec::init_elt::<TypeRef>(ccx.int_type, n_args as uint);
let output = ccx.int_type; let output = ccx.int_type;
let t = T_fn(inputs, output); let t = T_fn(inputs, output);
ret get_extern_fn(externs, llmod, name, lib::llvm::LLVMCCallConv, t); ret get_extern_fn(externs, llmod, name, lib::llvm::LLVMCCallConv, t);
@ -337,7 +339,7 @@ fn get_simple_extern_fn(cx: @block_ctxt,
fn trans_native_call(cx: @block_ctxt, externs: hashmap<str, ValueRef>, fn trans_native_call(cx: @block_ctxt, externs: hashmap<str, ValueRef>,
llmod: ModuleRef, name: str, args: [ValueRef]) -> llmod: ModuleRef, name: str, args: [ValueRef]) ->
ValueRef { ValueRef {
let n: int = std::vec::len::<ValueRef>(args) as int; let n: int = vec::len::<ValueRef>(args) as int;
let llnative: ValueRef = let llnative: ValueRef =
get_simple_extern_fn(cx, externs, llmod, name, n); get_simple_extern_fn(cx, externs, llmod, name, n);
let call_args: [ValueRef] = []; let call_args: [ValueRef] = [];
@ -600,7 +602,7 @@ fn dynamic_size_of(cx: @block_ctxt, t: ty::t, mode: align_mode) -> result {
} }
let max_size_val = Load(bcx, max_size); let max_size_val = Load(bcx, max_size);
let total_size = let total_size =
if std::vec::len(variants) != 1u { if vec::len(variants) != 1u {
Add(bcx, max_size_val, llsize_of(ccx, ccx.int_type)) Add(bcx, max_size_val, llsize_of(ccx, ccx.int_type))
} else { max_size_val }; } else { max_size_val };
ret rslt(bcx, total_size); ret rslt(bcx, total_size);
@ -693,7 +695,7 @@ fn GEP_tup_like(cx: @block_ctxt, t: ty::t, base: ValueRef, ixs: [int])
fn split_type(ccx: @crate_ctxt, t: ty::t, ixs: [int], n: uint) -> fn split_type(ccx: @crate_ctxt, t: ty::t, ixs: [int], n: uint) ->
{prefix: [ty::t], target: ty::t} { {prefix: [ty::t], target: ty::t} {
let len: uint = std::vec::len::<int>(ixs); let len: uint = vec::len::<int>(ixs);
// We don't support 0-index or 1-index GEPs: The former is nonsense // We don't support 0-index or 1-index GEPs: The former is nonsense
// and the latter would only be meaningful if we supported non-0 // and the latter would only be meaningful if we supported non-0
// values for the 0th index (we don't). // values for the 0th index (we don't).
@ -972,8 +974,8 @@ fn get_derived_tydesc(cx: @block_ctxt, t: ty::t, escapes: bool,
// promising to do so itself. // promising to do so itself.
let n_params = ty::count_ty_params(bcx_tcx(bcx), t); let n_params = ty::count_ty_params(bcx_tcx(bcx), t);
assert (n_params == std::vec::len::<uint>(tys.params)); assert (n_params == vec::len::<uint>(tys.params));
assert (n_params == std::vec::len::<ValueRef>(tys.descs)); assert (n_params == vec::len::<ValueRef>(tys.descs));
let llparamtydescs = let llparamtydescs =
alloca(bcx, T_array(T_ptr(bcx_ccx(bcx).tydesc_type), n_params + 1u)); alloca(bcx, T_array(T_ptr(bcx_ccx(bcx).tydesc_type), n_params + 1u));
@ -1042,7 +1044,7 @@ fn get_tydesc(cx: @block_ctxt, orig_t: ty::t, escapes: bool,
"orig_t = " + "orig_t = " +
ty_to_str(bcx_tcx(cx), orig_t) + ty_to_str(bcx_tcx(cx), orig_t) +
" ty_param = " + " ty_param = " +
std::uint::str(id)); uint::str(id));
} }
} }
none. {/* fall through */ } none. {/* fall through */ }
@ -1192,7 +1194,7 @@ fn make_generic_glue_inner(cx: @local_ctxt, sp: span, t: ty::t,
T_ptr(type_of(ccx, sp, t)) T_ptr(type_of(ccx, sp, t))
} else { T_ptr(T_i8()) }; } else { T_ptr(T_i8()) };
let ty_param_count = std::vec::len::<uint>(ty_params); let ty_param_count = vec::len::<uint>(ty_params);
let lltyparams = llvm::LLVMGetParam(llfn, 2u); let lltyparams = llvm::LLVMGetParam(llfn, 2u);
let load_env_bcx = new_raw_block_ctxt(fcx, fcx.llloadenv); let load_env_bcx = new_raw_block_ctxt(fcx, fcx.llloadenv);
let lltydescs = [mutable]; let lltydescs = [mutable];
@ -1200,7 +1202,7 @@ fn make_generic_glue_inner(cx: @local_ctxt, sp: span, t: ty::t,
while p < ty_param_count { while p < ty_param_count {
let llparam = GEPi(load_env_bcx, lltyparams, [p as int]); let llparam = GEPi(load_env_bcx, lltyparams, [p as int]);
llparam = Load(load_env_bcx, llparam); llparam = Load(load_env_bcx, llparam);
std::vec::grow_set(lltydescs, ty_params[p], 0 as ValueRef, llparam); vec::grow_set(lltydescs, ty_params[p], 0 as ValueRef, llparam);
p += 1u; p += 1u;
} }
@ -1453,7 +1455,7 @@ fn trans_res_drop(cx: @block_ctxt, rs: ValueRef, did: ast::def_id,
// for type variables. // for type variables.
let val_llty = lib::llvm::fn_ty_param_tys let val_llty = lib::llvm::fn_ty_param_tys
(llvm::LLVMGetElementType (llvm::LLVMGetElementType
(llvm::LLVMTypeOf(dtor_addr)))[std::vec::len(args)]; (llvm::LLVMTypeOf(dtor_addr)))[vec::len(args)];
let val_cast = BitCast(cx, val.val, val_llty); let val_cast = BitCast(cx, val.val, val_llty);
Call(cx, dtor_addr, args + [val_cast]); Call(cx, dtor_addr, args + [val_cast]);
@ -1608,7 +1610,7 @@ fn iter_structural_ty(cx: @block_ctxt, av: ValueRef, t: ty::t,
fn iter_variant(cx: @block_ctxt, a_tup: ValueRef, fn iter_variant(cx: @block_ctxt, a_tup: ValueRef,
variant: ty::variant_info, tps: [ty::t], tid: ast::def_id, variant: ty::variant_info, tps: [ty::t], tid: ast::def_id,
f: val_and_ty_fn) -> @block_ctxt { f: val_and_ty_fn) -> @block_ctxt {
if std::vec::len::<ty::t>(variant.args) == 0u { ret cx; } if vec::len::<ty::t>(variant.args) == 0u { ret cx; }
let fn_ty = variant.ctor_ty; let fn_ty = variant.ctor_ty;
let ccx = bcx_ccx(cx); let ccx = bcx_ccx(cx);
let cx = cx; let cx = cx;
@ -1667,7 +1669,7 @@ fn iter_structural_ty(cx: @block_ctxt, av: ValueRef, t: ty::t,
} }
ty::ty_tag(tid, tps) { ty::ty_tag(tid, tps) {
let variants = ty::tag_variants(bcx_tcx(cx), tid); let variants = ty::tag_variants(bcx_tcx(cx), tid);
let n_variants = std::vec::len(variants); let n_variants = vec::len(variants);
// Cast the tags to types we can GEP into. // Cast the tags to types we can GEP into.
if n_variants == 1u { if n_variants == 1u {
@ -2351,8 +2353,8 @@ fn autoderef(cx: @block_ctxt, v: ValueRef, t: ty::t) -> result_t {
} }
ty::ty_tag(did, tps) { ty::ty_tag(did, tps) {
let variants = ty::tag_variants(ccx.tcx, did); let variants = ty::tag_variants(ccx.tcx, did);
if std::vec::len(variants) != 1u || if vec::len(variants) != 1u ||
std::vec::len(variants[0].args) != 1u { vec::len(variants[0].args) != 1u {
break; break;
} }
t1 = t1 =
@ -2580,9 +2582,9 @@ fn build_environment(bcx: @block_ctxt, lltydescs: [ValueRef],
// Make a vector that contains ty_param_count copies of tydesc_ty. // Make a vector that contains ty_param_count copies of tydesc_ty.
// (We'll need room for that many tydescs in the closure.) // (We'll need room for that many tydescs in the closure.)
let ty_param_count = std::vec::len(lltydescs); let ty_param_count = vec::len(lltydescs);
let tydesc_ty: ty::t = ty::mk_type(tcx); let tydesc_ty: ty::t = ty::mk_type(tcx);
let captured_tys: [ty::t] = std::vec::init_elt(tydesc_ty, ty_param_count); let captured_tys: [ty::t] = vec::init_elt(tydesc_ty, ty_param_count);
// Get all the types we've got (some of which we synthesized // Get all the types we've got (some of which we synthesized
// ourselves) into a vector. The whole things ends up looking // ourselves) into a vector. The whole things ends up looking
@ -2746,7 +2748,7 @@ fn load_environment(enclosing_cx: @block_ctxt, fcx: @fn_ctxt, envty: ty::t,
// Populate the type parameters from the environment. We need to // Populate the type parameters from the environment. We need to
// do this first because the tydescs are needed to index into // do this first because the tydescs are needed to index into
// the bindings if they are dynamically sized. // the bindings if they are dynamically sized.
let tydesc_count = std::vec::len(enclosing_cx.fcx.lltydescs); let tydesc_count = vec::len(enclosing_cx.fcx.lltydescs);
let lltydescs = find_environment_tydescs(bcx, envty, llclosure); let lltydescs = find_environment_tydescs(bcx, envty, llclosure);
let i = 0u; let i = 0u;
while i < tydesc_count { while i < tydesc_count {
@ -2854,7 +2856,7 @@ fn lval_static_fn(bcx: @block_ctxt, tpt: ty::ty_param_kinds_and_ty,
}; };
let tys = ty::node_id_to_type_params(bcx_tcx(bcx), id); let tys = ty::node_id_to_type_params(bcx_tcx(bcx), id);
let gen = none, bcx = bcx; let gen = none, bcx = bcx;
if std::vec::len::<ty::t>(tys) != 0u { if vec::len::<ty::t>(tys) != 0u {
let tydescs = [], tis = []; let tydescs = [], tis = [];
for t in tys { for t in tys {
// TODO: Doesn't always escape. // TODO: Doesn't always escape.
@ -2950,7 +2952,7 @@ fn trans_var(cx: @block_ctxt, sp: span, def: ast::def, id: ast::node_id)
let bcx = alloc_result.bcx; let bcx = alloc_result.bcx;
let lltagptr = PointerCast(bcx, lltagblob, T_ptr(lltagty)); let lltagptr = PointerCast(bcx, lltagblob, T_ptr(lltagty));
let lldiscrimptr = GEPi(bcx, lltagptr, [0, 0]); let lldiscrimptr = GEPi(bcx, lltagptr, [0, 0]);
let d = if std::vec::len(ty::tag_variants(ccx.tcx, tid)) != 1u { let d = if vec::len(ty::tag_variants(ccx.tcx, tid)) != 1u {
let lldiscrim_gv = lookup_discriminant(bcx.fcx.lcx, vid); let lldiscrim_gv = lookup_discriminant(bcx.fcx.lcx, vid);
let lldiscrim = Load(bcx, lldiscrim_gv); let lldiscrim = Load(bcx, lldiscrim_gv);
lldiscrim lldiscrim
@ -3166,8 +3168,8 @@ fn maybe_add_env(bcx: @block_ctxt, c: lval_maybe_callee)
fn lval_maybe_callee_to_lval(c: lval_maybe_callee, ty: ty::t) -> lval_result { fn lval_maybe_callee_to_lval(c: lval_maybe_callee, ty: ty::t) -> lval_result {
alt c.generic { alt c.generic {
some(gi) { some(gi) {
let n_args = std::vec::len(ty::ty_fn_args(bcx_tcx(c.bcx), ty)); let n_args = vec::len(ty::ty_fn_args(bcx_tcx(c.bcx), ty));
let args = std::vec::init_elt(none::<@ast::expr>, n_args); let args = vec::init_elt(none::<@ast::expr>, n_args);
let space = alloc_ty(c.bcx, ty); let space = alloc_ty(c.bcx, ty);
let bcx = trans_bind_1(space.bcx, ty, c, args, ty, let bcx = trans_bind_1(space.bcx, ty, c, args, ty,
save_in(space.val)); save_in(space.val));
@ -3490,8 +3492,8 @@ fn trans_bind_1(cx: @block_ctxt, outgoing_fty: ty::t,
} }
} }
let ty_param_count = std::vec::len(lltydescs); let ty_param_count = vec::len(lltydescs);
if std::vec::len(bound) == 0u && ty_param_count == 0u { if vec::len(bound) == 0u && ty_param_count == 0u {
// Trivial 'binding': just return the closure // Trivial 'binding': just return the closure
let lv = lval_maybe_callee_to_lval(f_res, pair_ty); let lv = lval_maybe_callee_to_lval(f_res, pair_ty);
bcx = lv.bcx; bcx = lv.bcx;
@ -4598,9 +4600,9 @@ fn trans_block_cleanups(bcx: @block_ctxt, cleanup_cx: @block_ctxt) ->
@block_ctxt { @block_ctxt {
if bcx.unreachable { ret bcx; } if bcx.unreachable { ret bcx; }
if cleanup_cx.kind == NON_SCOPE_BLOCK { if cleanup_cx.kind == NON_SCOPE_BLOCK {
assert (std::vec::len::<cleanup>(cleanup_cx.cleanups) == 0u); assert (vec::len::<cleanup>(cleanup_cx.cleanups) == 0u);
} }
let i = std::vec::len::<cleanup>(cleanup_cx.cleanups), bcx = bcx; let i = vec::len::<cleanup>(cleanup_cx.cleanups), bcx = bcx;
while i > 0u { while i > 0u {
i -= 1u; i -= 1u;
let c = cleanup_cx.cleanups[i]; let c = cleanup_cx.cleanups[i];
@ -4913,7 +4915,7 @@ fn populate_fn_ctxt_from_llself(fcx: @fn_ctxt, llself: val_self_pair) {
// its magic. // its magic.
let fields_tup_ty = ty::mk_tup(fcx.lcx.ccx.tcx, field_tys); let fields_tup_ty = ty::mk_tup(fcx.lcx.ccx.tcx, field_tys);
let n_typarams = std::vec::len::<ast::ty_param>(bcx.fcx.lcx.obj_typarams); let n_typarams = vec::len::<ast::ty_param>(bcx.fcx.lcx.obj_typarams);
let llobj_box_ty: TypeRef = T_obj_ptr(ccx, n_typarams); let llobj_box_ty: TypeRef = T_obj_ptr(ccx, n_typarams);
let box_cell = GEPi(bcx, llself.v, [0, abi::obj_field_box]); let box_cell = GEPi(bcx, llself.v, [0, abi::obj_field_box]);
let box_ptr = Load(bcx, box_cell); let box_ptr = Load(bcx, box_cell);
@ -5073,7 +5075,7 @@ fn trans_tag_variant(cx: @local_ctxt, tag_id: ast::node_id,
ty_params: [ast::ty_param]) { ty_params: [ast::ty_param]) {
let ccx = cx.ccx; let ccx = cx.ccx;
if std::vec::len::<ast::variant_arg>(variant.node.args) == 0u { if vec::len::<ast::variant_arg>(variant.node.args) == 0u {
ret; // nullary constructors are just constants ret; // nullary constructors are just constants
} }
@ -5474,7 +5476,7 @@ fn trans_item(cx: @local_ctxt, item: ast::item) {
} }
ast::item_tag(variants, tps) { ast::item_tag(variants, tps) {
let sub_cx = extend_path(cx, item.ident); let sub_cx = extend_path(cx, item.ident);
let degen = std::vec::len(variants) == 1u; let degen = vec::len(variants) == 1u;
let i = 0; let i = 0;
for variant: ast::variant in variants { for variant: ast::variant in variants {
trans_tag_variant(sub_cx, item.id, variant, i, degen, tps); trans_tag_variant(sub_cx, item.id, variant, i, degen, tps);
@ -5522,7 +5524,7 @@ fn register_fn_full(ccx: @crate_ctxt, sp: span, path: [str], _flav: str,
: returns_non_ty_var(ccx, node_type) { : returns_non_ty_var(ccx, node_type) {
let path = path; let path = path;
let llfty = let llfty =
type_of_fn_from_ty(ccx, sp, node_type, std::vec::len(ty_params)); type_of_fn_from_ty(ccx, sp, node_type, vec::len(ty_params));
let ps: str = mangle_exported_name(ccx, path, node_type); let ps: str = mangle_exported_name(ccx, path, node_type);
let llfn: ValueRef = decl_cdecl_fn(ccx.llmod, ps, llfty); let llfn: ValueRef = decl_cdecl_fn(ccx.llmod, ps, llfty);
ccx.item_ids.insert(node_id, llfn); ccx.item_ids.insert(node_id, llfn);
@ -5543,7 +5545,7 @@ fn create_main_wrapper(ccx: @crate_ctxt, sp: span, main_llfn: ValueRef,
let main_takes_argv = let main_takes_argv =
alt ty::struct(ccx.tcx, main_node_type) { alt ty::struct(ccx.tcx, main_node_type) {
ty::ty_fn(_, args, _, _, _) { std::vec::len(args) != 0u } ty::ty_fn(_, args, _, _, _) { vec::len(args) != 0u }
}; };
let llfn = create_main(ccx, sp, main_llfn, main_takes_argv); let llfn = create_main(ccx, sp, main_llfn, main_takes_argv);
@ -5645,7 +5647,7 @@ fn native_fn_ty_param_count(cx: @crate_ctxt, id: ast::node_id) -> uint {
actually a fn"); actually a fn");
} }
ast::native_item_fn(_, tps) { ast::native_item_fn(_, tps) {
count = std::vec::len::<ast::ty_param>(tps); count = vec::len::<ast::ty_param>(tps);
} }
} }
ret count; ret count;
@ -5812,7 +5814,7 @@ fn collect_tag_ctor(ccx: @crate_ctxt, i: @ast::item, &&pt: [str],
alt i.node { alt i.node {
ast::item_tag(variants, tps) { ast::item_tag(variants, tps) {
for variant: ast::variant in variants { for variant: ast::variant in variants {
if std::vec::len(variant.node.args) != 0u { if vec::len(variant.node.args) != 0u {
register_fn(ccx, i.span, new_pt + [variant.node.name], register_fn(ccx, i.span, new_pt + [variant.node.name],
"tag", tps, variant.node.id); "tag", tps, variant.node.id);
} }
@ -5838,7 +5840,7 @@ fn trans_constant(ccx: @crate_ctxt, it: @ast::item, &&pt: [str],
alt it.node { alt it.node {
ast::item_tag(variants, _) { ast::item_tag(variants, _) {
let i = 0u; let i = 0u;
let n_variants = std::vec::len::<ast::variant>(variants); let n_variants = vec::len::<ast::variant>(variants);
while i < n_variants { while i < n_variants {
let variant = variants[i]; let variant = variants[i];
let p = new_pt + [it.ident, variant.node.name, "discrim"]; let p = new_pt + [it.ident, variant.node.name, "discrim"];

View file

@ -1,4 +1,4 @@
import std::{str, vec, option}; import core::{str, vec, option};
import option::{some, none}; import option::{some, none};
import lib::llvm::llvm; import lib::llvm::llvm;

View file

@ -1,5 +1,5 @@
import std::{vec, str}; import core::{vec, str};
import std::str::sbuf; import str::sbuf;
import lib::llvm::llvm; import lib::llvm::llvm;
import syntax::codemap::span; import syntax::codemap::span;
import llvm::{ValueRef, TypeRef, BasicBlockRef, BuilderRef, Opcode, import llvm::{ValueRef, TypeRef, BasicBlockRef, BuilderRef, Opcode,
@ -84,7 +84,7 @@ fn IndirectBr(cx: @block_ctxt, Addr: ValueRef, NumDests: uint) {
// lot more efficient) than doing str::as_buf("", ...) every time. // lot more efficient) than doing str::as_buf("", ...) every time.
fn noname() -> sbuf unsafe { fn noname() -> sbuf unsafe {
const cnull: uint = 0u; const cnull: uint = 0u;
ret std::unsafe::reinterpret_cast(std::ptr::addr_of(cnull)); ret unsafe::reinterpret_cast(ptr::addr_of(cnull));
} }
fn Invoke(cx: @block_ctxt, Fn: ValueRef, Args: [ValueRef], fn Invoke(cx: @block_ctxt, Fn: ValueRef, Args: [ValueRef],
@ -491,8 +491,8 @@ fn Phi(cx: @block_ctxt, Ty: TypeRef, vals: [ValueRef], bbs: [BasicBlockRef])
fn AddIncomingToPhi(phi: ValueRef, val: ValueRef, bb: BasicBlockRef) { fn AddIncomingToPhi(phi: ValueRef, val: ValueRef, bb: BasicBlockRef) {
if llvm::LLVMIsUndef(phi) == lib::llvm::True { ret; } if llvm::LLVMIsUndef(phi) == lib::llvm::True { ret; }
unsafe { unsafe {
let valptr = std::unsafe::reinterpret_cast(std::ptr::addr_of(val)); let valptr = unsafe::reinterpret_cast(ptr::addr_of(val));
let bbptr = std::unsafe::reinterpret_cast(std::ptr::addr_of(bb)); let bbptr = unsafe::reinterpret_cast(ptr::addr_of(bb));
llvm::LLVMAddIncoming(phi, valptr, bbptr, 1u); llvm::LLVMAddIncoming(phi, valptr, bbptr, 1u);
} }
} }

View file

@ -3,10 +3,10 @@
*/ */
import std::{int, vec, str, uint, option, unsafe}; import core::{int, vec, str, uint, option, unsafe};
import std::vec::to_ptr; import vec::to_ptr;
import std::map::hashmap; import std::map::hashmap;
import std::option::some; import option::some;
import syntax::ast; import syntax::ast;
import driver::session; import driver::session;
import middle::ty; import middle::ty;
@ -301,9 +301,9 @@ fn revoke_clean(cx: @block_ctxt, val: ValueRef) {
if found == -1 { ret; } if found == -1 { ret; }
// We found the cleanup and remove it // We found the cleanup and remove it
sc_cx.cleanups = sc_cx.cleanups =
std::vec::slice(sc_cx.cleanups, 0u, found as uint) + vec::slice(sc_cx.cleanups, 0u, found as uint) +
std::vec::slice(sc_cx.cleanups, (found as uint) + 1u, vec::slice(sc_cx.cleanups, (found as uint) + 1u,
std::vec::len(sc_cx.cleanups)); vec::len(sc_cx.cleanups));
sc_cx.lpad_dirty = true; sc_cx.lpad_dirty = true;
ret; ret;
} }
@ -411,7 +411,7 @@ fn val_str(tn: type_names, v: ValueRef) -> str { ret ty_str(tn, val_ty(v)); }
fn struct_elt(llstructty: TypeRef, n: uint) -> TypeRef unsafe { fn struct_elt(llstructty: TypeRef, n: uint) -> TypeRef unsafe {
let elt_count = llvm::LLVMCountStructElementTypes(llstructty); let elt_count = llvm::LLVMCountStructElementTypes(llstructty);
assert (n < elt_count); assert (n < elt_count);
let elt_tys = std::vec::init_elt(T_nil(), elt_count); let elt_tys = vec::init_elt(T_nil(), elt_count);
llvm::LLVMGetStructElementTypes(llstructty, to_ptr(elt_tys)); llvm::LLVMGetStructElementTypes(llstructty, to_ptr(elt_tys));
ret llvm::LLVMGetElementType(elt_tys[n]); ret llvm::LLVMGetElementType(elt_tys[n]);
} }
@ -531,7 +531,7 @@ fn T_size_t(targ_cfg: @session::config) -> TypeRef {
fn T_fn(inputs: [TypeRef], output: TypeRef) -> TypeRef { fn T_fn(inputs: [TypeRef], output: TypeRef) -> TypeRef {
unsafe { unsafe {
ret llvm::LLVMFunctionType(output, to_ptr(inputs), ret llvm::LLVMFunctionType(output, to_ptr(inputs),
std::vec::len::<TypeRef>(inputs), False); vec::len::<TypeRef>(inputs), False);
} }
} }
@ -543,7 +543,7 @@ fn T_ptr(t: TypeRef) -> TypeRef { ret llvm::LLVMPointerType(t, 0u); }
fn T_struct(elts: [TypeRef]) -> TypeRef { fn T_struct(elts: [TypeRef]) -> TypeRef {
unsafe { unsafe {
ret llvm::LLVMStructType(to_ptr(elts), std::vec::len(elts), False); ret llvm::LLVMStructType(to_ptr(elts), vec::len(elts), False);
} }
} }
@ -553,7 +553,7 @@ fn T_named_struct(name: str) -> TypeRef {
} }
fn set_struct_body(t: TypeRef, elts: [TypeRef]) unsafe { fn set_struct_body(t: TypeRef, elts: [TypeRef]) unsafe {
llvm::LLVMStructSetBody(t, to_ptr(elts), std::vec::len(elts), False); llvm::LLVMStructSetBody(t, to_ptr(elts), vec::len(elts), False);
} }
fn T_empty_struct() -> TypeRef { ret T_struct([]); } fn T_empty_struct() -> TypeRef { ret T_struct([]); }
@ -595,7 +595,7 @@ fn T_tydesc_field(cx: @crate_ctxt, field: int) -> TypeRef unsafe {
// Bit of a kludge: pick the fn typeref out of the tydesc.. // Bit of a kludge: pick the fn typeref out of the tydesc..
let tydesc_elts: [TypeRef] = let tydesc_elts: [TypeRef] =
std::vec::init_elt::<TypeRef>(T_nil(), vec::init_elt::<TypeRef>(T_nil(),
abi::n_tydesc_fields as uint); abi::n_tydesc_fields as uint);
llvm::LLVMGetStructElementTypes(cx.tydesc_type, llvm::LLVMGetStructElementTypes(cx.tydesc_type,
to_ptr::<TypeRef>(tydesc_elts)); to_ptr::<TypeRef>(tydesc_elts));
@ -733,7 +733,7 @@ fn T_opaque_tag_ptr(cx: @crate_ctxt) -> TypeRef {
} }
fn T_captured_tydescs(cx: @crate_ctxt, n: uint) -> TypeRef { fn T_captured_tydescs(cx: @crate_ctxt, n: uint) -> TypeRef {
ret T_struct(std::vec::init_elt::<TypeRef>(T_ptr(cx.tydesc_type), n)); ret T_struct(vec::init_elt::<TypeRef>(T_ptr(cx.tydesc_type), n));
} }
fn T_obj_ptr(cx: @crate_ctxt, n_captured_tydescs: uint) -> TypeRef { fn T_obj_ptr(cx: @crate_ctxt, n_captured_tydescs: uint) -> TypeRef {
@ -823,23 +823,23 @@ fn C_zero_byte_arr(size: uint) -> ValueRef unsafe {
let i = 0u; let i = 0u;
let elts: [ValueRef] = []; let elts: [ValueRef] = [];
while i < size { elts += [C_u8(0u)]; i += 1u; } while i < size { elts += [C_u8(0u)]; i += 1u; }
ret llvm::LLVMConstArray(T_i8(), std::vec::to_ptr(elts), ret llvm::LLVMConstArray(T_i8(), vec::to_ptr(elts),
std::vec::len(elts)); vec::len(elts));
} }
fn C_struct(elts: [ValueRef]) -> ValueRef unsafe { fn C_struct(elts: [ValueRef]) -> ValueRef unsafe {
ret llvm::LLVMConstStruct(std::vec::to_ptr(elts), std::vec::len(elts), ret llvm::LLVMConstStruct(vec::to_ptr(elts), vec::len(elts),
False); False);
} }
fn C_named_struct(T: TypeRef, elts: [ValueRef]) -> ValueRef unsafe { fn C_named_struct(T: TypeRef, elts: [ValueRef]) -> ValueRef unsafe {
ret llvm::LLVMConstNamedStruct(T, std::vec::to_ptr(elts), ret llvm::LLVMConstNamedStruct(T, vec::to_ptr(elts),
std::vec::len(elts)); vec::len(elts));
} }
fn C_array(ty: TypeRef, elts: [ValueRef]) -> ValueRef unsafe { fn C_array(ty: TypeRef, elts: [ValueRef]) -> ValueRef unsafe {
ret llvm::LLVMConstArray(ty, std::vec::to_ptr(elts), ret llvm::LLVMConstArray(ty, vec::to_ptr(elts),
std::vec::len(elts)); vec::len(elts));
} }
fn C_bytes(bytes: [u8]) -> ValueRef unsafe { fn C_bytes(bytes: [u8]) -> ValueRef unsafe {

View file

@ -1,6 +1,6 @@
// Translation of object-related things to LLVM IR. // Translation of object-related things to LLVM IR.
import std::{str, option, vec}; import core::{str, option, vec};
import option::{none, some}; import option::{none, some};
import lib::llvm::{llvm, True}; import lib::llvm::{llvm, True};

View file

@ -1,5 +1,5 @@
import std::vec; import vec;
import std::option::none; import option::none;
import syntax::ast; import syntax::ast;
import lib::llvm::llvm::{ValueRef, TypeRef}; import lib::llvm::llvm::{ValueRef, TypeRef};
import back::abi; import back::abi;
@ -131,7 +131,7 @@ fn trans_vec(bcx: @block_ctxt, args: [@ast::expr], id: ast::node_id,
} }
fn trans_str(bcx: @block_ctxt, s: str, dest: dest) -> @block_ctxt { fn trans_str(bcx: @block_ctxt, s: str, dest: dest) -> @block_ctxt {
let veclen = std::str::byte_len(s) + 1u; // +1 for \0 let veclen = str::byte_len(s) + 1u; // +1 for \0
let {bcx: bcx, val: sptr, _} = let {bcx: bcx, val: sptr, _} =
alloc(bcx, ty::mk_str(bcx_tcx(bcx)), veclen); alloc(bcx, ty::mk_str(bcx_tcx(bcx)), veclen);

View file

@ -1,5 +1,5 @@
import std::{int, uint}; import core::{int, uint};
import syntax::ast::*; import syntax::ast::*;
import syntax::ast_util::pat_binding_ids; import syntax::ast_util::pat_binding_ids;
import syntax::visit; import syntax::visit;

View file

@ -1,5 +1,5 @@
import std::{vec, int, uint, option}; import core::{vec, int, uint, option};
import std::option::*; import option::*;
import syntax::ast::*; import syntax::ast::*;
import syntax::ast_util::*; import syntax::ast_util::*;
import syntax::codemap::span; import syntax::codemap::span;
@ -989,7 +989,7 @@ fn args_mention<T>(args: [@constr_arg_use], q: fn([T], node_id) -> bool,
fn use_var(fcx: fn_ctxt, v: node_id) { *fcx.enclosing.used_vars += [v]; } fn use_var(fcx: fn_ctxt, v: node_id) { *fcx.enclosing.used_vars += [v]; }
// FIXME: This should be a function in std::vec::. // FIXME: This should be a function in vec::.
fn vec_contains(v: @mutable [node_id], i: node_id) -> bool { fn vec_contains(v: @mutable [node_id], i: node_id) -> bool {
for d: node_id in *v { if d == i { ret true; } } for d: node_id in *v { if d == i { ret true; } }
ret false; ret false;

View file

@ -1,7 +1,7 @@
import syntax::ast::*; import syntax::ast::*;
import syntax::visit; import syntax::visit;
import std::vec; import vec;
import std::option::*; import option::*;
import aux::*; import aux::*;
import tstate::ann::{pre_and_post, precond, postcond, prestate, poststate, import tstate::ann::{pre_and_post, precond, postcond, prestate, poststate,
relax_prestate, relax_precond, relax_poststate, relax_prestate, relax_precond, relax_poststate,

View file

@ -9,7 +9,7 @@ import middle::ty::{type_is_nil, ret_ty_of_fn};
import tstate::ann::{ import tstate::ann::{
precond, prestate, precond, prestate,
implies, ann_precond, ann_prestate}; implies, ann_precond, ann_prestate};
import std::{option}; import option;
import aux::*; import aux::*;
import syntax::print::pprust::ty_to_str; import syntax::print::pprust::ty_to_str;
import bitvectors::*; import bitvectors::*;

View file

@ -1,7 +1,7 @@
import syntax::ast::*; import syntax::ast::*;
import syntax::ast_util::*; import syntax::ast_util::*;
import util::ppaux::fn_ident_to_string; import util::ppaux::fn_ident_to_string;
import std::option::*; import option::*;
import syntax::visit; import syntax::visit;
import aux::*; import aux::*;
import util::common::new_def_hash; import util::common::new_def_hash;
@ -60,7 +60,7 @@ fn find_locals(tcx: ty::ctxt, f: _fn, tps: [ty_param], sp: span, i: fn_ident,
fn add_constraint(tcx: ty::ctxt, c: sp_constr, next: uint, tbl: constr_map) -> fn add_constraint(tcx: ty::ctxt, c: sp_constr, next: uint, tbl: constr_map) ->
uint { uint {
log constraint_to_str(tcx, c) + " |-> " + std::uint::str(next); log constraint_to_str(tcx, c) + " |-> " + uint::str(next);
alt c.node { alt c.node {
ninit(id, i) { tbl.insert(local_def(id), cinit(next, c.span, i)); } ninit(id, i) { tbl.insert(local_def(id), cinit(next, c.span, i)); }
npred(p, d_id, args) { npred(p, d_id, args) {
@ -142,7 +142,7 @@ fn mk_fn_info(ccx: crate_ctxt, f: _fn, tp: [ty_param], f_sp: span,
i_diverge: ninit(diverges_id, diverges_name), i_diverge: ninit(diverges_id, diverges_name),
used_vars: v}; used_vars: v};
ccx.fm.insert(id, rslt); ccx.fm.insert(id, rslt);
log name + " has " + std::uint::str(num_constraints(rslt)) + log name + " has " + uint::str(num_constraints(rslt)) +
" constraints"; " constraints";
} }

View file

@ -1,6 +1,6 @@
import std::{vec, option}; import core::{vec, option};
import std::option::{none, some}; import option::{none, some};
import tstate::ann::*; import tstate::ann::*;
import aux::*; import aux::*;

View file

@ -1,5 +1,5 @@
import std::{vec, option}; import core::{vec, option};
import std::option::{none, some}; import option::{none, some};
import ann::*; import ann::*;
import aux::*; import aux::*;
import tritv::{tritv_clone, tritv_set, ttrue}; import tritv::{tritv_clone, tritv_set, ttrue};

View file

@ -1,13 +1,13 @@
import std::vec; import vec;
import std::str; import str;
import std::uint; import uint;
import std::ufind; import std::ufind;
import std::map; import std::map;
import std::map::hashmap; import std::map::hashmap;
import std::math; import std::math;
import std::option; import option;
import std::option::none; import option::none;
import std::option::some; import option::some;
import std::smallintmap; import std::smallintmap;
import driver::session; import driver::session;
import syntax::ast; import syntax::ast;
@ -1471,7 +1471,7 @@ fn node_id_to_ty_param_substs_opt_and_ty(cx: ctxt, id: ast::node_id) ->
alt smallintmap::find(*cx.node_types, id as uint) { alt smallintmap::find(*cx.node_types, id as uint) {
none. { none. {
cx.sess.bug("node_id_to_ty_param_substs_opt_and_ty() called on " + cx.sess.bug("node_id_to_ty_param_substs_opt_and_ty() called on " +
"an untyped node (" + std::int::to_str(id, 10u) + "an untyped node (" + int::to_str(id, 10u) +
")"); ")");
} }
some(tpot) { ret tpot; } some(tpot) { ret tpot; }
@ -2712,7 +2712,7 @@ fn tag_variants(cx: ctxt, id: ast::def_id) -> [variant_info] {
for variant: ast::variant in variants { for variant: ast::variant in variants {
let ctor_ty = node_id_to_monotype(cx, variant.node.id); let ctor_ty = node_id_to_monotype(cx, variant.node.id);
let arg_tys: [t] = []; let arg_tys: [t] = [];
if std::vec::len(variant.node.args) > 0u { if vec::len(variant.node.args) > 0u {
for a: arg in ty_fn_args(cx, ctor_ty) { for a: arg in ty_fn_args(cx, ctor_ty) {
arg_tys += [a.ty]; arg_tys += [a.ty];
} }

View file

@ -12,9 +12,10 @@ import middle::ty::{node_id_to_type, arg, bind_params_in_type, block_ty,
ty_param_substs_opt_and_ty, ty_param_kinds_and_ty}; ty_param_substs_opt_and_ty, ty_param_kinds_and_ty};
import util::ppaux::ty_to_str; import util::ppaux::ty_to_str;
import middle::ty::unify::{ures_ok, ures_err, fix_ok, fix_err}; import middle::ty::unify::{ures_ok, ures_err, fix_ok, fix_err};
import std::{int, vec, str, option, smallintmap}; import core::{int, vec, str, option};
import std::smallintmap;
import std::map::{hashmap, new_int_hash}; import std::map::{hashmap, new_int_hash};
import std::option::{none, some}; import option::{none, some};
import syntax::print::pprust::*; import syntax::print::pprust::*;
export check_crate; export check_crate;
@ -1256,8 +1257,8 @@ fn check_pat(fcx: @fn_ctxt, map: ast_util::pat_id_map, pat: @ast::pat,
let arg_types = let arg_types =
variant_arg_types(fcx.ccx, pat.span, v_def_ids.var, variant_arg_types(fcx.ccx, pat.span, v_def_ids.var,
expected_tps); expected_tps);
let subpats_len = std::vec::len::<@ast::pat>(subpats); let subpats_len = vec::len::<@ast::pat>(subpats);
if std::vec::len::<ty::t>(arg_types) > 0u { if vec::len::<ty::t>(arg_types) > 0u {
// N-ary variant. // N-ary variant.
let arg_len = vec::len::<ty::t>(arg_types); let arg_len = vec::len::<ty::t>(arg_types);
@ -2270,7 +2271,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
let f = bind filtering_fn(fcx.ccx, _, ao.methods); let f = bind filtering_fn(fcx.ccx, _, ao.methods);
inner_obj_methods = inner_obj_methods =
std::vec::filter_map::<ty::method, vec::filter_map::<ty::method,
ty::method>(f, inner_obj_methods); ty::method>(f, inner_obj_methods);
method_types += inner_obj_methods; method_types += inner_obj_methods;

View file

@ -1,6 +1,6 @@
// The Rust abstract syntax tree. // The Rust abstract syntax tree.
import std::option; import option;
import codemap::{span, filename}; import codemap::{span, filename};
type spanned<T> = {node: T, span: span}; type spanned<T> = {node: T, span: span};

View file

@ -1,4 +1,5 @@
import std::{str, option, int, map}; import core::{str, option, int};
import std::map;
import codemap::span; import codemap::span;
import ast::*; import ast::*;
@ -212,7 +213,7 @@ fn is_constraint_arg(e: @expr) -> bool {
} }
} }
fn eq_ty(&&a: @ty, &&b: @ty) -> bool { ret std::box::ptr_eq(a, b); } fn eq_ty(&&a: @ty, &&b: @ty) -> bool { ret box::ptr_eq(a, b); }
fn hash_ty(&&t: @ty) -> uint { fn hash_ty(&&t: @ty) -> uint {
let res = (t.span.lo << 16u) + t.span.hi; let res = (t.span.lo << 16u) + t.span.hi;
@ -333,7 +334,7 @@ fn lit_to_const(lit: @lit) -> const_val {
lit_str(s) { const_str(s) } lit_str(s) { const_str(s) }
lit_int(n, _) { const_int(n) } lit_int(n, _) { const_int(n) }
lit_uint(n, _) { const_uint(n) } lit_uint(n, _) { const_uint(n) }
lit_float(n, _) { const_float(std::float::from_str(n)) } lit_float(n, _) { const_float(float::from_str(n)) }
lit_nil. { const_int(0i64) } lit_nil. { const_int(0i64) }
lit_bool(b) { const_int(b as i64) } lit_bool(b) { const_int(b as i64) }
} }

View file

@ -1,5 +1,6 @@
import std::{vec, uint, str, term, io, option, result}; import core::{vec, uint, str, option, result};
import std::option::{some, none}; import std::{term, io};
import option::{some, none};
type filename = str; type filename = str;

View file

@ -1,4 +1,4 @@
import std::{vec, option}; import core::{vec, option};
import std::map::hashmap; import std::map::hashmap;
import driver::session::session; import driver::session::session;
import codemap::span; import codemap::span;

View file

@ -1,4 +1,4 @@
import std::option; import option;
import base::*; import base::*;
import syntax::ast; import syntax::ast;

View file

@ -4,7 +4,8 @@
* should all get sucked into either the compiler syntax extension plugin * should all get sucked into either the compiler syntax extension plugin
* interface. * interface.
*/ */
import std::{vec, option, generic_os}; import core::{vec, option};
import std::generic_os;
import base::*; import base::*;
export expand_syntax_ext; export expand_syntax_ext;

View file

@ -1,9 +1,9 @@
import driver::session; import driver::session;
import std::option::{none, some}; import option::{none, some};
import std::map::hashmap; import std::map::hashmap;
import std::{vec}; import vec;
import syntax::ast::{crate, expr_, expr_mac, mac_invoc}; import syntax::ast::{crate, expr_, expr_mac, mac_invoc};
import syntax::fold::*; import syntax::fold::*;

View file

@ -5,9 +5,9 @@
* should all get sucked into either the standard library extfmt module or the * should all get sucked into either the standard library extfmt module or the
* compiler syntax extension plugin interface. * compiler syntax extension plugin interface.
*/ */
import std::{vec, str, option}; import core::{vec, str, option};
import std::option::{some}; import option::{some};
import std::extfmt::ct::*; import extfmt::ct::*;
import base::*; import base::*;
import codemap::span; import codemap::span;
export expand_syntax_ext; export expand_syntax_ext;
@ -257,7 +257,7 @@ fn pieces_to_expr(cx: ext_ctxt, sp: span, pieces: [piece], args: [@ast::expr])
} }
fn log_conv(c: conv) { fn log_conv(c: conv) {
alt c.param { alt c.param {
some(p) { log "param: " + std::int::to_str(p, 10u); } some(p) { log "param: " + int::to_str(p, 10u); }
_ { log "param: none"; } _ { log "param: none"; }
} }
for f: flag in c.flags { for f: flag in c.flags {
@ -270,17 +270,17 @@ fn pieces_to_expr(cx: ext_ctxt, sp: span, pieces: [piece], args: [@ast::expr])
} }
} }
alt c.width { alt c.width {
count_is(i) { log "width: count is " + std::int::to_str(i, 10u); } count_is(i) { log "width: count is " + int::to_str(i, 10u); }
count_is_param(i) { count_is_param(i) {
log "width: count is param " + std::int::to_str(i, 10u); log "width: count is param " + int::to_str(i, 10u);
} }
count_is_next_param. { log "width: count is next param"; } count_is_next_param. { log "width: count is next param"; }
count_implied. { log "width: count is implied"; } count_implied. { log "width: count is implied"; }
} }
alt c.precision { alt c.precision {
count_is(i) { log "prec: count is " + std::int::to_str(i, 10u); } count_is(i) { log "prec: count is " + int::to_str(i, 10u); }
count_is_param(i) { count_is_param(i) {
log "prec: count is param " + std::int::to_str(i, 10u); log "prec: count is param " + int::to_str(i, 10u);
} }
count_is_next_param. { log "prec: count is next param"; } count_is_next_param. { log "prec: count is next param"; }
count_implied. { log "prec: count is implied"; } count_implied. { log "prec: count is implied"; }

View file

@ -1,4 +1,4 @@
import std::{vec, option}; import core::{vec, option};
import base::*; import base::*;
import syntax::ast; import syntax::ast;

View file

@ -1,4 +1,4 @@
import std::{option}; import option;
import base::*; import base::*;
import syntax::ast; import syntax::ast;

View file

@ -1,7 +1,7 @@
use std; use std;
import codemap::span; import codemap::span;
import std::{vec, option}; import core::{vec, option};
import std::map::{hashmap, new_str_hash}; import std::map::{hashmap, new_str_hash};
import option::{some, none}; import option::{some, none};

View file

@ -1,7 +1,7 @@
import syntax::codemap::span; import syntax::codemap::span;
import ast::*; import ast::*;
import std::{vec, option}; import core::{vec, option};
export ast_fold_precursor; export ast_fold_precursor;
export ast_fold; export ast_fold;

View file

@ -1,7 +1,8 @@
import front::attr; import front::attr;
import std::{option, result, io, fs}; import core::{option, result};
import std::option::{some, none}; import std::{io, fs};
import option::{some, none};
import syntax::ast; import syntax::ast;
import syntax::parse::token; import syntax::parse::token;
import syntax::parse::parser::{parser, new_parser_from_file, import syntax::parse::parser::{parser, new_parser_from_file,

View file

@ -1,6 +1,7 @@
import std::{io, vec, str, option, either}; import core::{vec, str, option, either};
import std::option::{some, none}; import std::io;
import option::{some, none};
import util::interner; import util::interner;
import util::interner::intern; import util::interner::intern;
import codemap; import codemap;
@ -180,7 +181,7 @@ fn scan_digits(rdr: reader, radix: uint) -> str {
while true { while true {
let c = rdr.curr(); let c = rdr.curr();
if c == '_' { rdr.bump(); cont; } if c == '_' { rdr.bump(); cont; }
alt std::char::maybe_digit(c) { alt char::maybe_digit(c) {
some(d) when (d as uint) < radix { some(d) when (d as uint) < radix {
str::push_byte(rslt, c as u8); str::push_byte(rslt, c as u8);
rdr.bump(); rdr.bump();
@ -232,7 +233,7 @@ fn scan_number(c: char, rdr: reader) -> token::token {
tp = signed ? either::left(ast::ty_i64) tp = signed ? either::left(ast::ty_i64)
: either::right(ast::ty_u64); : either::right(ast::ty_u64);
} }
let parsed = std::u64::from_str(num_str, base as u64); let parsed = u64::from_str(num_str, base as u64);
alt tp { alt tp {
either::left(t) { ret token::LIT_INT(parsed as i64, t); } either::left(t) { ret token::LIT_INT(parsed as i64, t); }
either::right(t) { ret token::LIT_UINT(parsed, t); } either::right(t) { ret token::LIT_UINT(parsed, t); }
@ -276,7 +277,7 @@ fn scan_number(c: char, rdr: reader) -> token::token {
ret token::LIT_FLOAT(interner::intern(*rdr.get_interner(), num_str), ret token::LIT_FLOAT(interner::intern(*rdr.get_interner(), num_str),
ast::ty_f); ast::ty_f);
} else { } else {
let parsed = std::u64::from_str(num_str, base as u64); let parsed = u64::from_str(num_str, base as u64);
ret token::LIT_INT(parsed as i64, ast::ty_i); ret token::LIT_INT(parsed as i64, ast::ty_i);
} }
} }

View file

@ -1,7 +1,8 @@
import std::{io, vec, str, option, either, result, fs}; import core::{vec, str, option, either, result};
import std::option::{some, none}; import std::{io, fs};
import std::either::{left, right}; import option::{some, none};
import either::{left, right};
import std::map::{hashmap, new_str_hash}; import std::map::{hashmap, new_str_hash};
import token::can_begin_expr; import token::can_begin_expr;
import codemap::span; import codemap::span;

View file

@ -1,6 +1,6 @@
import util::interner; import util::interner;
import std::{int, uint, str}; import core::{int, uint, str};
type str_num = uint; type str_num = uint;

View file

@ -1,5 +1,6 @@
import std::{io, vec, str}; import core::{vec, str};
import std::io;
/* /*
* This pretty-printer is a direct reimplementation of Philip Karlton's * This pretty-printer is a direct reimplementation of Philip Karlton's

View file

@ -1,5 +1,6 @@
import std::{vec, int, io, str, uint, option}; import core::{vec, int, str, uint, option};
import std::io;
import parse::lexer; import parse::lexer;
import syntax::codemap::codemap; import syntax::codemap::codemap;
import ast; import ast;

View file

@ -1,9 +1,10 @@
// An "interner" is a data structure that associates values with uint tags and // An "interner" is a data structure that associates values with uint tags and
// allows bidirectional lookup; i.e. given a value, one can easily find the // allows bidirectional lookup; i.e. given a value, one can easily find the
// type, and vice versa. // type, and vice versa.
import std::{vec, map}; import core::vec;
import std::map;
import std::map::{hashmap, hashfn, eqfn}; import std::map::{hashmap, hashfn, eqfn};
import std::option::{none, some}; import option::{none, some};
type interner<T> = type interner<T> =
{map: hashmap<T, uint>, {map: hashmap<T, uint>,

View file

@ -1,7 +1,7 @@
import ast::*; import ast::*;
import std::option; import option;
import std::option::{none, some}; import option::{none, some};
import codemap::span; import codemap::span;

View file

@ -1,7 +1,7 @@
import std::{str, option}; import core::{str, option};
import std::math::{max, min}; import std::math::{max, min};
import std::map::hashmap; import std::map::hashmap;
import std::option::{some}; import option::{some};
import syntax::ast; import syntax::ast;
import ast::{ty, pat}; import ast::{ty, pat};
import syntax::codemap::{span}; import syntax::codemap::{span};
@ -82,7 +82,7 @@ fn local_rhs_span(l: @ast::local, def: span) -> span {
} }
fn is_main_name(path: [ast::ident]) -> bool { fn is_main_name(path: [ast::ident]) -> bool {
str::eq(option::get(std::vec::last(path)), "main") str::eq(option::get(vec::last(path)), "main")
} }

View file

@ -2,9 +2,9 @@
// FIXME: I'm not happy how this module turned out. Should probably // FIXME: I'm not happy how this module turned out. Should probably
// just be folded into cstore. // just be folded into cstore.
import std::option; import core::option;
import std::fs; import std::fs;
import std::vec; import vec;
import std::os; import std::os;
export filesearch; export filesearch;

View file

@ -1,5 +1,5 @@
import std::{vec, str, int, option}; import core::{vec, str, int, option};
import std::option::{none, some}; import option::{none, some};
import middle::ty; import middle::ty;
import middle::ty::*; import middle::ty::*;
import metadata::encoder; import metadata::encoder;

View file

@ -1,4 +1,4 @@
import std::option; import option;
tag mode { mode_compile_fail; mode_run_fail; mode_run_pass; mode_pretty; } tag mode { mode_compile_fail; mode_run_fail; mode_run_pass; mode_pretty; }

View file

@ -1,18 +1,18 @@
// FIXME: The way this module sets up tests is a relic and more convoluted // FIXME: The way this module sets up tests is a relic and more convoluted
// than it needs to be // than it needs to be
import std::option; import option;
import std::getopts; import std::getopts;
import std::test; import std::test;
import std::fs; import std::fs;
import std::str; import str;
import std::vec; import vec;
import std::task; import task;
import std::comm::port; import comm::port;
import std::comm::chan; import comm::chan;
import std::comm::send; import comm::send;
import std::comm::recv; import comm::recv;
import common::cx; import common::cx;
import common::config; import common::config;

View file

@ -1,5 +1,5 @@
import std::option; import option;
import std::str; import str;
import std::io; import std::io;
import std::fs; import std::fs;
@ -63,7 +63,7 @@ fn is_test_ignored(config: config, testfile: str) -> bool {
} }
fn iter_header(testfile: str, it: block(str)) { fn iter_header(testfile: str, it: block(str)) {
let rdr = std::result::get(io::file_reader(testfile)); let rdr = result::get(io::file_reader(testfile));
while !rdr.eof() { while !rdr.eof() {
let ln = rdr.read_line(); let ln = rdr.read_line();

View file

@ -4,20 +4,21 @@
// child process. Because of that we have to use a complicated scheme with a // child process. Because of that we have to use a complicated scheme with a
// dedicated server for spawning processes. // dedicated server for spawning processes.
import std::option; import core::comm;
import std::task; import core::option;
import task;
import std::generic_os::setenv; import std::generic_os::setenv;
import std::generic_os::getenv; import std::generic_os::getenv;
import std::vec; import vec;
import std::os; import std::os;
import std::run; import std::run;
import std::io; import std::io;
import std::str; import str;
import std::comm::chan; import comm::chan;
import std::comm::port; import comm::port;
import std::comm::send; import comm::send;
import std::comm::recv; import comm::recv;
import std::ctypes::{pid_t, fd_t}; import ctypes::{pid_t, fd_t};
export handle; export handle;
export mk; export mk;

View file

@ -1,10 +1,10 @@
import std::io; import std::io;
import std::str; import str;
import std::option; import option;
import std::fs; import std::fs;
import std::os; import std::os;
import std::vec; import vec;
import std::result; import result;
import common::mode_run_pass; import common::mode_run_pass;
import common::mode_run_fail; import common::mode_run_fail;

View file

@ -1,4 +1,4 @@
import std::option; import option;
import std::generic_os::getenv; import std::generic_os::getenv;
import std::io; import std::io;

View file

@ -1,5 +1,5 @@
use std; use std;
import std::vec; import vec;
fn vec_equal<T>(v: [T], u: [T], element_equality_test: fn(T, T) -> bool) -> fn vec_equal<T>(v: [T], u: [T], element_equality_test: fn(T, T) -> bool) ->
bool { bool {

View file

@ -1,7 +1,7 @@
use std; use std;
import std::vec; import vec;
import std::rand; import std::rand;
import std::option; import option;
// random uint less than n // random uint less than n
fn under(r : rand::rng, n : uint) -> uint { assert n != 0u; r.next() as uint % n } fn under(r : rand::rng, n : uint) -> uint { assert n != 0u; r.next() as uint % n }

View file

@ -1,4 +1,5 @@
import std::{fs, io, math, vec, str, int, uint, option, result}; import core::{vec, str, int, uint, option, result};
import std::{fs, io, math};
import rustc::syntax::{ast, ast_util, fold, visit, codemap}; import rustc::syntax::{ast, ast_util, fold, visit, codemap};
import rustc::syntax::parse::parser; import rustc::syntax::parse::parser;

View file

@ -17,10 +17,10 @@ vec_edits is not an iter because iters might go away.
*/ */
use std; use std;
import std::vec; import vec;
import std::vec::slice; import vec::slice;
import std::vec::len; import vec::len;
import std::int; import int;
fn vec_omit<T>(v: [T], i: uint) -> [T] { fn vec_omit<T>(v: [T], i: uint) -> [T] {
slice(v, 0u, i) + slice(v, i + 1u, len(v)) slice(v, 0u, i) + slice(v, i + 1u, len(v))

View file

@ -1,6 +1,6 @@
use std; use std;
import std::rand; import std::rand;
import std::vec; import vec;
// random uint less than n // random uint less than n
fn under(r : rand::rng, n : uint) -> uint { assert n != 0u; r.next() as uint % n } fn under(r : rand::rng, n : uint) -> uint { assert n != 0u; r.next() as uint % n }

134
src/libcore/bool.rs Normal file
View file

@ -0,0 +1,134 @@
// -*- rust -*-
/*
Module: bool
Classic Boolean logic reified as ADT
*/
export t;
export not, and, or, xor, implies;
export eq, ne, is_true, is_false;
export from_str, to_str, all_values, to_bit;
/*
Type: t
The type of boolean logic values
*/
type t = bool;
/* Function: not
Negation/Inverse
*/
pure fn not(v: t) -> t { !v }
/* Function: and
Conjunction
*/
pure fn and(a: t, b: t) -> t { a && b }
/* Function: or
Disjunction
*/
pure fn or(a: t, b: t) -> t { a || b }
/*
Function: xor
Exclusive or, i.e. `or(and(a, not(b)), and(not(a), b))`
*/
pure fn xor(a: t, b: t) -> t { (a && !b) || (!a && b) }
/*
Function: implies
Implication in the logic, i.e. from `a` follows `b`
*/
pure fn implies(a: t, b: t) -> t { !a || b }
/*
Predicate: eq
Returns:
true if truth values `a` and `b` are indistinguishable in the logic
*/
pure fn eq(a: t, b: t) -> bool { a == b }
/*
Predicate: ne
Returns:
true if truth values `a` and `b` are distinguishable in the logic
*/
pure fn ne(a: t, b: t) -> bool { a != b }
/*
Predicate: is_true
Returns:
true if `v` represents truth in the logic
*/
pure fn is_true(v: t) -> bool { v }
/*
Predicate: is_false
Returns:
true if `v` represents falsehood in the logic
*/
pure fn is_false(v: t) -> bool { !v }
/*
Function: from_str
Parse logic value from `s`
*/
pure fn from_str(s: str) -> t {
alt s {
"true" { true }
"false" { false }
}
}
/*
Function: to_str
Convert `v` into a string
*/
pure fn to_str(v: t) -> str { if v { "true" } else { "false" } }
/*
Function: all_values
Iterates over all truth values by passing them to `blk`
in an unspecified order
*/
fn all_values(blk: block(v: t)) {
blk(true);
blk(false);
}
/*
Function: to_bit
Returns:
An u8 whose first bit is set if `if_true(v)` holds
*/
fn to_bit(v: t) -> u8 { if v { 1u8 } else { 0u8 } }
// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:

20
src/libcore/box.rs Normal file
View file

@ -0,0 +1,20 @@
/*
Module: box
*/
export ptr_eq;
/*
Function: ptr_eq
Determine if two shared boxes point to the same object
*/
fn ptr_eq<T>(a: @T, b: @T) -> bool {
// FIXME: ptr::addr_of
unsafe {
let a_ptr: uint = unsafe::reinterpret_cast(a);
let b_ptr: uint = unsafe::reinterpret_cast(b);
ret a_ptr == b_ptr;
}
}

150
src/libcore/char.rs Normal file
View file

@ -0,0 +1,150 @@
/*
Module: char
Utilities for manipulating the char type
*/
/*
Function: is_whitespace
Indicates whether a character is whitespace.
Whitespace characters include space (U+0020), tab (U+0009), line feed
(U+000A), carriage return (U+000D), and a number of less common
ASCII and unicode characters.
*/
pure fn is_whitespace(c: char) -> bool {
const ch_space: char = '\u0020';
const ch_ogham_space_mark: char = '\u1680';
const ch_mongolian_vowel_sep: char = '\u180e';
const ch_en_quad: char = '\u2000';
const ch_em_quad: char = '\u2001';
const ch_en_space: char = '\u2002';
const ch_em_space: char = '\u2003';
const ch_three_per_em_space: char = '\u2004';
const ch_four_per_em_space: char = '\u2005';
const ch_six_per_em_space: char = '\u2006';
const ch_figure_space: char = '\u2007';
const ch_punctuation_space: char = '\u2008';
const ch_thin_space: char = '\u2009';
const ch_hair_space: char = '\u200a';
const ch_narrow_no_break_space: char = '\u202f';
const ch_medium_mathematical_space: char = '\u205f';
const ch_ideographic_space: char = '\u3000';
const ch_line_separator: char = '\u2028';
const ch_paragraph_separator: char = '\u2029';
const ch_character_tabulation: char = '\u0009';
const ch_line_feed: char = '\u000a';
const ch_line_tabulation: char = '\u000b';
const ch_form_feed: char = '\u000c';
const ch_carriage_return: char = '\u000d';
const ch_next_line: char = '\u0085';
const ch_no_break_space: char = '\u00a0';
if c == ch_space {
true
} else if c == ch_ogham_space_mark {
true
} else if c == ch_mongolian_vowel_sep {
true
} else if c == ch_en_quad {
true
} else if c == ch_em_quad {
true
} else if c == ch_en_space {
true
} else if c == ch_em_space {
true
} else if c == ch_three_per_em_space {
true
} else if c == ch_four_per_em_space {
true
} else if c == ch_six_per_em_space {
true
} else if c == ch_figure_space {
true
} else if c == ch_punctuation_space {
true
} else if c == ch_thin_space {
true
} else if c == ch_hair_space {
true
} else if c == ch_narrow_no_break_space {
true
} else if c == ch_medium_mathematical_space {
true
} else if c == ch_ideographic_space {
true
} else if c == ch_line_tabulation {
true
} else if c == ch_paragraph_separator {
true
} else if c == ch_character_tabulation {
true
} else if c == ch_line_feed {
true
} else if c == ch_line_tabulation {
true
} else if c == ch_form_feed {
true
} else if c == ch_carriage_return {
true
} else if c == ch_next_line {
true
} else if c == ch_no_break_space { true } else { false }
}
/*
Function: to_digit
Convert a char to the corresponding digit.
Parameters:
c - a char, either '0' to '9', 'a' to 'z' or 'A' to 'Z'
Returns:
If `c` is between '0' and '9', the corresponding value between 0 and 9.
If `c` is 'a' or 'A', 10. If `c` is 'b' or 'B', 11, etc.
Safety note:
This function fails if `c` is not a valid char
*/
pure fn to_digit(c: char) -> u8 unsafe {
alt maybe_digit(c) {
option::some(x) { x }
option::none. { fail; }
}
}
/*
Function: to_digit
Convert a char to the corresponding digit. Returns none when the
character is not a valid hexadecimal digit.
*/
fn maybe_digit(c: char) -> option::t<u8> {
alt c {
'0' to '9' { option::some(c as u8 - ('0' as u8)) }
'a' to 'z' { option::some(c as u8 + 10u8 - ('a' as u8)) }
'A' to 'Z' { option::some(c as u8 + 10u8 - ('A' as u8)) }
_ { option::none }
}
}
/*
Function: cmp
Compare two chars.
Parameters:
a - a char
b - a char
Returns:
-1 if a<b, 0 if a==b, +1 if a>b
*/
fn cmp(a: char, b: char) -> int {
ret if b > a { -1 }
else if b < a { 1 }
else { 0 }
}

184
src/libcore/comm.rs Normal file
View file

@ -0,0 +1,184 @@
/*
Module: comm
Communication between tasks
Communication between tasks is facilitated by ports (in the receiving task),
and channels (in the sending task). Any number of channels may feed into a
single port.
Ports and channels may only transmit values of unique types; that is,
values that are statically guaranteed to be accessed by a single
'owner' at a time. Unique types include scalars, vectors, strings,
and records, tags, tuples and unique boxes (~T) thereof. Most notably,
shared boxes (@T) may not be transmitted across channels.
Example:
> use std::{task, comm, io};
>
> let p = comm::port();
> task::spawn(comm::chan(p), fn (c: chan<str>) {
> comm::send(c, "Hello, World");
> });
>
> io::println(comm::recv(p));
*/
import sys;
import task;
export send;
export recv;
export chan;
export port;
#[abi = "cdecl"]
native mod rustrt {
type void;
type rust_port;
fn chan_id_send<send T>(t: *sys::type_desc,
target_task: task::task, target_port: port_id,
data: T) -> ctypes::uintptr_t;
fn new_port(unit_sz: uint) -> *rust_port;
fn del_port(po: *rust_port);
fn rust_port_detach(po: *rust_port);
fn get_port_id(po: *rust_port) -> port_id;
fn rust_port_size(po: *rust_port) -> ctypes::size_t;
fn port_recv(dptr: *uint, po: *rust_port,
yield: *ctypes::uintptr_t,
killed: *ctypes::uintptr_t);
}
#[abi = "rust-intrinsic"]
native mod rusti {
fn call_with_retptr<send T>(&&f: fn@(*uint)) -> T;
}
type port_id = int;
// It's critical that this only have one variant, so it has a record
// layout, and will work in the rust_task structure in task.rs.
/*
Type: chan
A communication endpoint that can send messages. Channels send
messages to ports.
Each channel is bound to a port when the channel is constructed, so
the destination port for a channel must exist before the channel
itself.
Channels are weak: a channel does not keep the port it is bound to alive.
If a channel attempts to send data to a dead port that data will be silently
dropped.
Channels may be duplicated and themselves transmitted over other channels.
*/
tag chan<send T> {
chan_t(task::task, port_id);
}
resource port_ptr<send T>(po: *rustrt::rust_port) {
// Once the port is detached it's guaranteed not to receive further
// messages
rustrt::rust_port_detach(po);
// Drain the port so that all the still-enqueued items get dropped
while rustrt::rust_port_size(po) > 0u {
// FIXME: For some reason if we don't assign to something here
// we end up with invalid reads in the drop glue.
let _t = recv_::<T>(po);
}
rustrt::del_port(po);
}
/*
Type: port
A communication endpoint that can receive messages. Ports receive
messages from channels.
Each port has a unique per-task identity and may not be replicated or
transmitted. If a port value is copied, both copies refer to the same port.
Ports may be associated with multiple <chan>s.
*/
tag port<send T> { port_t(@port_ptr<T>); }
/*
Function: send
Sends data over a channel.
The sent data is moved into the channel, whereupon the caller loses access
to it.
*/
fn send<send T>(ch: chan<T>, -data: T) {
let chan_t(t, p) = ch;
let res = rustrt::chan_id_send(sys::get_type_desc::<T>(), t, p, data);
if res != 0u unsafe {
// Data sent successfully
unsafe::leak(data);
}
task::yield();
}
/*
Function: port
Constructs a port.
*/
fn port<send T>() -> port<T> {
port_t(@port_ptr(rustrt::new_port(sys::size_of::<T>())))
}
/*
Function: recv
Receive from a port.
If no data is available on the port then the task will block until data
becomes available.
*/
fn recv<send T>(p: port<T>) -> T { recv_(***p) }
// Receive on a raw port pointer
fn recv_<send T>(p: *rustrt::rust_port) -> T {
// FIXME: Due to issue 1185 we can't use a return pointer when
// calling C code, and since we can't create our own return
// pointer on the stack, we're going to call a little intrinsic
// that will grab the value of the return pointer, then call this
// function, which we will then use to call the runtime.
fn recv(dptr: *uint, port: *rustrt::rust_port,
yield: *ctypes::uintptr_t,
killed: *ctypes::uintptr_t) unsafe {
rustrt::port_recv(dptr, port, yield, killed);
}
let yield = 0u;
let yieldp = ptr::addr_of(yield);
let killed = 0u;
let killedp = ptr::addr_of(killed);
let res = rusti::call_with_retptr(bind recv(_, p, yieldp, killedp));
if killed != 0u {
fail "killed";
}
if yield != 0u {
// Data isn't available yet, so res has not been initialized.
task::yield();
}
ret res;
}
/*
Function: chan
Constructs a channel.
The channel is bound to the port used to construct it.
*/
fn chan<send T>(p: port<T>) -> chan<T> {
chan_t(task::get_task(), rustrt::get_port_id(***p))
}

View file

@ -7,6 +7,47 @@
#[license = "BSD"]; #[license = "BSD"];
#[crate_type = "lib"]; #[crate_type = "lib"];
export box, char, float, int, str, ptr, uint, u8, u32, u64, vec, bool;
export either, option, result;
export ctypes, sys, unsafe, comm, task;
export extfmt;
// Built-in-type support modules
mod box;
mod char;
mod float;
mod int;
mod str;
mod ptr;
mod uint;
mod u8;
mod u32;
mod u64;
mod vec;
mod bool;
// Ubiquitous-utility-type modules
mod either;
mod option;
mod result;
// Runtime and language-primitive support
mod ctypes;
mod sys;
mod unsafe;
mod comm;
mod task;
// Compiler support modules
mod extfmt;
// Local Variables: // Local Variables:
// mode: rust; // mode: rust;
// fill-column: 78; // fill-column: 78;

146
src/libcore/ctypes.rs Normal file
View file

@ -0,0 +1,146 @@
/*
Module: ctypes
Definitions useful for C interop
*/
/*
FIXME: Add a test that uses some native code to verify these sizes,
which are not obviously correct for all potential platforms.
*/
/*
Type: c_int
A signed integer with the same size as a C `int`
*/
type c_int = i32;
/*
Type: c_uint
An unsigned integer with the same size as a C `unsigned int`
*/
type c_uint = u32;
/*
Type: long
A signed integer with the same size as a C `long`
*/
type long = int;
/*
Type: unsigned
An unsigned integer with the same size as a C `unsigned int`
*/
type unsigned = u32;
/*
Type: ulong
An unsigned integer with the same size as a C `unsigned long`
*/
type ulong = uint;
/*
Type: intptr_t
A signed integer with the same size as a pointer. This is
guaranteed to always be the same type as a Rust `int`
*/
type intptr_t = uint; // FIXME: int
/*
Type: uintptr_t
An unsigned integer with the same size as a pointer. This is
guaranteed to always be the same type as a Rust `uint`.
*/
type uintptr_t = uint;
type uint32_t = u32;
/*
Type: void
A type, a pointer to which can be used as C `void *`
Note that this does not directly correspond to the C `void` type,
which is an incomplete type. Using pointers to this type
when interoperating with C void pointers can help in documentation.
*/
type void = int;
// machine type equivalents of rust int, uint, float
/*
Type: m_int
FIXME: What C type does this represent?
*/
#[cfg(target_arch="x86")]
type m_int = i32;
#[cfg(target_arch="x86_64")]
type m_int = i64;
/*
Type: m_uint
FIXME: What C type does this represent?
*/
#[cfg(target_arch="x86")]
type m_uint = u32;
#[cfg(target_arch="x86_64")]
type m_uint = u64;
// This *must* match with "import m_float = fXX" in std::math per arch
/*
Type: m_float
FIXME: What C type does this represent?
*/
type m_float = f64;
/*
Type: size_t
An unsigned integer corresponding to the C `size_t`
*/
type size_t = uint;
/*
Type: ssize_t
A signed integer correpsonding to the C `ssize_t`
*/
type ssize_t = int;
/*
Type: off_t
An unsigned integer corresponding to the C `off_t`
*/
type off_t = uint;
/*
Type: fd_t
A type that can be used for C file descriptors
*/
type fd_t = i32; // not actually a C type, but should be.
/*
Type: pid_t
A type for representing process ID's, corresponding to C `pid_t`
*/
type pid_t = i32;
// enum is implementation-defined, but is 32-bits in practice
/*
Type: enum
An unsigned integer with the same size as a C enum
*/
type enum = u32;

89
src/libcore/either.rs Normal file
View file

@ -0,0 +1,89 @@
/*
Module: either
A type that represents one of two alternatives
*/
/*
Tag: t
The either type
*/
tag t<T, U> {
/* Variant: left */
left(T);
/* Variant: right */
right(U);
}
/* Section: Operations */
/*
Function: either
Applies a function based on the given either value
If `value` is left(T) then `f_left` is applied to its contents, if
`value` is right(U) then `f_right` is applied to its contents, and
the result is returned.
*/
fn either<T, U,
V>(f_left: block(T) -> V, f_right: block(U) -> V, value: t<T, U>) ->
V {
alt value { left(l) { f_left(l) } right(r) { f_right(r) } }
}
/*
Function: lefts
Extracts from a vector of either all the left values.
*/
fn lefts<copy T, U>(eithers: [t<T, U>]) -> [T] {
let result: [T] = [];
for elt: t<T, U> in eithers {
alt elt { left(l) { result += [l]; } _ {/* fallthrough */ } }
}
ret result;
}
/*
Function: rights
Extracts from a vector of either all the right values
*/
fn rights<T, copy U>(eithers: [t<T, U>]) -> [U] {
let result: [U] = [];
for elt: t<T, U> in eithers {
alt elt { right(r) { result += [r]; } _ {/* fallthrough */ } }
}
ret result;
}
/*
Function: partition
Extracts from a vector of either all the left values and right values
Returns a structure containing a vector of left values and a vector of
right values.
*/
fn partition<copy T, copy U>(eithers: [t<T, U>])
-> {lefts: [T], rights: [U]} {
let lefts: [T] = [];
let rights: [U] = [];
for elt: t<T, U> in eithers {
alt elt { left(l) { lefts += [l]; } right(r) { rights += [r]; } }
}
ret {lefts: lefts, rights: rights};
}
//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
//

453
src/libcore/extfmt.rs Normal file
View file

@ -0,0 +1,453 @@
/*
Syntax Extension: fmt
Format a string
The 'fmt' extension is modeled on the posix printf system.
A posix conversion ostensibly looks like this
> %[parameter][flags][width][.precision][length]type
Given the different numeric type bestiary we have, we omit the 'length'
parameter and support slightly different conversions for 'type'
> %[parameter][flags][width][.precision]type
we also only support translating-to-rust a tiny subset of the possible
combinations at the moment.
Example:
log #fmt("hello, %s!", "world");
*/
import option::{some, none};
/*
* We have a 'ct' (compile-time) module that parses format strings into a
* sequence of conversions. From those conversions AST fragments are built
* that call into properly-typed functions in the 'rt' (run-time) module.
* Each of those run-time conversion functions accepts another conversion
* description that specifies how to format its output.
*
* The building of the AST is currently done in a module inside the compiler,
* but should migrate over here as the plugin interface is defined.
*/
// Functions used by the fmt extension at compile time
mod ct {
tag signedness { signed; unsigned; }
tag caseness { case_upper; case_lower; }
tag ty {
ty_bool;
ty_str;
ty_char;
ty_int(signedness);
ty_bits;
ty_hex(caseness);
ty_octal;
ty_float;
// FIXME: More types
}
tag flag {
flag_left_justify;
flag_left_zero_pad;
flag_space_for_sign;
flag_sign_always;
flag_alternate;
}
tag count {
count_is(int);
count_is_param(int);
count_is_next_param;
count_implied;
}
// A formatted conversion from an expression to a string
type conv =
{param: option::t<int>,
flags: [flag],
width: count,
precision: count,
ty: ty};
// A fragment of the output sequence
tag piece { piece_string(str); piece_conv(conv); }
type error_fn = fn@(str) -> ! ;
fn parse_fmt_string(s: str, error: error_fn) -> [piece] {
let pieces: [piece] = [];
let lim = str::byte_len(s);
let buf = "";
fn flush_buf(buf: str, &pieces: [piece]) -> str {
if str::byte_len(buf) > 0u {
let piece = piece_string(buf);
pieces += [piece];
}
ret "";
}
let i = 0u;
while i < lim {
let curr = str::substr(s, i, 1u);
if str::eq(curr, "%") {
i += 1u;
if i >= lim {
error("unterminated conversion at end of string");
}
let curr2 = str::substr(s, i, 1u);
if str::eq(curr2, "%") {
i += 1u;
} else {
buf = flush_buf(buf, pieces);
let rs = parse_conversion(s, i, lim, error);
pieces += [rs.piece];
i = rs.next;
}
} else { buf += curr; i += 1u; }
}
buf = flush_buf(buf, pieces);
ret pieces;
}
fn peek_num(s: str, i: uint, lim: uint) ->
option::t<{num: uint, next: uint}> {
if i >= lim { ret none; }
let c = s[i];
if !('0' as u8 <= c && c <= '9' as u8) { ret option::none; }
let n = c - ('0' as u8) as uint;
ret alt peek_num(s, i + 1u, lim) {
none. { some({num: n, next: i + 1u}) }
some(next) {
let m = next.num;
let j = next.next;
some({num: n * 10u + m, next: j})
}
};
}
fn parse_conversion(s: str, i: uint, lim: uint, error: error_fn) ->
{piece: piece, next: uint} {
let parm = parse_parameter(s, i, lim);
let flags = parse_flags(s, parm.next, lim);
let width = parse_count(s, flags.next, lim);
let prec = parse_precision(s, width.next, lim);
let ty = parse_type(s, prec.next, lim, error);
ret {piece:
piece_conv({param: parm.param,
flags: flags.flags,
width: width.count,
precision: prec.count,
ty: ty.ty}),
next: ty.next};
}
fn parse_parameter(s: str, i: uint, lim: uint) ->
{param: option::t<int>, next: uint} {
if i >= lim { ret {param: none, next: i}; }
let num = peek_num(s, i, lim);
ret alt num {
none. { {param: none, next: i} }
some(t) {
let n = t.num;
let j = t.next;
if j < lim && s[j] == '$' as u8 {
{param: some(n as int), next: j + 1u}
} else { {param: none, next: i} }
}
};
}
fn parse_flags(s: str, i: uint, lim: uint) ->
{flags: [flag], next: uint} {
let noflags: [flag] = [];
if i >= lim { ret {flags: noflags, next: i}; }
// FIXME: This recursion generates illegal instructions if the return
// value isn't boxed. Only started happening after the ivec conversion
fn more_(f: flag, s: str, i: uint, lim: uint) ->
@{flags: [flag], next: uint} {
let next = parse_flags(s, i + 1u, lim);
let rest = next.flags;
let j = next.next;
let curr: [flag] = [f];
ret @{flags: curr + rest, next: j};
}
let more = bind more_(_, s, i, lim);
let f = s[i];
ret if f == '-' as u8 {
*more(flag_left_justify)
} else if f == '0' as u8 {
*more(flag_left_zero_pad)
} else if f == ' ' as u8 {
*more(flag_space_for_sign)
} else if f == '+' as u8 {
*more(flag_sign_always)
} else if f == '#' as u8 {
*more(flag_alternate)
} else { {flags: noflags, next: i} };
}
fn parse_count(s: str, i: uint, lim: uint) -> {count: count, next: uint} {
ret if i >= lim {
{count: count_implied, next: i}
} else if s[i] == '*' as u8 {
let param = parse_parameter(s, i + 1u, lim);
let j = param.next;
alt param.param {
none. { {count: count_is_next_param, next: j} }
some(n) { {count: count_is_param(n), next: j} }
}
} else {
let num = peek_num(s, i, lim);
alt num {
none. { {count: count_implied, next: i} }
some(num) {
{count: count_is(num.num as int), next: num.next}
}
}
};
}
fn parse_precision(s: str, i: uint, lim: uint) ->
{count: count, next: uint} {
ret if i >= lim {
{count: count_implied, next: i}
} else if s[i] == '.' as u8 {
let count = parse_count(s, i + 1u, lim);
// If there were no digits specified, i.e. the precision
// was ".", then the precision is 0
alt count.count {
count_implied. { {count: count_is(0), next: count.next} }
_ { count }
}
} else { {count: count_implied, next: i} };
}
fn parse_type(s: str, i: uint, lim: uint, error: error_fn) ->
{ty: ty, next: uint} {
if i >= lim { error("missing type in conversion"); }
let tstr = str::substr(s, i, 1u);
// TODO: Do we really want two signed types here?
// How important is it to be printf compatible?
let t =
if str::eq(tstr, "b") {
ty_bool
} else if str::eq(tstr, "s") {
ty_str
} else if str::eq(tstr, "c") {
ty_char
} else if str::eq(tstr, "d") || str::eq(tstr, "i") {
ty_int(signed)
} else if str::eq(tstr, "u") {
ty_int(unsigned)
} else if str::eq(tstr, "x") {
ty_hex(case_lower)
} else if str::eq(tstr, "X") {
ty_hex(case_upper)
} else if str::eq(tstr, "t") {
ty_bits
} else if str::eq(tstr, "o") {
ty_octal
} else if str::eq(tstr, "f") {
ty_float
} else { error("unknown type in conversion: " + tstr) };
ret {ty: t, next: i + 1u};
}
}
// Functions used by the fmt extension at runtime. For now there are a lot of
// decisions made a runtime. If it proves worthwhile then some of these
// conditions can be evaluated at compile-time. For now though it's cleaner to
// implement it this way, I think.
mod rt {
tag flag {
flag_left_justify;
flag_left_zero_pad;
flag_space_for_sign;
flag_sign_always;
flag_alternate;
// FIXME: This is a hack to avoid creating 0-length vec exprs,
// which have some difficulty typechecking currently. See
// comments in front::extfmt::make_flags
flag_none;
}
tag count { count_is(int); count_implied; }
tag ty { ty_default; ty_bits; ty_hex_upper; ty_hex_lower; ty_octal; }
// FIXME: May not want to use a vector here for flags;
// instead just use a bool per flag
type conv = {flags: [flag], width: count, precision: count, ty: ty};
fn conv_int(cv: conv, i: int) -> str {
let radix = 10u;
let prec = get_int_precision(cv);
let s = int_to_str_prec(i, radix, prec);
if 0 <= i {
if have_flag(cv.flags, flag_sign_always) {
s = "+" + s;
} else if have_flag(cv.flags, flag_space_for_sign) {
s = " " + s;
}
}
ret pad(cv, s, pad_signed);
}
fn conv_uint(cv: conv, u: uint) -> str {
let prec = get_int_precision(cv);
let rs =
alt cv.ty {
ty_default. { uint_to_str_prec(u, 10u, prec) }
ty_hex_lower. { uint_to_str_prec(u, 16u, prec) }
ty_hex_upper. { str::to_upper(uint_to_str_prec(u, 16u, prec)) }
ty_bits. { uint_to_str_prec(u, 2u, prec) }
ty_octal. { uint_to_str_prec(u, 8u, prec) }
};
ret pad(cv, rs, pad_unsigned);
}
fn conv_bool(cv: conv, b: bool) -> str {
let s = if b { "true" } else { "false" };
// run the boolean conversion through the string conversion logic,
// giving it the same rules for precision, etc.
ret conv_str(cv, s);
}
fn conv_char(cv: conv, c: char) -> str {
ret pad(cv, str::from_char(c), pad_nozero);
}
fn conv_str(cv: conv, s: str) -> str {
// For strings, precision is the maximum characters
// displayed
// FIXME: substr works on bytes, not chars!
let unpadded =
alt cv.precision {
count_implied. { s }
count_is(max) {
if max as uint < str::char_len(s) {
str::substr(s, 0u, max as uint)
} else { s }
}
};
ret pad(cv, unpadded, pad_nozero);
}
fn conv_float(cv: conv, f: float) -> str {
let (to_str, digits) = alt cv.precision {
count_is(c) { (float::to_str_exact, c as uint) }
count_implied. { (float::to_str, 6u) }
};
let s = to_str(f, digits);
if 0.0 <= f {
if have_flag(cv.flags, flag_sign_always) {
s = "+" + s;
} else if have_flag(cv.flags, flag_space_for_sign) {
s = " " + s;
}
}
ret pad(cv, s, pad_signed);
}
// Convert an int to string with minimum number of digits. If precision is
// 0 and num is 0 then the result is the empty string.
fn int_to_str_prec(num: int, radix: uint, prec: uint) -> str {
ret if num < 0 {
"-" + uint_to_str_prec(-num as uint, radix, prec)
} else { uint_to_str_prec(num as uint, radix, prec) };
}
// Convert a uint to string with a minimum number of digits. If precision
// 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.
fn uint_to_str_prec(num: uint, radix: uint, prec: uint) -> str {
ret if prec == 0u && num == 0u {
""
} else {
let s = uint::to_str(num, radix);
let len = str::char_len(s);
if len < prec {
let diff = prec - len;
let pad = str_init_elt('0', diff);
pad + s
} else { s }
};
}
fn get_int_precision(cv: conv) -> uint {
ret alt cv.precision {
count_is(c) { c as uint }
count_implied. { 1u }
};
}
// FIXME: This might be useful in str: but needs to be utf8 safe first
fn str_init_elt(c: char, n_elts: uint) -> str {
let svec = vec::init_elt::<u8>(c as u8, n_elts);
ret str::unsafe_from_bytes(svec);
}
tag pad_mode { pad_signed; pad_unsigned; pad_nozero; }
fn pad(cv: conv, s: str, mode: pad_mode) -> str {
let uwidth;
alt cv.width {
count_implied. { ret s; }
count_is(width) {
// FIXME: Maybe width should be uint
uwidth = width as uint;
}
}
let strlen = str::char_len(s);
if uwidth <= strlen { ret s; }
let padchar = ' ';
let diff = uwidth - strlen;
if have_flag(cv.flags, flag_left_justify) {
let padstr = str_init_elt(padchar, diff);
ret s + padstr;
}
let might_zero_pad = false;
let signed = false;
alt mode {
pad_nozero. {
// fallthrough
}
pad_signed. { might_zero_pad = true; signed = true; }
pad_unsigned. { might_zero_pad = true; }
}
fn have_precision(cv: conv) -> bool {
ret alt cv.precision { count_implied. { false } _ { true } };
}
let zero_padding = false;
if might_zero_pad && have_flag(cv.flags, flag_left_zero_pad) &&
!have_precision(cv) {
padchar = '0';
zero_padding = true;
}
let padstr = str_init_elt(padchar, diff);
// This is completely heinous. If we have a signed value then
// potentially rip apart the intermediate result and insert some
// zeros. It may make sense to convert zero padding to a precision
// instead.
if signed && zero_padding && str::byte_len(s) > 0u {
let head = s[0];
if head == '+' as u8 || head == '-' as u8 || head == ' ' as u8 {
let headstr = str::unsafe_from_bytes([head]);
let bytelen = str::byte_len(s);
let numpart = str::substr(s, 1u, bytelen - 1u);
ret headstr + padstr + numpart;
}
}
ret padstr + s;
}
fn have_flag(flags: [flag], f: flag) -> bool {
for candidate: flag in flags { if candidate == f { ret true; } }
ret false;
}
}
// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:

343
src/libcore/float.rs Normal file
View file

@ -0,0 +1,343 @@
/*
Module: float
*/
/**
* Section: String Conversions
*/
/*
Function: to_str_common
Converts a float to a string
Parameters:
num - The float value
digits - The number of significant digits
exact - Whether to enforce the exact number of significant digits
*/
fn to_str_common(num: float, digits: uint, exact: bool) -> str {
let (num, accum) = num < 0.0 ? (-num, "-") : (num, "");
let trunc = num as uint;
let frac = num - (trunc as float);
accum += uint::str(trunc);
if frac == 0.0 || digits == 0u { ret accum; }
accum += ".";
let i = digits;
let epsilon = 1. / pow_uint_to_uint_as_float(10u, i);
while i > 0u && (frac >= epsilon || exact) {
frac *= 10.0;
epsilon *= 10.0;
let digit = frac as uint;
accum += uint::str(digit);
frac -= digit as float;
i -= 1u;
}
ret accum;
}
/*
Function: to_str
Converts a float to a string with exactly the number of provided significant
digits
Parameters:
num - The float value
digits - The number of significant digits
*/
fn to_str_exact(num: float, digits: uint) -> str {
to_str_common(num, digits, true)
}
/*
Function: to_str
Converts a float to a string with a maximum number of significant digits
Parameters:
num - The float value
digits - The number of significant digits
*/
fn to_str(num: float, digits: uint) -> str {
to_str_common(num, digits, false)
}
/*
Function: from_str
Convert a string to a float
This function accepts strings such as
* "3.14"
* "+3.14", equivalent to "3.14"
* "-3.14"
* "2.5E10", or equivalently, "2.5e10"
* "2.5E-10"
* "", or, equivalently, "." (understood as 0)
* "5."
* ".5", or, equivalently, "0.5"
Leading and trailing whitespace are ignored.
Parameters:
num - A string, possibly empty.
Returns:
<NaN> If the string did not represent a valid number.
Otherwise, the floating-point number represented [num].
*/
fn from_str(num: str) -> float {
let num = str::trim(num);
let pos = 0u; //Current byte position in the string.
//Used to walk the string in O(n).
let len = str::byte_len(num); //Length of the string, in bytes.
if len == 0u { ret 0.; }
let total = 0f; //Accumulated result
let c = 'z'; //Latest char.
//The string must start with one of the following characters.
alt str::char_at(num, 0u) {
'-' | '+' | '0' to '9' | '.' {}
_ { ret NaN; }
}
//Determine if first char is '-'/'+'. Set [pos] and [neg] accordingly.
let neg = false; //Sign of the result
alt str::char_at(num, 0u) {
'-' {
neg = true;
pos = 1u;
}
'+' {
pos = 1u;
}
_ {}
}
//Examine the following chars until '.', 'e', 'E'
while(pos < len) {
let char_range = str::char_range_at(num, pos);
c = char_range.ch;
pos = char_range.next;
alt c {
'0' to '9' {
total = total * 10f;
total += ((c as int) - ('0' as int)) as float;
}
'.' | 'e' | 'E' {
break;
}
_ {
ret NaN;
}
}
}
if c == '.' {//Examine decimal part
let decimal = 1.f;
while(pos < len) {
let char_range = str::char_range_at(num, pos);
c = char_range.ch;
pos = char_range.next;
alt c {
'0' | '1' | '2' | '3' | '4' | '5' | '6'| '7' | '8' | '9' {
decimal /= 10.f;
total += (((c as int) - ('0' as int)) as float)*decimal;
}
'e' | 'E' {
break;
}
_ {
ret NaN;
}
}
}
}
if (c == 'e') | (c == 'E') {//Examine exponent
let exponent = 0u;
let neg_exponent = false;
if(pos < len) {
let char_range = str::char_range_at(num, pos);
c = char_range.ch;
alt c {
'+' {
pos = char_range.next;
}
'-' {
pos = char_range.next;
neg_exponent = true;
}
_ {}
}
while(pos < len) {
let char_range = str::char_range_at(num, pos);
c = char_range.ch;
alt c {
'0' | '1' | '2' | '3' | '4' | '5' | '6'| '7' | '8' | '9' {
exponent *= 10u;
exponent += ((c as uint) - ('0' as uint));
}
_ {
break;
}
}
pos = char_range.next;
}
let multiplier = pow_uint_to_uint_as_float(10u, exponent);
//Note: not [int::pow], otherwise, we'll quickly
//end up with a nice overflow
if neg_exponent {
total = total / multiplier;
} else {
total = total * multiplier;
}
} else {
ret NaN;
}
}
if(pos < len) {
ret NaN;
} else {
if(neg) {
total *= -1f;
}
ret total;
}
}
/**
* Section: Arithmetics
*/
/*
Function: pow_uint_to_uint_as_float
Compute the exponentiation of an integer by another integer as a float.
Parameters:
x - The base.
pow - The exponent.
Returns:
<NaN> of both `x` and `pow` are `0u`, otherwise `x^pow`.
*/
fn pow_uint_to_uint_as_float(x: uint, pow: uint) -> float {
if x == 0u {
if pow == 0u {
ret NaN;
}
ret 0.;
}
let my_pow = pow;
let total = 1f;
let multiplier = x as float;
while (my_pow > 0u) {
if my_pow % 2u == 1u {
total = total * multiplier;
}
my_pow /= 2u;
multiplier *= multiplier;
}
ret total;
}
/* Const: NaN */
const NaN: float = 0./0.;
/* Const: infinity */
const infinity: float = 1./0.;
/* Const: neg_infinity */
const neg_infinity: float = -1./0.;
/* Predicate: isNaN */
pure fn isNaN(f: float) -> bool { f != f }
/* Function: add */
pure fn add(x: float, y: float) -> float { ret x + y; }
/* Function: sub */
pure fn sub(x: float, y: float) -> float { ret x - y; }
/* Function: mul */
pure fn mul(x: float, y: float) -> float { ret x * y; }
/* Function: div */
pure fn div(x: float, y: float) -> float { ret x / y; }
/* Function: rem */
pure fn rem(x: float, y: float) -> float { ret x % y; }
/* Predicate: lt */
pure fn lt(x: float, y: float) -> bool { ret x < y; }
/* Predicate: le */
pure fn le(x: float, y: float) -> bool { ret x <= y; }
/* Predicate: eq */
pure fn eq(x: float, y: float) -> bool { ret x == y; }
/* Predicate: ne */
pure fn ne(x: float, y: float) -> bool { ret x != y; }
/* Predicate: ge */
pure fn ge(x: float, y: float) -> bool { ret x >= y; }
/* Predicate: gt */
pure fn gt(x: float, y: float) -> bool { ret x > y; }
/*
Predicate: positive
Returns true if `x` is a positive number, including +0.0 and +Infinity.
*/
pure fn positive(x: float) -> bool { ret x > 0. || (1./x) == infinity; }
/*
Predicate: negative
Returns true if `x` is a negative number, including -0.0 and -Infinity.
*/
pure fn negative(x: float) -> bool { ret x < 0. || (1./x) == neg_infinity; }
/*
Predicate: nonpositive
Returns true if `x` is a negative number, including -0.0 and -Infinity.
(This is the same as `float::negative`.)
*/
pure fn nonpositive(x: float) -> bool {
ret x < 0. || (1./x) == neg_infinity;
}
/*
Predicate: nonnegative
Returns true if `x` is a positive number, including +0.0 and +Infinity.
(This is the same as `float::positive`.)
*/
pure fn nonnegative(x: float) -> bool {
ret x > 0. || (1./x) == infinity;
}
//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
//

189
src/libcore/int.rs Normal file
View file

@ -0,0 +1,189 @@
/*
Module: int
*/
/*
Const: max_value
The maximum value of an integer
*/
// FIXME: Find another way to access the machine word size in a const expr
#[cfg(target_arch="x86")]
const max_value: int = (-1 << 31)-1;
#[cfg(target_arch="x86_64")]
const max_value: int = (-1 << 63)-1;
/*
Const: min_value
The minumum value of an integer
*/
#[cfg(target_arch="x86")]
const min_value: int = -1 << 31;
#[cfg(target_arch="x86_64")]
const min_value: int = -1 << 63;
/* Function: add */
pure fn add(x: int, y: int) -> int { ret x + y; }
/* Function: sub */
pure fn sub(x: int, y: int) -> int { ret x - y; }
/* Function: mul */
pure fn mul(x: int, y: int) -> int { ret x * y; }
/* Function: div */
pure fn div(x: int, y: int) -> int { ret x / y; }
/* Function: rem */
pure fn rem(x: int, y: int) -> int { ret x % y; }
/* Predicate: lt */
pure fn lt(x: int, y: int) -> bool { ret x < y; }
/* Predicate: le */
pure fn le(x: int, y: int) -> bool { ret x <= y; }
/* Predicate: eq */
pure fn eq(x: int, y: int) -> bool { ret x == y; }
/* Predicate: ne */
pure fn ne(x: int, y: int) -> bool { ret x != y; }
/* Predicate: ge */
pure fn ge(x: int, y: int) -> bool { ret x >= y; }
/* Predicate: gt */
pure fn gt(x: int, y: int) -> bool { ret x > y; }
/* Predicate: positive */
pure fn positive(x: int) -> bool { ret x > 0; }
/* Predicate: negative */
pure fn negative(x: int) -> bool { ret x < 0; }
/* Predicate: nonpositive */
pure fn nonpositive(x: int) -> bool { ret x <= 0; }
/* Predicate: nonnegative */
pure fn nonnegative(x: int) -> bool { ret x >= 0; }
// FIXME: Make sure this works with negative integers.
/*
Function: hash
Produce a uint suitable for use in a hash table
*/
fn hash(x: int) -> uint { ret x as uint; }
/*
Function: range
Iterate over the range [`lo`..`hi`)
*/
fn range(lo: int, hi: int, it: block(int)) {
let i = lo;
while i < hi { it(i); i += 1; }
}
/*
Function: parse_buf
Parse a buffer of bytes
Parameters:
buf - A byte buffer
radix - The base of the number
Failure:
buf must not be empty
*/
fn parse_buf(buf: [u8], radix: uint) -> int {
if vec::len::<u8>(buf) == 0u {
log_err "parse_buf(): buf is empty";
fail;
}
let i = vec::len::<u8>(buf) - 1u;
let start = 0u;
let power = 1;
if buf[0] == ('-' as u8) {
power = -1;
start = 1u;
}
let n = 0;
while true {
let digit = char::to_digit(buf[i] as char);
if (digit as uint) >= radix {
fail;
}
n += (digit as int) * power;
power *= radix as int;
if i <= start { ret n; }
i -= 1u;
}
fail;
}
/*
Function: from_str
Parse a string to an int
Failure:
s must not be empty
*/
fn from_str(s: str) -> int { parse_buf(str::bytes(s), 10u) }
/*
Function: to_str
Convert to a string in a given base
*/
fn to_str(n: int, radix: uint) -> str {
assert (0u < radix && radix <= 16u);
ret if n < 0 {
"-" + uint::to_str(-n as uint, radix)
} else { uint::to_str(n as uint, radix) };
}
/*
Function: str
Convert to a string
*/
fn str(i: int) -> str { ret to_str(i, 10u); }
/*
Function: pow
Returns `base` raised to the power of `exponent`
*/
fn pow(base: int, exponent: uint) -> int {
if exponent == 0u { ret 1; } //Not mathemtically true if [base == 0]
if base == 0 { ret 0; }
let my_pow = exponent;
let acc = 1;
let multiplier = base;
while(my_pow > 0u) {
if my_pow % 2u == 1u {
acc *= multiplier;
}
my_pow /= 2u;
multiplier *= multiplier;
}
ret acc;
}
// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:

93
src/libcore/option.rs Normal file
View file

@ -0,0 +1,93 @@
/*
Module: option
Represents the presence or absence of a value.
Every option<T> value can either be some(T) or none. Where in other languages
you might use a nullable type, in Rust you would use an option type.
*/
/*
Tag: t
The option type
*/
tag t<T> {
/* Variant: none */
none;
/* Variant: some */
some(T);
}
/* Section: Operations */
/*
Function: get
Gets the value out of an option
Failure:
Fails if the value equals `none`.
*/
fn get<copy T>(opt: t<T>) -> T {
alt opt { some(x) { ret x; } none. { fail "option none"; } }
}
/*
*/
fn map<T, U>(f: block(T) -> U, opt: t<T>) -> t<U> {
alt opt { some(x) { some(f(x)) } none. { none } }
}
/*
Function: is_none
Returns true if the option equals none
*/
pure fn is_none<T>(opt: t<T>) -> bool {
alt opt { none. { true } some(_) { false } }
}
/*
Function: is_some
Returns true if the option contains some value
*/
pure fn is_some<T>(opt: t<T>) -> bool { !is_none(opt) }
/*
Function: from_maybe
Returns the contained value or a default
*/
fn from_maybe<T>(def: T, opt: t<T>) -> T {
alt opt { some(x) { x } none. { def } }
}
/*
Function: maybe
Applies a function to the contained value or returns a default
*/
fn maybe<T, U>(def: U, f: block(T) -> U, opt: t<T>) -> U {
alt opt { none. { def } some(t) { f(t) } }
}
// FIXME: Can be defined in terms of the above when/if we have const bind.
/*
Function: may
Performs an operation on the contained value or does nothing
*/
fn may<T>(f: block(T), opt: t<T>) {
alt opt { none. {/* nothing */ } some(t) { f(t); } }
}
// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:

52
src/libcore/ptr.rs Normal file
View file

@ -0,0 +1,52 @@
/*
Module: ptr
Unsafe pointer utility functions
*/
#[abi = "rust-intrinsic"]
native mod rusti {
fn addr_of<T>(val: T) -> *T;
fn ptr_offset<T>(ptr: *T, count: uint) -> *T;
}
/*
Function: addr_of
Get an unsafe pointer to a value
*/
fn addr_of<T>(val: T) -> *T { ret rusti::addr_of(val); }
/*
Function: mut_addr_of
Get an unsafe mutable pointer to a value
*/
fn mut_addr_of<T>(val: T) -> *mutable T unsafe {
ret unsafe::reinterpret_cast(rusti::addr_of(val));
}
/*
Function: offset
Calculate the offset from a pointer
*/
fn offset<T>(ptr: *T, count: uint) -> *T {
ret rusti::ptr_offset(ptr, count);
}
/*
Function: mut_offset
Calculate the offset from a mutable pointer
*/
fn mut_offset<T>(ptr: *mutable T, count: uint) -> *mutable T {
ret rusti::ptr_offset(ptr as *T, count) as *mutable T;
}
/*
Function: null
Create an unsafe null pointer
*/
fn null<T>() -> *T unsafe { ret unsafe::reinterpret_cast(0u); }

112
src/libcore/result.rs Normal file
View file

@ -0,0 +1,112 @@
/*
Module: result
A type representing either success or failure
*/
/* Section: Types */
/*
Tag: t
The result type
*/
tag t<T, U> {
/*
Variant: ok
Contains the result value
*/
ok(T);
/*
Variant: err
Contains the error value
*/
err(U);
}
/* Section: Operations */
/*
Function: get
Get the value out of a successful result
Failure:
If the result is an error
*/
fn get<T, U>(res: t<T, U>) -> T {
alt res {
ok(t) { t }
err(_) {
// FIXME: Serialize the error value
// and include it in the fail message
fail "get called on error result";
}
}
}
/*
Function: get_err
Get the value out of an error result
Failure:
If the result is not an error
*/
fn get_err<T, U>(res: t<T, U>) -> U {
alt res {
err(u) { u }
ok(_) {
fail "get_error called on ok result";
}
}
}
/*
Function: success
Returns true if the result is <ok>
*/
fn success<T, U>(res: t<T, U>) -> bool {
alt res {
ok(_) { true }
err(_) { false }
}
}
/*
Function: failure
Returns true if the result is <error>
*/
fn failure<T, U>(res: t<T, U>) -> bool {
!success(res)
}
/*
Function: chain
Call a function based on a previous result
If `res` is <ok> then the value is extracted and passed to `op` whereupon
`op`s result is returned. if `res` is <err> then it is immediately returned.
This function can be used to compose the results of two functions.
Example:
> let res = chain(read_file(file), { |buf|
> ok(parse_buf(buf))
> })
*/
fn chain<T, copy U, copy V>(res: t<T, V>, op: block(T) -> t<U, V>)
-> t<U, V> {
alt res {
ok(t) { op(t) }
err(e) { err(e) }
}
}

962
src/libcore/str.rs Normal file
View file

@ -0,0 +1,962 @@
/*
Module: str
String manipulation.
*/
export eq, lteq, hash, is_empty, is_not_empty, is_whitespace, byte_len,
byte_len_range, index,
rindex, find, starts_with, ends_with, substr, slice, split, concat,
connect, to_upper, replace, char_slice, trim_left, trim_right, trim,
unshift_char, shift_char, pop_char, push_char, is_utf8, from_chars,
to_chars, char_len, char_len_range, char_at, bytes, is_ascii,
shift_byte, pop_byte,
unsafe_from_byte, unsafe_from_bytes, from_char, char_range_at,
str_from_cstr, sbuf, as_buf, push_byte, utf8_char_width, safe_slice,
contains, iter_chars, loop_chars, loop_chars_sub,
escape;
#[abi = "cdecl"]
native mod rustrt {
fn rust_str_push(&s: str, ch: u8);
}
/*
Function: eq
Bytewise string equality
*/
fn eq(&&a: str, &&b: str) -> bool { a == b }
/*
Function: lteq
Bytewise less than or equal
*/
fn lteq(&&a: str, &&b: str) -> bool { a <= b }
/*
Function: hash
String hash function
*/
fn hash(&&s: str) -> uint {
// djb hash.
// FIXME: replace with murmur.
let u: uint = 5381u;
for c: u8 in s { u *= 33u; u += c as uint; }
ret u;
}
// UTF-8 tags and ranges
const tag_cont_u8: u8 = 128u8;
const tag_cont: uint = 128u;
const max_one_b: uint = 128u;
const tag_two_b: uint = 192u;
const max_two_b: uint = 2048u;
const tag_three_b: uint = 224u;
const max_three_b: uint = 65536u;
const tag_four_b: uint = 240u;
const max_four_b: uint = 2097152u;
const tag_five_b: uint = 248u;
const max_five_b: uint = 67108864u;
const tag_six_b: uint = 252u;
/*
Function: is_utf8
Determines if a vector uf bytes contains valid UTF-8
*/
fn is_utf8(v: [u8]) -> bool {
let i = 0u;
let total = vec::len::<u8>(v);
while i < total {
let 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] & 192u8 != tag_cont_u8 { ret false; }
i += 1u;
chsize -= 1u;
}
}
ret true;
}
/*
Function: is_ascii
Determines if a string contains only ASCII characters
*/
fn is_ascii(s: str) -> bool {
let i: uint = byte_len(s);
while i > 0u { i -= 1u; if s[i] & 128u8 != 0u8 { ret false; } }
ret true;
}
/*
Predicate: is_empty
Returns true if the string has length 0
*/
pure fn is_empty(s: str) -> bool { for c: u8 in s { ret false; } ret true; }
/*
Predicate: is_not_empty
Returns true if the string has length greater than 0
*/
pure fn is_not_empty(s: str) -> bool { !is_empty(s) }
/*
Function: is_whitespace
Returns true if the string contains only whitespace
*/
fn is_whitespace(s: str) -> bool {
let i = 0u;
let len = char_len(s);
while i < len {
// FIXME: This is not how char_at works
if !char::is_whitespace(char_at(s, i)) { ret false; }
i += 1u;
}
ret true;
}
/*
Function: byte_len
Returns the length in bytes of a string
*/
fn byte_len(s: str) -> uint unsafe {
let v: [u8] = unsafe::reinterpret_cast(s);
let vlen = vec::len(v);
unsafe::leak(v);
// There should always be a null terminator
assert (vlen > 0u);
ret vlen - 1u;
}
/*
Function: byte_len_range
As byte_len but for a substring
Parameters:
s - A string
byte_offset - The byte offset at which to start in the string
char_len - The number of chars (not bytes!) in the range
Returns:
The number of bytes in the substring starting at `byte_offset` and
containing `char_len` chars.
Safety note:
This function fails if `byte_offset` or `char_len` do not represent
valid positions in `s`
*/
fn byte_len_range(s: str, byte_offset: uint, char_len: uint) -> uint {
let i = byte_offset;
let chars = 0u;
while chars < char_len {
let chsize = utf8_char_width(s[i]);
assert (chsize > 0u);
i += chsize;
chars += 1u;
}
ret i - byte_offset;
}
/*
Function: bytes
Converts a string to a vector of bytes. The result vector is not
null-terminated.
*/
fn bytes(s: str) -> [u8] unsafe {
let v = unsafe::reinterpret_cast(s);
let vcopy = vec::slice(v, 0u, vec::len(v) - 1u);
unsafe::leak(v);
ret vcopy;
}
/*
Function: unsafe_from_bytes
Converts a vector of bytes to a string. Does not verify that the
vector contains valid UTF-8.
*/
fn unsafe_from_bytes(v: [const u8]) -> str unsafe {
let vcopy: [u8] = v + [0u8];
let scopy: str = unsafe::reinterpret_cast(vcopy);
unsafe::leak(vcopy);
ret scopy;
}
/*
Function: unsafe_from_byte
Converts a byte to a string. Does not verify that the byte is
valid UTF-8.
*/
fn unsafe_from_byte(u: u8) -> str { unsafe_from_bytes([u]) }
fn push_utf8_bytes(&s: str, ch: char) {
let code = ch as uint;
let bytes =
if code < max_one_b {
[code as u8]
} else if code < max_two_b {
[code >> 6u & 31u | tag_two_b as u8, code & 63u | tag_cont as u8]
} else if code < max_three_b {
[code >> 12u & 15u | tag_three_b as u8,
code >> 6u & 63u | tag_cont as u8, code & 63u | tag_cont as u8]
} else if code < max_four_b {
[code >> 18u & 7u | tag_four_b as u8,
code >> 12u & 63u | tag_cont as u8,
code >> 6u & 63u | tag_cont as u8, code & 63u | tag_cont as u8]
} else if code < max_five_b {
[code >> 24u & 3u | tag_five_b as u8,
code >> 18u & 63u | tag_cont as u8,
code >> 12u & 63u | tag_cont as u8,
code >> 6u & 63u | tag_cont as u8, code & 63u | tag_cont as u8]
} else {
[code >> 30u & 1u | tag_six_b as u8,
code >> 24u & 63u | tag_cont as u8,
code >> 18u & 63u | tag_cont as u8,
code >> 12u & 63u | tag_cont as u8,
code >> 6u & 63u | tag_cont as u8, code & 63u | tag_cont as u8]
};
push_bytes(s, bytes);
}
/*
Function: from_char
Convert a char to a string
*/
fn from_char(ch: char) -> str {
let buf = "";
push_utf8_bytes(buf, ch);
ret buf;
}
/*
Function: from_chars
Convert a vector of chars to a string
*/
fn from_chars(chs: [char]) -> str {
let buf = "";
for ch: char in chs { push_utf8_bytes(buf, ch); }
ret buf;
}
/*
Function: utf8_char_width
FIXME: What does this function do?
*/
fn utf8_char_width(b: u8) -> uint {
let byte: uint = b as uint;
if byte < 128u { ret 1u; }
if byte < 192u {
ret 0u; // Not a valid start byte
}
if byte < 224u { ret 2u; }
if byte < 240u { ret 3u; }
if byte < 248u { ret 4u; }
if byte < 252u { ret 5u; }
ret 6u;
}
/*
Function: char_range_at
Pluck a character out of a string and return the index of the next character.
This function can be used to iterate over the unicode characters of a string.
Example:
> let s = "Clam chowder, hot sauce, pork rinds";
> let i = 0;
> while i < len(s) {
> let {ch, next} = char_range_at(s, i);
> log ch;
> i = next;
> }
Parameters:
s - The string
i - The byte offset of the char to extract
Returns:
A record {ch: char, next: uint} containing the char value and the byte
index of the next unicode character.
Failure:
If `i` is greater than or equal to the length of the string.
If `i` is not the index of the beginning of a valid UTF-8 character.
*/
fn char_range_at(s: str, i: uint) -> {ch: char, next: uint} {
let b0 = s[i];
let w = utf8_char_width(b0);
assert (w != 0u);
if w == 1u { ret {ch: b0 as char, next: i + 1u}; }
let val = 0u;
let end = i + w;
let i = i + 1u;
while i < end {
let byte = s[i];
assert (byte & 192u8 == tag_cont_u8);
val <<= 6u;
val += byte & 63u8 as uint;
i += 1u;
}
// Clunky way to get the right bits from the first byte. Uses two shifts,
// the first to clip off the marker bits at the left of the byte, and then
// a second (as uint) to get it to the right position.
val += (b0 << (w + 1u as u8) as uint) << ((w - 1u) * 6u - w - 1u);
ret {ch: val as char, next: i};
}
/*
Function: char_at
Pluck a character out of a string
*/
fn char_at(s: str, i: uint) -> char { ret char_range_at(s, i).ch; }
/*
Function: iter_chars
Iterate over the characters in a string
*/
fn iter_chars(s: str, it: block(char)) {
let pos = 0u, len = byte_len(s);
while (pos < len) {
let {ch, next} = char_range_at(s, pos);
pos = next;
it(ch);
}
}
/*
Function: loop_chars
Loop through a string, char by char
Parameters:
s - A string to traverse. It may be empty.
it - A block to execute with each consecutive character of `s`.
Return `true` to continue, `false` to stop.
Returns:
`true` If execution proceeded correctly, `false` if it was interrupted,
that is if `it` returned `false` at any point.
*/
fn loop_chars(s: str, it: block(char) -> bool) -> bool{
ret loop_chars_sub(s, 0u, byte_len(s), it);
}
/*
Function: loop_chars_sub
Loop through a substring, char by char
Parameters:
s - A string to traverse. It may be empty.
byte_offset - The byte offset at which to start in the string.
byte_len - The number of bytes to traverse in the string
it - A block to execute with each consecutive character of `s`.
Return `true` to continue, `false` to stop.
Returns:
`true` If execution proceeded correctly, `false` if it was interrupted,
that is if `it` returned `false` at any point.
Safety note:
- This function does not check whether the substring is valid.
- This function fails if `byte_offset` or `byte_len` do not
represent valid positions inside `s`
*/
fn loop_chars_sub(s: str, byte_offset: uint, byte_len: uint,
it: block(char) -> bool) -> bool {
let i = byte_offset;
let result = true;
while i < byte_len {
let {ch, next} = char_range_at(s, i);
if !it(ch) {result = false; break;}
i = next;
}
ret result;
}
/*
Function: char_len
Count the number of unicode characters in a string
*/
fn char_len(s: str) -> uint {
ret char_len_range(s, 0u, byte_len(s));
}
/*
Function: char_len_range
As char_len but for a slice of a string
Parameters:
s - A valid string
byte_start - The position inside `s` where to start counting in bytes.
byte_len - The number of bytes of `s` to take into account.
Returns:
The number of Unicode characters in `s` in
segment [byte_start, byte_start+len( .
Safety note:
- This function does not check whether the substring is valid.
- This function fails if `byte_offset` or `byte_len` do not
represent valid positions inside `s`
*/
fn char_len_range(s: str, byte_start: uint, byte_len: uint) -> uint {
let i = byte_start;
let len = 0u;
while i < byte_len {
let chsize = utf8_char_width(s[i]);
assert (chsize > 0u);
len += 1u;
i += chsize;
}
assert (i == byte_len);
ret len;
}
/*
Function: to_chars
Convert a string to a vector of characters
*/
fn to_chars(s: str) -> [char] {
let buf: [char] = [];
let i = 0u;
let len = byte_len(s);
while i < len {
let cur = char_range_at(s, i);
buf += [cur.ch];
i = cur.next;
}
ret buf;
}
/*
Function: push_char
Append a character to a string
*/
fn push_char(&s: str, ch: char) { s += from_char(ch); }
/*
Function: pop_char
Remove the final character from a string and return it.
Failure:
If the string does not contain any characters.
*/
fn pop_char(&s: str) -> char {
let end = byte_len(s);
while end > 0u && s[end - 1u] & 192u8 == tag_cont_u8 { end -= 1u; }
assert (end > 0u);
let ch = char_at(s, end - 1u);
s = substr(s, 0u, end - 1u);
ret ch;
}
/*
Function: shift_char
Remove the first character from a string and return it.
Failure:
If the string does not contain any characters.
*/
fn shift_char(&s: str) -> char {
let r = char_range_at(s, 0u);
s = substr(s, r.next, byte_len(s) - r.next);
ret r.ch;
}
/*
Function: unshift_char
Prepend a char to a string
*/
fn unshift_char(&s: str, ch: char) { s = from_char(ch) + s; }
/*
Function: index
Returns the index of the first matching byte. Returns -1 if
no match is found.
*/
fn index(s: str, c: u8) -> int {
let i: int = 0;
for k: u8 in s { if k == c { ret i; } i += 1; }
ret -1;
}
/*
Function: rindex
Returns the index of the last matching byte. Returns -1
if no match is found.
*/
fn rindex(s: str, c: u8) -> int {
let n: int = byte_len(s) as int;
while n >= 0 { if s[n] == c { ret n; } n -= 1; }
ret n;
}
/*
Function: find
Finds the index of the first matching substring.
Returns -1 if `haystack` does not contain `needle`.
Parameters:
haystack - The string to look in
needle - The string to look for
Returns:
The index of the first occurance of `needle`, or -1 if not found.
*/
fn find(haystack: str, needle: str) -> int {
let haystack_len: int = byte_len(haystack) as int;
let needle_len: int = byte_len(needle) as int;
if needle_len == 0 { ret 0; }
fn match_at(haystack: str, needle: str, i: int) -> bool {
let j: int = i;
for c: u8 in needle { if haystack[j] != c { ret false; } j += 1; }
ret true;
}
let i: int = 0;
while i <= haystack_len - needle_len {
if match_at(haystack, needle, i) { ret i; }
i += 1;
}
ret -1;
}
/*
Function: contains
Returns true if one string contains another
Parameters:
haystack - The string to look in
needle - The string to look for
*/
fn contains(haystack: str, needle: str) -> bool {
0 <= find(haystack, needle)
}
/*
Function: starts_with
Returns true if one string starts with another
Parameters:
haystack - The string to look in
needle - The string to look for
*/
fn starts_with(haystack: str, needle: str) -> bool {
let haystack_len: uint = byte_len(haystack);
let needle_len: uint = byte_len(needle);
if needle_len == 0u { ret true; }
if needle_len > haystack_len { ret false; }
ret eq(substr(haystack, 0u, needle_len), needle);
}
/*
Function: ends_with
Returns true if one string ends with another
haystack - The string to look in
needle - The string to look for
*/
fn ends_with(haystack: str, needle: str) -> bool {
let haystack_len: uint = byte_len(haystack);
let needle_len: uint = byte_len(needle);
ret if needle_len == 0u {
true
} else if needle_len > haystack_len {
false
} else {
eq(substr(haystack, haystack_len - needle_len, needle_len),
needle)
};
}
/*
Function: substr
Take a substring of another. Returns a string containing `len` bytes
starting at byte offset `begin`.
This function is not unicode-safe.
Failure:
If `begin` + `len` is is greater than the byte length of the string
*/
fn substr(s: str, begin: uint, len: uint) -> str {
ret slice(s, begin, begin + len);
}
/*
Function: slice
Takes a bytewise slice from a string. Returns the substring from
[`begin`..`end`).
This function is not unicode-safe.
Failure:
- If begin is greater than end.
- If end is greater than the length of the string.
*/
fn slice(s: str, begin: uint, end: uint) -> str unsafe {
// FIXME: Typestate precondition
assert (begin <= end);
assert (end <= byte_len(s));
let v: [u8] = unsafe::reinterpret_cast(s);
let v2 = vec::slice(v, begin, end);
unsafe::leak(v);
v2 += [0u8];
let s2: str = unsafe::reinterpret_cast(v2);
unsafe::leak(v2);
ret s2;
}
/*
Function: safe_slice
*/
fn safe_slice(s: str, begin: uint, end: uint) : uint::le(begin, end) -> str {
// would need some magic to make this a precondition
assert (end <= byte_len(s));
ret slice(s, begin, end);
}
/*
Function: shift_byte
Removes the first byte from a string and returns it.
This function is not unicode-safe.
*/
fn shift_byte(&s: str) -> u8 {
let len = byte_len(s);
assert (len > 0u);
let b = s[0];
s = substr(s, 1u, len - 1u);
ret b;
}
/*
Function: pop_byte
Removes the last byte from a string and returns it.
This function is not unicode-safe.
*/
fn pop_byte(&s: str) -> u8 {
let len = byte_len(s);
assert (len > 0u);
let b = s[len - 1u];
s = substr(s, 0u, len - 1u);
ret b;
}
/*
Function: push_byte
Appends a byte to a string.
This function is not unicode-safe.
*/
fn push_byte(&s: str, b: u8) { rustrt::rust_str_push(s, b); }
/*
Function: push_bytes
Appends a vector of bytes to a string.
This function is not unicode-safe.
*/
fn push_bytes(&s: str, bytes: [u8]) {
for byte in bytes { rustrt::rust_str_push(s, byte); }
}
/*
Function: split
Split a string at each occurance of a given separator
Returns:
A vector containing all the strings between each occurance of the separator
*/
fn split(s: str, sep: u8) -> [str] {
let v: [str] = [];
let accum: str = "";
let ends_with_sep: bool = false;
for c: u8 in s {
if c == sep {
v += [accum];
accum = "";
ends_with_sep = true;
} else { accum += unsafe_from_byte(c); ends_with_sep = false; }
}
if byte_len(accum) != 0u || ends_with_sep { v += [accum]; }
ret v;
}
/*
Function: concat
Concatenate a vector of strings
*/
fn concat(v: [str]) -> str {
let s: str = "";
for ss: str in v { s += ss; }
ret s;
}
/*
Function: connect
Concatenate a vector of strings, placing a given separator between each
*/
fn connect(v: [str], sep: str) -> str {
let s: str = "";
let first: bool = true;
for ss: str in v {
if first { first = false; } else { s += sep; }
s += ss;
}
ret s;
}
// FIXME: This only handles ASCII
/*
Function: to_upper
Convert a string to uppercase
*/
fn to_upper(s: str) -> str {
let outstr = "";
let ascii_a = 'a' as u8;
let ascii_z = 'z' as u8;
let diff = 32u8;
for byte: u8 in s {
let next;
if ascii_a <= byte && byte <= ascii_z {
next = byte - diff;
} else { next = byte; }
push_byte(outstr, next);
}
ret outstr;
}
// FIXME: This is super-inefficient
/*
Function: replace
Replace all occurances of one string with another
Parameters:
s - The string containing substrings to replace
from - The string to replace
to - The replacement string
Returns:
The original string with all occurances of `from` replaced with `to`
*/
fn replace(s: str, from: str, to: str) : is_not_empty(from) -> str {
// FIXME (694): Shouldn't have to check this
check (is_not_empty(from));
if byte_len(s) == 0u {
ret "";
} else if starts_with(s, from) {
ret to + replace(slice(s, byte_len(from), byte_len(s)), from, to);
} else {
ret unsafe_from_byte(s[0]) +
replace(slice(s, 1u, byte_len(s)), from, to);
}
}
// FIXME: Also not efficient
/*
Function: char_slice
Unicode-safe slice. Returns a slice of the given string containing
the characters in the range [`begin`..`end`). `begin` and `end` are
character indexes, not byte indexes.
Failure:
- If begin is greater than end
- If end is greater than the character length of the string
*/
fn char_slice(s: str, begin: uint, end: uint) -> str {
from_chars(vec::slice(to_chars(s), begin, end))
}
/*
Function: trim_left
Returns a string with leading whitespace removed.
*/
fn trim_left(s: str) -> str {
fn count_whities(s: [char]) -> uint {
let i = 0u;
while i < vec::len(s) {
if !char::is_whitespace(s[i]) { break; }
i += 1u;
}
ret i;
}
let chars = to_chars(s);
let whities = count_whities(chars);
ret from_chars(vec::slice(chars, whities, vec::len(chars)));
}
/*
Function: trim_right
Returns a string with trailing whitespace removed.
*/
fn trim_right(s: str) -> str {
fn count_whities(s: [char]) -> uint {
let i = vec::len(s);
while 0u < i {
if !char::is_whitespace(s[i - 1u]) { break; }
i -= 1u;
}
ret i;
}
let chars = to_chars(s);
let whities = count_whities(chars);
ret from_chars(vec::slice(chars, 0u, whities));
}
/*
Function: trim
Returns a string with leading and trailing whitespace removed
*/
fn trim(s: str) -> str { trim_left(trim_right(s)) }
/*
Type: sbuf
An unsafe buffer of bytes. Corresponds to a C char pointer.
*/
type sbuf = *u8;
// NB: This is intentionally unexported because it's easy to misuse (there's
// no guarantee that the string is rooted). Instead, use as_buf below.
unsafe fn buf(s: str) -> sbuf {
let saddr = ptr::addr_of(s);
let vaddr: *[u8] = unsafe::reinterpret_cast(saddr);
let buf = vec::to_ptr(*vaddr);
ret buf;
}
/*
Function: as_buf
Work with the byte buffer of a string. Allows for unsafe manipulation
of strings, which is useful for native interop.
Example:
> let s = str::as_buf("PATH", { |path_buf| libc::getenv(path_buf) });
*/
fn as_buf<T>(s: str, f: block(sbuf) -> T) -> T unsafe {
let buf = buf(s); f(buf)
}
/*
Function: str_from_cstr
Create a Rust string from a null-terminated C string
*/
unsafe fn str_from_cstr(cstr: sbuf) -> str {
let res = "";
let start = cstr;
let curr = start;
let i = 0u;
while *curr != 0u8 {
push_byte(res, *curr);
i += 1u;
curr = ptr::offset(start, i);
}
ret res;
}
/*
Function: escape_char
Escapes a single character.
*/
fn escape_char(c: char) -> str {
alt c {
'"' { "\\\"" }
'\\' { "\\\\" }
'\n' { "\\n" }
'\t' { "\\t" }
'\r' { "\\r" }
// FIXME: uncomment this when extfmt is moved to core
// in a snapshot.
// '\x00' to '\x1f' { #fmt["\\x%02x", c as uint] }
v { from_char(c) }
}
}
/*
Function: escape
Escapes special characters inside the string, making it safe for transfer.
*/
fn escape(s: str) -> str {
let r = "";
loop_chars(s, { |c| r += escape_char(c); true });
r
}

96
src/libcore/sys.rs Normal file
View file

@ -0,0 +1,96 @@
/*
Module: sys
Misc low level stuff
*/
tag type_desc = {
first_param: **ctypes::c_int,
size: ctypes::size_t,
align: ctypes::size_t
// Remaining fields not listed
};
#[abi = "cdecl"]
native 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.
fn last_os_error() -> str;
fn refcount<T>(t: @T) -> uint;
fn do_gc();
fn unsupervise();
}
#[abi = "rust-intrinsic"]
native mod rusti {
fn get_type_desc<T>() -> *type_desc;
}
/*
Function: get_type_desc
Returns a pointer to a type descriptor. Useful for calling certain
function in the Rust runtime or otherwise performing dark magick.
*/
fn get_type_desc<T>() -> *type_desc {
ret rusti::get_type_desc::<T>();
}
/*
Function: last_os_error
Get a string representing the platform-dependent last error
*/
fn last_os_error() -> str {
ret rustrt::last_os_error();
}
/*
Function: size_of
Returns the size of a type
*/
fn size_of<T>() -> uint unsafe {
ret (*get_type_desc::<T>()).size;
}
/*
Function: align_of
Returns the alignment of a type
*/
fn align_of<T>() -> uint unsafe {
ret (*get_type_desc::<T>()).align;
}
/*
Function: refcount
Returns the refcount of a shared box
*/
fn refcount<T>(t: @T) -> uint {
ret rustrt::refcount::<T>(t);
}
/*
Function: do_gc
Force a garbage collection
*/
fn do_gc() -> () {
ret rustrt::do_gc();
}
// FIXME: There's a wrapper for this in the task module and this really
// just belongs there
fn unsupervise() -> () {
ret rustrt::unsupervise();
}
// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:

357
src/libcore/task.rs Normal file
View file

@ -0,0 +1,357 @@
/*
Module: task
Task management.
An executing Rust program consists of a tree of tasks, each with their own
stack, and sole ownership of their allocated heap data. Tasks communicate
with each other using ports and channels.
When a task fails, that failure will propagate to its parent (the task
that spawned it) and the parent will fail as well. The reverse is not
true: when a parent task fails its children will continue executing. When
the root (main) task fails, all tasks fail, and then so does the entire
process.
A task may remove itself from this failure propagation mechanism by
calling the <unsupervise> function, after which failure will only
result in the termination of that task.
Tasks may execute in parallel and are scheduled automatically by the runtime.
Example:
> spawn("Hello, World", fn (&&msg: str) {
> log msg;
> });
*/
import cast = unsafe::reinterpret_cast;
import comm;
import option::{some, none};
import option = option::t;
import ptr;
export task;
export joinable_task;
export sleep;
export yield;
export task_notification;
export join;
export unsupervise;
export pin;
export unpin;
export set_min_stack;
export task_result;
export tr_success;
export tr_failure;
export get_task;
export spawn;
export spawn_notify;
export spawn_joinable;
#[abi = "rust-intrinsic"]
native mod rusti {
// these must run on the Rust stack so that they can swap stacks etc:
fn task_sleep(task: *rust_task, time_in_us: uint, &killed: bool);
}
#[link_name = "rustrt"]
#[abi = "cdecl"]
native mod rustrt {
// these can run on the C stack:
fn pin_task();
fn unpin_task();
fn get_task_id() -> task_id;
fn rust_get_task() -> *rust_task;
fn set_min_stack(stack_size: uint);
fn new_task() -> task_id;
fn drop_task(task_id: *rust_task);
fn get_task_pointer(id: task_id) -> *rust_task;
fn migrate_alloc(alloc: *u8, target: task_id);
fn start_task(id: task, closure: *u8);
}
/* Section: Types */
type rust_task =
{id: task,
mutable notify_enabled: int,
mutable notify_chan: comm::chan<task_notification>,
mutable stack_ptr: *u8};
resource rust_task_ptr(task: *rust_task) { rustrt::drop_task(task); }
type task_id = int;
/*
Type: task
A handle to a task
*/
type task = task_id;
/*
Type: joinable_task
A task that sends notification upon termination
*/
type joinable_task = (task, comm::port<task_notification>);
/*
Tag: task_result
Indicates the manner in which a task exited
*/
tag task_result {
/* Variant: tr_success */
tr_success;
/* Variant: tr_failure */
tr_failure;
}
/*
Tag: task_notification
Message sent upon task exit to indicate normal or abnormal termination
*/
tag task_notification {
/* Variant: exit */
exit(task, task_result);
}
/* Section: Operations */
/*
Type: get_task
Retreives a handle to the currently executing task
*/
fn get_task() -> task { rustrt::get_task_id() }
/*
Function: sleep
Hints the scheduler to yield this task for a specified ammount of time.
Parameters:
time_in_us - maximum number of microseconds to yield control for
*/
fn sleep(time_in_us: uint) {
let task = rustrt::rust_get_task();
let killed = false;
// FIXME: uncomment this when extfmt is moved to core
// in a snapshot.
// log #fmt("yielding for %u us", time_in_us);
rusti::task_sleep(task, time_in_us, killed);
if killed {
fail "killed";
}
}
/*
Function: yield
Yield control to the task scheduler
The scheduler may schedule another task to execute.
*/
fn yield() { sleep(1u) }
/*
Function: join
Wait for a child task to exit
The child task must have been spawned with <spawn_joinable>, which
produces a notification port that the child uses to communicate its
exit status.
Returns:
A task_result indicating whether the task terminated normally or failed
*/
fn join(task_port: joinable_task) -> task_result {
let (id, port) = task_port;
alt comm::recv::<task_notification>(port) {
exit(_id, res) {
if _id == id {
ret res
} else {
// FIXME: uncomment this when extfmt is moved to core
// in a snapshot.
// fail #fmt["join received id %d, expected %d", _id, id]
fail;
}
}
}
}
/*
Function: unsupervise
Detaches this task from its parent in the task tree
An unsupervised task will not propagate its failure up the task tree
*/
fn unsupervise() { ret sys::unsupervise(); }
/*
Function: pin
Pins the current task and future child tasks to a single scheduler thread
*/
fn pin() { rustrt::pin_task(); }
/*
Function: unpin
Unpin the current task and future child tasks
*/
fn unpin() { rustrt::unpin_task(); }
/*
Function: set_min_stack
Set the minimum stack size (in bytes) for tasks spawned in the future.
This function has global effect and should probably not be used.
*/
fn set_min_stack(stack_size: uint) { rustrt::set_min_stack(stack_size); }
/*
Function: spawn
Creates and executes a new child task
Sets up a new task with its own call stack and schedules it to be executed.
Upon execution the new task will call function `f` with the provided
argument `data`.
Function `f` is a bare function, meaning it may not close over any data, as do
shared functions (fn@) and lambda blocks. `data` must be a uniquely owned
type; it is moved into the new task and thus can no longer be accessed
locally.
Parameters:
data - A unique-type value to pass to the new task
f - A function to execute in the new task
Returns:
A handle to the new task
*/
fn spawn<send T>(-data: T, f: fn(T)) -> task {
spawn_inner(data, f, none)
}
/*
Function: spawn_notify
Create and execute a new child task, requesting notification upon its
termination
Immediately before termination, either on success or failure, the spawned
task will send a <task_notification> message on the provided channel.
*/
fn spawn_notify<send T>(-data: T, f: fn(T),
notify: comm::chan<task_notification>) -> task {
spawn_inner(data, f, some(notify))
}
/*
Function: spawn_joinable
Create and execute a task which can later be joined with the <join> function
This is a convenience wrapper around spawn_notify which, when paired
with <join> can be easily used to spawn a task then wait for it to
complete.
*/
fn spawn_joinable<send T>(-data: T, f: fn(T)) -> joinable_task {
let p = comm::port::<task_notification>();
let id = spawn_notify(data, f, comm::chan::<task_notification>(p));
ret (id, p);
}
// FIXME: To transition from the unsafe spawn that spawns a shared closure to
// the safe spawn that spawns a bare function we're going to write
// barefunc-spawn on top of unsafe-spawn. Sadly, bind does not work reliably
// enough to suite our needs (#1034, probably others yet to be discovered), so
// we're going to copy the bootstrap data into a unique pointer, cast it to an
// unsafe pointer then wrap up the bare function and the unsafe pointer in a
// shared closure to spawn.
//
// After the transition this should all be rewritten.
fn spawn_inner<send T>(-data: T, f: fn(T),
notify: option<comm::chan<task_notification>>)
-> task unsafe {
fn wrapper<send T>(data: *u8, f: fn(T)) unsafe {
let data: ~T = unsafe::reinterpret_cast(data);
f(*data);
}
let data = ~data;
let dataptr: *u8 = unsafe::reinterpret_cast(data);
unsafe::leak(data);
let wrapped = bind wrapper(dataptr, f);
ret unsafe_spawn_inner(wrapped, notify);
}
// FIXME: This is the old spawn function that spawns a shared closure.
// It is a hack and needs to be rewritten.
fn unsafe_spawn_inner(-thunk: fn@(),
notify: option<comm::chan<task_notification>>) ->
task unsafe {
let id = rustrt::new_task();
let raw_thunk: {code: uint, env: uint} = cast(thunk);
// set up the task pointer
let task_ptr <- rust_task_ptr(rustrt::get_task_pointer(id));
assert (ptr::null() != (**task_ptr).stack_ptr);
// copy the thunk from our stack to the new stack
let sp: uint = cast((**task_ptr).stack_ptr);
let ptrsize = sys::size_of::<*u8>();
let thunkfn: *mutable uint = cast(sp - ptrsize * 2u);
let thunkenv: *mutable uint = cast(sp - ptrsize);
*thunkfn = cast(raw_thunk.code);;
*thunkenv = cast(raw_thunk.env);;
// align the stack to 16 bytes
(**task_ptr).stack_ptr = cast(sp - ptrsize * 4u);
// set up notifications if they are enabled.
alt notify {
some(c) {
(**task_ptr).notify_enabled = 1;
(**task_ptr).notify_chan = c;
}
none { }
}
// give the thunk environment's allocation to the new task
rustrt::migrate_alloc(cast(raw_thunk.env), id);
rustrt::start_task(id, cast(thunkfn));
// don't cleanup the thunk in this task
unsafe::leak(thunk);
ret id;
}
// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:

27
src/libcore/u32.rs Normal file
View file

@ -0,0 +1,27 @@
/*
Module: u32
*/
/*
Const: min_value
Return the minimal value for a u32
*/
const min_value: u32 = 0u32;
/*
Const: max_value
Return the maximal value for a u32
*/
const max_value: u32 = 0xffff_ffffu32;
//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
//

88
src/libcore/u64.rs Normal file
View file

@ -0,0 +1,88 @@
/*
Module: u64
*/
/*
Const: min_value
Return the minimal value for a u64
*/
const min_value: u64 = 0u64;
/*
Const: max_value
Return the maximal value for a u64
*/
const max_value: u64 = 18446744073709551615u64;
/*
Function: to_str
Convert to a string in a given base
*/
fn to_str(n: u64, radix: uint) -> str {
assert (0u < radix && radix <= 16u);
let r64 = radix as u64;
fn digit(n: u64) -> str {
ret alt n {
0u64 { "0" }
1u64 { "1" }
2u64 { "2" }
3u64 { "3" }
4u64 { "4" }
5u64 { "5" }
6u64 { "6" }
7u64 { "7" }
8u64 { "8" }
9u64 { "9" }
10u64 { "a" }
11u64 { "b" }
12u64 { "c" }
13u64 { "d" }
14u64 { "e" }
15u64 { "f" }
_ { fail }
};
}
if n == 0u64 { ret "0"; }
let s = "";
let n = n;
while n > 0u64 { s = digit(n % r64) + s; n /= r64; }
ret s;
}
/*
Function: str
Convert to a string
*/
fn str(n: u64) -> str { ret to_str(n, 10u); }
/*
Function: parse_buf
Parse a string as an unsigned integer.
*/
fn from_str(buf: str, radix: u64) -> u64 {
if str::byte_len(buf) == 0u {
log_err "parse_buf(): buf is empty";
fail;
}
let i = str::byte_len(buf) - 1u;
let power = 1u64, n = 0u64;
while true {
let digit = char::to_digit(buf[i] as char) as u64;
if digit >= radix { fail; }
n += digit * power;
power *= radix;
if i == 0u { ret n; }
i -= 1u;
}
fail;
}

68
src/libcore/u8.rs Normal file
View file

@ -0,0 +1,68 @@
/*
Module: u8
*/
/*
Const: max_value
The maximum value of a u8.
*/
const max_value: u8 = 255u8;
/*
Const: min_value
The minumum value of a u8.
*/
const min_value: u8 = 0u8;
/* Function: add */
pure fn add(x: u8, y: u8) -> u8 { ret x + y; }
/* Function: sub */
pure fn sub(x: u8, y: u8) -> u8 { ret x - y; }
/* Function: mul */
pure fn mul(x: u8, y: u8) -> u8 { ret x * y; }
/* Function: div */
pure fn div(x: u8, y: u8) -> u8 { ret x / y; }
/* Function: rem */
pure fn rem(x: u8, y: u8) -> u8 { ret x % y; }
/* Predicate: lt */
pure fn lt(x: u8, y: u8) -> bool { ret x < y; }
/* Predicate: le */
pure fn le(x: u8, y: u8) -> bool { ret x <= y; }
/* Predicate: eq */
pure fn eq(x: u8, y: u8) -> bool { ret x == y; }
/* Predicate: ne */
pure fn ne(x: u8, y: u8) -> bool { ret x != y; }
/* Predicate: ge */
pure fn ge(x: u8, y: u8) -> bool { ret x >= y; }
/* Predicate: gt */
pure fn gt(x: u8, y: u8) -> bool { ret x > y; }
/*
Function: range
Iterate over the range [`lo`..`hi`)
*/
fn range(lo: u8, hi: u8, it: block(u8)) {
let i = lo;
while i < hi { it(i); i += 1u8; }
}
// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:

254
src/libcore/uint.rs Normal file
View file

@ -0,0 +1,254 @@
/*
Module: uint
*/
/*
Const: min_value
Return the minimal value for an uint.
This is always 0
*/
const min_value: uint = 0u;
/*
Const: max_value
Return the maximal value for an uint.
This is 2^wordsize - 1
*/
const max_value: uint = 0u - 1u;
/* Function: add */
pure fn add(x: uint, y: uint) -> uint { ret x + y; }
/* Function: sub */
pure fn sub(x: uint, y: uint) -> uint { ret x - y; }
/* Function: mul */
pure fn mul(x: uint, y: uint) -> uint { ret x * y; }
/* Function: div */
pure fn div(x: uint, y: uint) -> uint { ret x / y; }
/* Function: div_ceil
Divide two numbers, return the result, rounded up.
Parameters:
x - an integer
y - an integer distinct from 0u
Return:
The smallest integer `q` such that `x/y <= q`.
*/
pure fn div_ceil(x: uint, y: uint) -> uint {
let div = div(x, y);
if x % y == 0u { ret div;}
else { ret div + 1u; }
}
/* Function: div_ceil
Divide two numbers, return the result, rounded to the closest integer.
Parameters:
x - an integer
y - an integer distinct from 0u
Return:
The integer `q` closest to `x/y`.
*/
pure fn div_round(x: uint, y: uint) -> uint {
let div = div(x, y);
if x % y * 2u < y { ret div;}
else { ret div + 1u; }
}
/* Function: div_ceil
Divide two numbers, return the result, rounded down.
Parameters:
x - an integer
y - an integer distinct from 0u
Note: This is the same function as `div`.
Return:
The smallest integer `q` such that `x/y <= q`. This
is either `x/y` or `x/y + 1`.
*/
pure fn div_floor(x: uint, y: uint) -> uint { ret x / y; }
/* Function: rem */
pure fn rem(x: uint, y: uint) -> uint { ret x % y; }
/* Predicate: lt */
pure fn lt(x: uint, y: uint) -> bool { ret x < y; }
/* Predicate: le */
pure fn le(x: uint, y: uint) -> bool { ret x <= y; }
/* Predicate: eq */
pure fn eq(x: uint, y: uint) -> bool { ret x == y; }
/* Predicate: ne */
pure fn ne(x: uint, y: uint) -> bool { ret x != y; }
/* Predicate: ge */
pure fn ge(x: uint, y: uint) -> bool { ret x >= y; }
/* Predicate: gt */
pure fn gt(x: uint, y: uint) -> bool { ret x > y; }
/*
Function: range
Iterate over the range [`lo`..`hi`)
*/
fn range(lo: uint, hi: uint, it: block(uint)) {
let i = lo;
while i < hi { it(i); i += 1u; }
}
/*
Function: loop
Iterate over the range [`lo`..`hi`), or stop when requested
Parameters:
lo - The integer at which to start the loop (included)
hi - The integer at which to stop the loop (excluded)
it - A block to execute with each consecutive integer of the range.
Return `true` to continue, `false` to stop.
Returns:
`true` If execution proceeded correctly, `false` if it was interrupted,
that is if `it` returned `false` at any point.
*/
fn loop(lo: uint, hi: uint, it: block(uint) -> bool) -> bool {
let i = lo;
while i < hi {
if (!it(i)) { ret false; }
i += 1u;
}
ret true;
}
/*
Function: next_power_of_two
Returns the smallest power of 2 greater than or equal to `n`
*/
fn next_power_of_two(n: uint) -> uint {
let halfbits: uint = sys::size_of::<uint>() * 4u;
let tmp: uint = n - 1u;
let shift: uint = 1u;
while shift <= halfbits { tmp |= tmp >> shift; shift <<= 1u; }
ret tmp + 1u;
}
/*
Function: parse_buf
Parse a buffer of bytes
Parameters:
buf - A byte buffer
radix - The base of the number
Failure:
buf must not be empty
*/
fn parse_buf(buf: [u8], radix: uint) -> uint {
if vec::len::<u8>(buf) == 0u {
log_err "parse_buf(): buf is empty";
fail;
}
let i = vec::len::<u8>(buf) - 1u;
let power = 1u;
let n = 0u;
while true {
let digit = char::to_digit(buf[i] as char);
if (digit as uint) >= radix {
fail;
}
n += (digit as uint) * power;
power *= radix;
if i == 0u { ret n; }
i -= 1u;
}
fail;
}
/*
Function: from_str
Parse a string to an int
Failure:
s must not be empty
*/
fn from_str(s: str) -> uint { parse_buf(str::bytes(s), 10u) }
/*
Function: to_str
Convert to a string in a given base
*/
fn to_str(num: uint, radix: uint) -> str {
let n = num;
assert (0u < radix && radix <= 16u);
fn digit(n: uint) -> char {
ret alt n {
0u { '0' }
1u { '1' }
2u { '2' }
3u { '3' }
4u { '4' }
5u { '5' }
6u { '6' }
7u { '7' }
8u { '8' }
9u { '9' }
10u { 'a' }
11u { 'b' }
12u { 'c' }
13u { 'd' }
14u { 'e' }
15u { 'f' }
_ { fail }
};
}
if n == 0u { ret "0"; }
let s: str = "";
while n != 0u {
s += str::unsafe_from_byte(digit(n % radix) as u8);
n /= radix;
}
let s1: str = "";
let len: uint = str::byte_len(s);
while len != 0u { len -= 1u; s1 += str::unsafe_from_byte(s[len]); }
ret s1;
}
/*
Function: str
Convert to a string
*/
fn str(i: uint) -> str { ret to_str(i, 10u); }
// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:

41
src/libcore/unsafe.rs Normal file
View file

@ -0,0 +1,41 @@
/*
Module: unsafe
Unsafe operations
*/
#[abi = "rust-intrinsic"]
native mod rusti {
fn cast<T, U>(src: T) -> U;
}
#[abi = "cdecl"]
native mod rustrt {
fn leak<T>(-thing: T);
}
/*
Function: reinterpret_cast
Casts the value at `src` to U. The two types must have the same length.
*/
unsafe fn reinterpret_cast<T, U>(src: T) -> U {
let t1 = sys::get_type_desc::<T>();
let t2 = sys::get_type_desc::<U>();
if (*t1).size != (*t2).size {
fail "attempt to cast values of differing sizes";
}
ret rusti::cast(src);
}
/*
Function: leak
Move `thing` into the void.
The leak function will take ownership of the provided value but neglect
to run any required cleanup or memory-management operations on it. This
can be used for various acts of magick, particularly when using
reinterpret_cast on managed pointer types.
*/
unsafe fn leak<T>(-thing: T) { rustrt::leak(thing); }

835
src/libcore/vec.rs Normal file
View file

@ -0,0 +1,835 @@
/*
Module: vec
*/
import option::{some, none};
import uint::next_power_of_two;
import ptr::addr_of;
#[abi = "rust-intrinsic"]
native mod rusti {
fn vec_len<T>(&&v: [const T]) -> uint;
}
#[abi = "cdecl"]
native mod rustrt {
fn vec_reserve_shared<T>(t: *sys::type_desc,
&v: [const T],
n: uint);
fn vec_from_buf_shared<T>(t: *sys::type_desc,
ptr: *T,
count: uint) -> [T];
}
/*
Type: init_op
A function used to initialize the elements of a vector.
*/
type init_op<T> = block(uint) -> T;
/*
Predicate: is_empty
Returns true if a vector contains no elements.
*/
pure fn is_empty<T>(v: [const T]) -> bool {
// FIXME: This would be easier if we could just call len
for t: T in v { ret false; }
ret true;
}
/*
Predicate: is_not_empty
Returns true if a vector contains some elements.
*/
pure fn is_not_empty<T>(v: [const T]) -> bool { ret !is_empty(v); }
/*
Predicate: same_length
Returns true if two vectors have the same length
*/
pure fn same_length<T, U>(xs: [T], ys: [U]) -> bool {
vec::len(xs) == vec::len(ys)
}
/*
Function: reserve
Reserves capacity for `n` elements in the given vector.
If the capacity for `v` is already equal to or greater than the requested
capacity, then no action is taken.
Parameters:
v - A vector
n - The number of elements to reserve space for
*/
fn reserve<T>(&v: [const T], n: uint) {
rustrt::vec_reserve_shared(sys::get_type_desc::<T>(), v, n);
}
/*
Function: len
Returns the length of a vector
*/
pure fn len<T>(v: [const T]) -> uint { unchecked { rusti::vec_len(v) } }
/*
Function: init_fn
Creates and initializes an immutable vector.
Creates an immutable vector of size `n_elts` and initializes the elements
to the value returned by the function `op`.
*/
fn init_fn<T>(op: init_op<T>, n_elts: uint) -> [T] {
let v = [];
reserve(v, n_elts);
let i: uint = 0u;
while i < n_elts { v += [op(i)]; i += 1u; }
ret v;
}
// TODO: Remove me once we have slots.
/*
Function: init_fn_mut
Creates and initializes a mutable vector.
Creates a mutable vector of size `n_elts` and initializes the elements to
the value returned by the function `op`.
*/
fn init_fn_mut<T>(op: init_op<T>, n_elts: uint) -> [mutable T] {
let v = [mutable];
reserve(v, n_elts);
let i: uint = 0u;
while i < n_elts { v += [mutable op(i)]; i += 1u; }
ret v;
}
/*
Function: init_elt
Creates and initializes an immutable vector.
Creates an immutable vector of size `n_elts` and initializes the elements
to the value `t`.
*/
fn init_elt<copy T>(t: T, n_elts: uint) -> [T] {
let v = [];
reserve(v, n_elts);
let i: uint = 0u;
while i < n_elts { v += [t]; i += 1u; }
ret v;
}
// TODO: Remove me once we have slots.
/*
Function: init_elt_mut
Creates and initializes a mutable vector.
Creates a mutable vector of size `n_elts` and initializes the elements
to the value `t`.
*/
fn init_elt_mut<copy T>(t: T, n_elts: uint) -> [mutable T] {
let v = [mutable];
reserve(v, n_elts);
let i: uint = 0u;
while i < n_elts { v += [mutable t]; i += 1u; }
ret v;
}
// FIXME: Possible typestate postcondition:
// len(result) == len(v) (needs issue #586)
/*
Function: to_mut
Produces a mutable vector from an immutable vector.
*/
fn to_mut<copy T>(v: [T]) -> [mutable T] {
let vres = [mutable];
for t: T in v { vres += [mutable t]; }
ret vres;
}
// Same comment as from_mut
/*
Function: from_mut
Produces an immutable vector from a mutable vector.
*/
fn from_mut<copy T>(v: [mutable T]) -> [T] {
let vres = [];
for t: T in v { vres += [t]; }
ret vres;
}
// Accessors
/*
Function: head
Returns the first element of a vector
Predicates:
<is_not_empty> (v)
*/
fn head<copy T>(v: [const T]) : is_not_empty(v) -> T { ret v[0]; }
/*
Function: tail
Returns all but the first element of a vector
Predicates:
<is_not_empty> (v)
*/
fn tail<copy T>(v: [const T]) : is_not_empty(v) -> [T] {
ret slice(v, 1u, len(v));
}
// FIXME: This name is sort of confusing next to init_fn, etc
// but this is the name haskell uses for this function,
// along with head/tail/last.
/*
Function: init
Returns all but the last elemnt of a vector
Preconditions:
`v` is not empty
*/
fn init<copy T>(v: [const T]) -> [T] {
assert len(v) != 0u;
slice(v, 0u, len(v) - 1u)
}
/*
Function: last
Returns the last element of a vector
Returns:
An option containing the last element of `v` if `v` is not empty, or
none if `v` is empty.
*/
fn last<copy T>(v: [const T]) -> option::t<T> {
if len(v) == 0u { ret none; }
ret some(v[len(v) - 1u]);
}
/*
Function: last_total
Returns the last element of a non-empty vector `v`
Predicates:
<is_not_empty> (v)
*/
fn last_total<copy T>(v: [const T]) : is_not_empty(v) -> T {
ret v[len(v) - 1u];
}
/*
Function: slice
Returns a copy of the elements from [`start`..`end`) from `v`.
*/
fn slice<copy T>(v: [const T], start: uint, end: uint) -> [T] {
assert (start <= end);
assert (end <= len(v));
let result = [];
reserve(result, end - start);
let i = start;
while i < end { result += [v[i]]; i += 1u; }
ret result;
}
// TODO: Remove me once we have slots.
/*
Function: slice_mut
Returns a copy of the elements from [`start`..`end`) from `v`.
*/
fn slice_mut<copy T>(v: [const T], start: uint, end: uint) -> [mutable T] {
assert (start <= end);
assert (end <= len(v));
let result = [mutable];
reserve(result, end - start);
let i = start;
while i < end { result += [mutable v[i]]; i += 1u; }
ret result;
}
// Mutators
/*
Function: shift
Removes the first element from a vector and return it
*/
fn shift<copy T>(&v: [const T]) -> T {
let ln = len::<T>(v);
assert (ln > 0u);
let e = v[0];
v = slice::<T>(v, 1u, ln);
ret e;
}
// TODO: Write this, unsafely, in a way that's not O(n).
/*
Function: pop
Remove the last element from a vector and return it
*/
fn pop<copy T>(&v: [const T]) -> T {
let ln = len(v);
assert (ln > 0u);
ln -= 1u;
let e = v[ln];
v = slice(v, 0u, ln);
ret e;
}
// TODO: More.
// Appending
/*
Function: grow
Expands a vector in place, initializing the new elements to a given value
Parameters:
v - The vector to grow
n - The number of elements to add
initval - The value for the new elements
*/
fn grow<copy T>(&v: [T], n: uint, initval: T) {
reserve(v, next_power_of_two(len(v) + n));
let i: uint = 0u;
while i < n { v += [initval]; i += 1u; }
}
// TODO: Remove me once we have slots.
// FIXME: Can't grow take a [const T]
/*
Function: grow_mut
Expands a vector in place, initializing the new elements to a given value
Parameters:
v - The vector to grow
n - The number of elements to add
initval - The value for the new elements
*/
fn grow_mut<copy T>(&v: [mutable T], n: uint, initval: T) {
reserve(v, next_power_of_two(len(v) + n));
let i: uint = 0u;
while i < n { v += [mutable initval]; i += 1u; }
}
/*
Function: grow_fn
Expands a vector in place, initializing the new elements to the result of a
function
Function `init_fn` is called `n` times with the values [0..`n`)
Parameters:
v - The vector to grow
n - The number of elements to add
init_fn - A function to call to retreive each appended element's value
*/
fn grow_fn<T>(&v: [T], n: uint, op: init_op<T>) {
reserve(v, next_power_of_two(len(v) + n));
let i: uint = 0u;
while i < n { v += [op(i)]; i += 1u; }
}
/*
Function: grow_set
Sets the value of a vector element at a given index, growing the vector as
needed
Sets the element at position `index` to `val`. If `index` is past the end
of the vector, expands the vector by replicating `initval` to fill the
intervening space.
*/
fn grow_set<copy T>(&v: [mutable T], index: uint, initval: T, val: T) {
if index >= len(v) { grow_mut(v, index - len(v) + 1u, initval); }
v[index] = val;
}
// Functional utilities
/*
Function: map
Apply a function to each element of a vector and return the results
*/
fn map<T, U>(f: block(T) -> U, v: [T]) -> [U] {
let result = [];
reserve(result, len(v));
for elem: T in v { result += [f(elem)]; }
ret result;
}
/*
Function: map_mut
Apply a function to each element of a mutable vector and return the results
*/
fn map_mut<copy T, U>(f: block(T) -> U, v: [const T]) -> [U] {
let result = [];
reserve(result, len(v));
for elem: T in v {
// copy satisfies alias checker
result += [f(copy elem)];
}
ret result;
}
/*
Function: map2
Apply a function to each pair of elements and return the results
*/
fn map2<copy T, copy U, V>(f: block(T, U) -> V, v0: [T], v1: [U]) -> [V] {
let v0_len = len(v0);
if v0_len != len(v1) { fail; }
let u: [V] = [];
let i = 0u;
while i < v0_len { u += [f(copy v0[i], copy v1[i])]; i += 1u; }
ret u;
}
/*
Function: filter_map
Apply a function to each element of a vector and return the results
If function `f` returns `none` then that element is excluded from
the resulting vector.
*/
fn filter_map<copy T, copy U>(f: block(T) -> option::t<U>, v: [const T])
-> [U] {
let result = [];
for elem: T in v {
alt f(copy elem) {
none. {/* no-op */ }
some(result_elem) { result += [result_elem]; }
}
}
ret result;
}
/*
Function: filter
Construct a new vector from the elements of a vector for which some predicate
holds.
Apply function `f` to each element of `v` and return a vector containing
only those elements for which `f` returned true.
*/
fn filter<copy T>(f: block(T) -> bool, v: [T]) -> [T] {
let result = [];
for elem: T in v {
if f(elem) { result += [elem]; }
}
ret result;
}
/*
Function: concat
Concatenate a vector of vectors. Flattens a vector of vectors of T into
a single vector of T.
*/
fn concat<copy T>(v: [const [const T]]) -> [T] {
let new: [T] = [];
for inner: [T] in v { new += inner; }
ret new;
}
/*
Function: foldl
Reduce a vector from left to right
*/
fn foldl<copy T, U>(p: block(T, U) -> T, z: T, v: [const U]) -> T {
let accum = z;
iter(v) { |elt|
accum = p(accum, elt);
}
ret accum;
}
/*
Function: foldr
Reduce a vector from right to left
*/
fn foldr<T, copy U>(p: block(T, U) -> U, z: U, v: [const T]) -> U {
let accum = z;
riter(v) { |elt|
accum = p(elt, accum);
}
ret accum;
}
/*
Function: any
Return true if a predicate matches any elements
If the vector contains no elements then false is returned.
*/
fn any<T>(f: block(T) -> bool, v: [T]) -> bool {
for elem: T in v { if f(elem) { ret true; } }
ret false;
}
/*
Function: all
Return true if a predicate matches all elements
If the vector contains no elements then true is returned.
*/
fn all<T>(f: block(T) -> bool, v: [T]) -> bool {
for elem: T in v { if !f(elem) { ret false; } }
ret true;
}
/*
Function: member
Return true if a vector contains an element with the given value
*/
fn member<T>(x: T, v: [T]) -> bool {
for elt: T in v { if x == elt { ret true; } }
ret false;
}
/*
Function: count
Returns the number of elements that are equal to a given value
*/
fn count<T>(x: T, v: [const T]) -> uint {
let cnt = 0u;
for elt: T in v { if x == elt { cnt += 1u; } }
ret cnt;
}
/*
Function: find
Search for an element that matches a given predicate
Apply function `f` to each element of `v`, starting from the first.
When function `f` returns true then an option containing the element
is returned. If `f` matches no elements then none is returned.
*/
fn find<copy T>(f: block(T) -> bool, v: [T]) -> option::t<T> {
for elt: T in v { if f(elt) { ret some(elt); } }
ret none;
}
/*
Function: position
Find the first index containing a matching value
Returns:
option::some(uint) - The first index containing a matching value
option::none - No elements matched
*/
fn position<T>(x: T, v: [T]) -> option::t<uint> {
let i: uint = 0u;
while i < len(v) { if x == v[i] { ret some::<uint>(i); } i += 1u; }
ret none;
}
/*
Function: position_pred
Find the first index for which the value matches some predicate
*/
fn position_pred<T>(f: block(T) -> bool, v: [T]) -> option::t<uint> {
let i: uint = 0u;
while i < len(v) { if f(v[i]) { ret some::<uint>(i); } i += 1u; }
ret none;
}
// FIXME: if issue #586 gets implemented, could have a postcondition
// saying the two result lists have the same length -- or, could
// return a nominal record with a constraint saying that, instead of
// returning a tuple (contingent on issue #869)
/*
Function: unzip
Convert a vector of pairs into a pair of vectors
Returns a tuple containing two vectors where the i-th element of the first
vector contains the first element of the i-th tuple of the input vector,
and the i-th element of the second vector contains the second element
of the i-th tuple of the input vector.
*/
fn unzip<copy T, copy U>(v: [(T, U)]) -> ([T], [U]) {
let as = [], bs = [];
for (a, b) in v { as += [a]; bs += [b]; }
ret (as, bs);
}
/*
Function: zip
Convert two vectors to a vector of pairs
Returns a vector of tuples, where the i-th tuple contains contains the
i-th elements from each of the input vectors.
Preconditions:
<same_length> (v, u)
*/
fn zip<copy T, copy U>(v: [T], u: [U]) : same_length(v, u) -> [(T, U)] {
let zipped = [];
let sz = len(v), i = 0u;
assert (sz == len(u));
while i < sz { zipped += [(v[i], u[i])]; i += 1u; }
ret zipped;
}
/*
Function: swap
Swaps two elements in a vector
Parameters:
v - The input vector
a - The index of the first element
b - The index of the second element
*/
fn swap<T>(v: [mutable T], a: uint, b: uint) {
v[a] <-> v[b];
}
/*
Function: reverse
Reverse the order of elements in a vector, in place
*/
fn reverse<T>(v: [mutable T]) {
let i: uint = 0u;
let ln = len::<T>(v);
while i < ln / 2u { v[i] <-> v[ln - i - 1u]; i += 1u; }
}
/*
Function: reversed
Returns a vector with the order of elements reversed
*/
fn reversed<copy T>(v: [const T]) -> [T] {
let rs: [T] = [];
let i = len::<T>(v);
if i == 0u { ret rs; } else { i -= 1u; }
while i != 0u { rs += [v[i]]; i -= 1u; }
rs += [v[0]];
ret rs;
}
// FIXME: Seems like this should take char params. Maybe belongs in char
/*
Function: enum_chars
Returns a vector containing a range of chars
*/
fn enum_chars(start: u8, end: u8) : u8::le(start, end) -> [char] {
let i = start;
let r = [];
while i <= end { r += [i as char]; i += 1u as u8; }
ret r;
}
// FIXME: Probably belongs in uint. Compare to uint::range
/*
Function: enum_uints
Returns a vector containing a range of uints
*/
fn enum_uints(start: uint, end: uint) : uint::le(start, end) -> [uint] {
let i = start;
let r = [];
while i <= end { r += [i]; i += 1u; }
ret r;
}
/*
Function: iter
Iterates over a vector
Iterates over vector `v` and, for each element, calls function `f` with the
element's value.
*/
fn iter<T>(v: [const T], f: block(T)) {
iter2(v) { |_i, v| f(v) }
}
/*
Function: iter2
Iterates over a vector's elements and indexes
Iterates over vector `v` and, for each element, calls function `f` with the
element's value and index.
*/
fn iter2<T>(v: [const T], f: block(uint, T)) {
let i = 0u, l = len(v);
while i < l { f(i, v[i]); i += 1u; }
}
/*
Function: riter
Iterates over a vector in reverse
Iterates over vector `v` and, for each element, calls function `f` with the
element's value.
*/
fn riter<T>(v: [const T], f: block(T)) {
riter2(v) { |_i, v| f(v) }
}
/*
Function: riter2
Iterates over a vector's elements and indexes in reverse
Iterates over vector `v` and, for each element, calls function `f` with the
element's value and index.
*/
fn riter2<T>(v: [const T], f: block(uint, T)) {
let i = len(v);
while 0u < i {
i -= 1u;
f(i, v[i]);
};
}
/*
Function: permute
Iterate over all permutations of vector `v`. Permutations are produced in
lexicographic order with respect to the order of elements in `v` (so if `v`
is sorted then the permutations are lexicographically sorted).
The total number of permutations produced is `len(v)!`. If `v` contains
repeated elements, then some permutations are repeated.
*/
fn permute<copy T>(v: [const T], put: block([T])) {
let ln = len(v);
if ln == 0u {
put([]);
} else {
let i = 0u;
while i < ln {
let elt = v[i];
let rest = slice(v, 0u, i) + slice(v, i+1u, ln);
permute(rest) {|permutation| put([elt] + permutation)}
i += 1u;
}
}
}
/*
Function: to_ptr
FIXME: We don't need this wrapper
*/
unsafe fn to_ptr<T>(v: [T]) -> *T { ret unsafe::to_ptr(v); }
/*
Module: unsafe
*/
mod unsafe {
type vec_repr = {mutable fill: uint, mutable alloc: uint, data: u8};
/*
Function: from_buf
Constructs a vector from an unsafe pointer to a buffer
Parameters:
ptr - An unsafe pointer to a buffer of `T`
elts - The number of elements in the buffer
*/
unsafe fn from_buf<T>(ptr: *T, elts: uint) -> [T] {
ret rustrt::vec_from_buf_shared(sys::get_type_desc::<T>(),
ptr, elts);
}
/*
Function: set_len
Sets the length of a vector
This well explicitly set the size of the vector, without actually
modifing its buffers, so it is up to the caller to ensure that
the vector is actually the specified size.
*/
unsafe fn set_len<T>(&v: [const T], new_len: uint) {
let repr: **vec_repr = ::unsafe::reinterpret_cast(addr_of(v));
(**repr).fill = new_len * sys::size_of::<T>();
}
/*
Function: to_ptr
Returns an unsafe pointer to the vector's buffer
The caller must ensure that the vector outlives the pointer this
function returns, or else it will end up pointing to garbage.
Modifying the vector may cause its buffer to be reallocated, which
would also make any pointers to it invalid.
*/
unsafe fn to_ptr<T>(v: [const T]) -> *T {
let repr: **vec_repr = ::unsafe::reinterpret_cast(addr_of(v));
ret ::unsafe::reinterpret_cast(addr_of((**repr).data));
}
}
// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:

View file

@ -3,6 +3,7 @@
// Simple Extensible Binary Markup Language (ebml) reader and writer on a // Simple Extensible Binary Markup Language (ebml) reader and writer on a
// cursor model. See the specification here: // cursor model. See the specification here:
// http://www.matroska.org/technical/specs/rfc/index.html // http://www.matroska.org/technical/specs/rfc/index.html
import core::option;
import option::{some, none}; import option::{some, none};
type ebml_tag = {id: uint, size: uint}; type ebml_tag = {id: uint, size: uint};

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