Copy first batch of material from libstd to libcore.
This commit is contained in:
parent
32087f5c2a
commit
fa9ad984fb
325 changed files with 5579 additions and 720 deletions
|
@ -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,
|
||||||
|
|
|
@ -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)); }
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import std::{vec, option};
|
import core::{vec, option};
|
||||||
import syntax::{ast, fold};
|
import syntax::{ast, fold};
|
||||||
import attr;
|
import attr;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 "*" +
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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::*;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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};
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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.
|
||||||
//
|
//
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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"];
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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};
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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::*;
|
||||||
|
|
|
@ -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";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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::*;
|
||||||
|
|
|
@ -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};
|
||||||
|
|
|
@ -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];
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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};
|
||||||
|
|
|
@ -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) }
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import std::option;
|
import option;
|
||||||
import base::*;
|
import base::*;
|
||||||
import syntax::ast;
|
import syntax::ast;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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::*;
|
||||||
|
|
|
@ -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"; }
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import std::{vec, option};
|
import core::{vec, option};
|
||||||
import base::*;
|
import base::*;
|
||||||
import syntax::ast;
|
import syntax::ast;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import std::{option};
|
import option;
|
||||||
import base::*;
|
import base::*;
|
||||||
import syntax::ast;
|
import syntax::ast;
|
||||||
|
|
||||||
|
|
|
@ -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};
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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>,
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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; }
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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 }
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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
134
src/libcore/bool.rs
Normal 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
20
src/libcore/box.rs
Normal 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
150
src/libcore/char.rs
Normal 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
184
src/libcore/comm.rs
Normal 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))
|
||||||
|
}
|
|
@ -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
146
src/libcore/ctypes.rs
Normal 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
89
src/libcore/either.rs
Normal 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
453
src/libcore/extfmt.rs
Normal 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
343
src/libcore/float.rs
Normal 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
189
src/libcore/int.rs
Normal 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
93
src/libcore/option.rs
Normal 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
52
src/libcore/ptr.rs
Normal 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
112
src/libcore/result.rs
Normal 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
962
src/libcore/str.rs
Normal 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
96
src/libcore/sys.rs
Normal 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
357
src/libcore/task.rs
Normal 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
27
src/libcore/u32.rs
Normal 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
88
src/libcore/u64.rs
Normal 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
68
src/libcore/u8.rs
Normal 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
254
src/libcore/uint.rs
Normal 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
41
src/libcore/unsafe.rs
Normal 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
835
src/libcore/vec.rs
Normal 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:
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue