Merge branch 'master' of github.com:graydon/rust
This commit is contained in:
commit
47d27af228
16 changed files with 176 additions and 322 deletions
|
@ -27,6 +27,7 @@ Jesse Ruderman <jruderman@gmail.com>
|
|||
Josh Matthews <josh@joshmatthews.net>
|
||||
Joshua Wise <joshua@joshuawise.com>
|
||||
Kelly Wilson <wilsonk@cpsc.ucalgary.ca>
|
||||
Lennart Kudling
|
||||
Lindsey Kuper <lkuper@mozilla.com>
|
||||
Marijn Haverbeke <marijnh@gmail.com>
|
||||
Matt Brubeck <mbrubeck@limpet.net>
|
||||
|
|
|
@ -653,7 +653,7 @@ fn encode_hash(ebml_w: ebml::writer, hash: str) {
|
|||
|
||||
fn encode_metadata(cx: @crate_ctxt, crate: @crate) -> str {
|
||||
|
||||
let abbrevs = map::mk_hashmap(ty::hash_ty, ty::eq_ty);
|
||||
let abbrevs = ty::new_ty_hash();
|
||||
let ecx = @{ccx: cx, type_abbrevs: abbrevs};
|
||||
|
||||
let string_w = io::string_writer();
|
||||
|
|
|
@ -43,7 +43,6 @@ fn check_expr(sess: session, e: @expr, &&is_const: bool, v: visit::vt<bool>) {
|
|||
"disallowed operator in constant expression");
|
||||
ret;
|
||||
}
|
||||
expr_cast(_, _) { }
|
||||
expr_lit(@{node: lit_str(_), _}) {
|
||||
sess.span_err(e.span,
|
||||
"string constants are not supported");
|
||||
|
|
|
@ -267,8 +267,7 @@ fn create_basic_type(cx: @crate_ctxt, t: ty::t, ty: @ast::ty)
|
|||
let cache = get_cache(cx);
|
||||
let tg = BasicTypeDescriptorTag;
|
||||
alt cached_metadata::<@metadata<tydesc_md>>(
|
||||
cache, tg,
|
||||
{|md| ty::hash_ty(t) == ty::hash_ty(md.data.hash)}) {
|
||||
cache, tg, {|md| t == md.data.hash}) {
|
||||
option::some(md) { ret md; }
|
||||
option::none. {}
|
||||
}
|
||||
|
@ -311,7 +310,7 @@ fn create_basic_type(cx: @crate_ctxt, t: ty::t, ty: @ast::ty)
|
|||
lli32(0), //XXX flags?
|
||||
lli32(encoding)];
|
||||
let llnode = llmdnode(lldata);
|
||||
let mdval = @{node: llnode, data: {hash: ty::hash_ty(t)}};
|
||||
let mdval = @{node: llnode, data: {hash: t}};
|
||||
update_cache(cache, tg, tydesc_metadata(mdval));
|
||||
add_named_metadata(cx, "llvm.dbg.ty", llnode);
|
||||
ret mdval;
|
||||
|
@ -333,7 +332,7 @@ fn create_pointer_type(cx: @crate_ctxt, t: ty::t, span: codemap::span,
|
|||
//let cu_node = create_compile_unit(cx, fname);
|
||||
let llnode = create_derived_type(tg, file_node.node, "", 0, size * 8,
|
||||
align * 8, 0, pointee.node);
|
||||
let mdval = @{node: llnode, data: {hash: ty::hash_ty(t)}};
|
||||
let mdval = @{node: llnode, data: {hash: t}};
|
||||
//update_cache(cache, tg, tydesc_metadata(mdval));
|
||||
add_named_metadata(cx, "llvm.dbg.ty", llnode);
|
||||
ret mdval;
|
||||
|
|
|
@ -3581,12 +3581,7 @@ fn trans_expr(bcx: @block_ctxt, e: @ast::expr, dest: dest) -> @block_ctxt {
|
|||
}
|
||||
else { ret lval_to_dps(bcx, a, dest); }
|
||||
}
|
||||
ast::expr_cast(val, _) {
|
||||
alt tcx.cast_map.find(e.id) {
|
||||
some(ty::triv_cast.) { ret trans_expr(bcx, val, dest); }
|
||||
_ { ret trans_cast(bcx, val, e.id, dest); }
|
||||
}
|
||||
}
|
||||
ast::expr_cast(val, _) { ret trans_cast(bcx, val, e.id, dest); }
|
||||
ast::expr_anon_obj(anon_obj) {
|
||||
ret trans_anon_obj(bcx, e.span, anon_obj, e.id, dest);
|
||||
}
|
||||
|
@ -3615,7 +3610,7 @@ fn trans_expr(bcx: @block_ctxt, e: @ast::expr, dest: dest) -> @block_ctxt {
|
|||
// that is_call_expr(ex) -- but we don't support that
|
||||
// yet
|
||||
// FIXME
|
||||
check (ast_util::is_tail_call_expr(ex));
|
||||
check (ast_util::is_call_expr(ex));
|
||||
ret trans_be(bcx, ex);
|
||||
}
|
||||
ast::expr_fail(expr) {
|
||||
|
@ -3952,8 +3947,7 @@ fn trans_ret(bcx: @block_ctxt, e: option::t<@ast::expr>) -> @block_ctxt {
|
|||
fn build_return(bcx: @block_ctxt) { Br(bcx, bcx_fcx(bcx).llreturn); }
|
||||
|
||||
// fn trans_be(cx: &@block_ctxt, e: &@ast::expr) -> result {
|
||||
fn trans_be(cx: @block_ctxt, e: @ast::expr) :
|
||||
ast_util::is_tail_call_expr(e) ->
|
||||
fn trans_be(cx: @block_ctxt, e: @ast::expr) : ast_util::is_call_expr(e) ->
|
||||
@block_ctxt {
|
||||
// FIXME: Turn this into a real tail call once
|
||||
// calling convention issues are settled
|
||||
|
@ -4354,7 +4348,7 @@ fn new_fn_ctxt_w_id(cx: @local_ctxt, sp: span, llfndecl: ValueRef,
|
|||
lllocals: new_int_hash::<local_val>(),
|
||||
llupvars: new_int_hash::<ValueRef>(),
|
||||
mutable lltydescs: [],
|
||||
derived_tydescs: map::mk_hashmap(ty::hash_ty, ty::eq_ty),
|
||||
derived_tydescs: ty::new_ty_hash(),
|
||||
id: id,
|
||||
ret_style: rstyle,
|
||||
sp: sp,
|
||||
|
@ -4728,16 +4722,6 @@ fn trans_impl(cx: @local_ctxt, name: ast::ident, methods: [@ast::method],
|
|||
// that does so later on?
|
||||
fn trans_const_expr(cx: @crate_ctxt, e: @ast::expr) -> ValueRef {
|
||||
alt e.node {
|
||||
ast::expr_cast(e1, _) {
|
||||
alt ccx_tcx(cx).cast_map.find(e.id) {
|
||||
some(ty::triv_cast.) { trans_const_expr(cx, e1) }
|
||||
_ {
|
||||
cx.sess.span_err(e.span,
|
||||
"non-trivial cast in constant expression");
|
||||
fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::expr_lit(lit) { ret trans_crate_lit(cx, *lit); }
|
||||
ast::expr_binary(b, e1, e2) {
|
||||
let te1 = trans_const_expr(cx, e1);
|
||||
|
@ -5658,13 +5642,6 @@ fn trans_crate(sess: session::session, crate: @ast::crate, tcx: ty::ctxt,
|
|||
tn.associate("taskptr", taskptr_type);
|
||||
let tydesc_type = T_tydesc(targ_cfg);
|
||||
tn.associate("tydesc", tydesc_type);
|
||||
let hasher = ty::hash_ty;
|
||||
let eqer = ty::eq_ty;
|
||||
let tag_sizes = map::mk_hashmap::<ty::t, uint>(hasher, eqer);
|
||||
let tydescs = map::mk_hashmap::<ty::t, @tydesc_info>(hasher, eqer);
|
||||
let lltypes = map::mk_hashmap::<ty::t, TypeRef>(hasher, eqer);
|
||||
let sha1s = map::mk_hashmap::<ty::t, str>(hasher, eqer);
|
||||
let short_names = map::mk_hashmap::<ty::t, str>(hasher, eqer);
|
||||
let crate_map = decl_crate_map(sess, link_meta.name, llmod);
|
||||
let dbg_cx = if sess.get_opts().debuginfo {
|
||||
option::some(@{llmetadata: map::new_int_hash(),
|
||||
|
@ -5685,18 +5662,18 @@ fn trans_crate(sess: session::session, crate: @ast::crate, tcx: ty::ctxt,
|
|||
item_symbols: new_int_hash::<str>(),
|
||||
mutable main_fn: none::<ValueRef>,
|
||||
link_meta: link_meta,
|
||||
tag_sizes: tag_sizes,
|
||||
tag_sizes: ty::new_ty_hash(),
|
||||
discrims: ast_util::new_def_id_hash::<ValueRef>(),
|
||||
discrim_symbols: new_int_hash::<str>(),
|
||||
consts: new_int_hash::<ValueRef>(),
|
||||
obj_methods: new_int_hash::<()>(),
|
||||
tydescs: tydescs,
|
||||
tydescs: ty::new_ty_hash(),
|
||||
module_data: new_str_hash::<ValueRef>(),
|
||||
lltypes: lltypes,
|
||||
lltypes: ty::new_ty_hash(),
|
||||
names: namegen(0),
|
||||
sha: sha,
|
||||
type_sha1s: sha1s,
|
||||
type_short_names: short_names,
|
||||
type_sha1s: ty::new_ty_hash(),
|
||||
type_short_names: ty::new_ty_hash(),
|
||||
tcx: tcx,
|
||||
mut_map: mut_map,
|
||||
copy_map: copy_map,
|
||||
|
|
|
@ -31,13 +31,11 @@ export ast_constr_to_constr;
|
|||
export bind_params_in_type;
|
||||
export block_ty;
|
||||
export constr;
|
||||
export cast_type;
|
||||
export constr_general;
|
||||
export constr_table;
|
||||
export count_ty_params;
|
||||
export ctxt;
|
||||
export def_has_ty_params;
|
||||
export eq_ty;
|
||||
export expr_has_ty_params;
|
||||
export expr_ty;
|
||||
export expr_ty_params_and_ty;
|
||||
|
@ -48,7 +46,6 @@ export field_idx;
|
|||
export get_field;
|
||||
export fm_general;
|
||||
export get_element_type;
|
||||
export hash_ty;
|
||||
export idx_nil;
|
||||
export is_binopable;
|
||||
export is_pred_ty;
|
||||
|
@ -104,10 +101,9 @@ export stmt_node_id;
|
|||
export sty;
|
||||
export substitute_type_params;
|
||||
export t;
|
||||
export new_ty_hash;
|
||||
export tag_variants;
|
||||
export tag_variant_with_id;
|
||||
export triv_cast;
|
||||
export triv_eq_ty;
|
||||
export ty_param_substs_opt_and_ty;
|
||||
export ty_param_kinds_and_ty;
|
||||
export ty_native_fn;
|
||||
|
@ -133,7 +129,6 @@ export ty_param;
|
|||
export ty_ptr;
|
||||
export ty_rec;
|
||||
export ty_tag;
|
||||
export ty_to_machine_ty;
|
||||
export ty_tup;
|
||||
export ty_type;
|
||||
export ty_send_type;
|
||||
|
@ -141,6 +136,7 @@ export ty_uint;
|
|||
export ty_uniq;
|
||||
export ty_var;
|
||||
export ty_named;
|
||||
export same_type, same_method;
|
||||
export ty_var_id;
|
||||
export ty_param_substs_opt_and_ty_to_monotype;
|
||||
export ty_fn_args;
|
||||
|
@ -211,20 +207,10 @@ type mt = {ty: t, mut: ast::mutability};
|
|||
// the types of AST nodes.
|
||||
type creader_cache = hashmap<{cnum: int, pos: uint, len: uint}, ty::t>;
|
||||
|
||||
type tag_var_cache =
|
||||
@smallintmap::smallintmap<@mutable [variant_info]>;
|
||||
|
||||
tag cast_type {
|
||||
/* cast may be ignored after substituting primitive with machine types
|
||||
since expr already has the right type */
|
||||
triv_cast;
|
||||
}
|
||||
|
||||
type ctxt =
|
||||
@{ts: @type_store,
|
||||
sess: session::session,
|
||||
def_map: resolve::def_map,
|
||||
cast_map: hashmap<ast::node_id, cast_type>,
|
||||
node_types: node_type_table,
|
||||
items: ast_map::map,
|
||||
freevars: freevars::freevar_map,
|
||||
|
@ -234,7 +220,7 @@ type ctxt =
|
|||
needs_drop_cache: hashmap<t, bool>,
|
||||
kind_cache: hashmap<t, ast::kind>,
|
||||
ast_ty_to_ty_cache: hashmap<@ast::ty, option::t<t>>,
|
||||
tag_var_cache: tag_var_cache};
|
||||
tag_var_cache: hashmap<ast::def_id, @[variant_info]>};
|
||||
|
||||
type ty_ctxt = ctxt;
|
||||
|
||||
|
@ -409,29 +395,31 @@ fn mk_rcache() -> creader_cache {
|
|||
ret map::mk_hashmap(hash_cache_entry, eq_cache_entries);
|
||||
}
|
||||
|
||||
fn new_ty_hash<copy V>() -> map::hashmap<t, V> { map::new_uint_hash() }
|
||||
|
||||
fn mk_ctxt(s: session::session, dm: resolve::def_map, amap: ast_map::map,
|
||||
freevars: freevars::freevar_map) -> ctxt {
|
||||
let ntt: node_type_table =
|
||||
@smallintmap::mk::<ty::ty_param_substs_opt_and_ty>();
|
||||
let tcache = new_def_hash::<ty::ty_param_kinds_and_ty>();
|
||||
fn eq_raw_ty(&&a: @raw_t, &&b: @raw_t) -> bool {
|
||||
ret a.hash == b.hash && a.struct == b.struct;
|
||||
}
|
||||
let ts = @interner::mk::<@raw_t>(hash_raw_ty, eq_raw_ty);
|
||||
let cx =
|
||||
@{ts: ts,
|
||||
sess: s,
|
||||
def_map: dm,
|
||||
cast_map: ast_util::new_node_hash(),
|
||||
node_types: ntt,
|
||||
items: amap,
|
||||
freevars: freevars,
|
||||
tcache: tcache,
|
||||
tcache: new_def_hash(),
|
||||
rcache: mk_rcache(),
|
||||
short_names_cache: map::mk_hashmap(ty::hash_ty, ty::eq_ty),
|
||||
needs_drop_cache: map::mk_hashmap(ty::hash_ty, ty::eq_ty),
|
||||
kind_cache: map::mk_hashmap(ty::hash_ty, ty::eq_ty),
|
||||
short_names_cache: new_ty_hash(),
|
||||
needs_drop_cache: new_ty_hash(),
|
||||
kind_cache: new_ty_hash(),
|
||||
ast_ty_to_ty_cache:
|
||||
map::mk_hashmap(ast_util::hash_ty, ast_util::eq_ty),
|
||||
tag_var_cache: @smallintmap::mk()};
|
||||
tag_var_cache: new_def_hash()};
|
||||
populate_type_store(cx);
|
||||
ret cx;
|
||||
}
|
||||
|
@ -1245,8 +1233,7 @@ fn type_autoderef(cx: ctxt, t: ty::t) -> ty::t {
|
|||
ret t1;
|
||||
}
|
||||
|
||||
// Type hashing. This function is private to this module (and slow); external
|
||||
// users should use `hash_ty()` instead.
|
||||
// Type hashing.
|
||||
fn hash_type_structure(st: sty) -> uint {
|
||||
fn hash_uint(id: uint, n: uint) -> uint {
|
||||
let h = id;
|
||||
|
@ -1261,7 +1248,7 @@ fn hash_type_structure(st: sty) -> uint {
|
|||
}
|
||||
fn hash_subty(id: uint, subty: t) -> uint {
|
||||
let h = id;
|
||||
h += (h << 5u) + hash_ty(subty);
|
||||
h += (h << 5u) + subty;
|
||||
ret h;
|
||||
}
|
||||
fn hash_subtys(id: uint, subtys: [t]) -> uint {
|
||||
|
@ -1296,8 +1283,8 @@ fn hash_type_structure(st: sty) -> uint {
|
|||
|
||||
fn hash_fn(id: uint, args: [arg], rty: t) -> uint {
|
||||
let h = id;
|
||||
for a: arg in args { h += (h << 5u) + hash_ty(a.ty); }
|
||||
h += (h << 5u) + hash_ty(rty);
|
||||
for a: arg in args { h += (h << 5u) + a.ty; }
|
||||
h += (h << 5u) + rty;
|
||||
ret h;
|
||||
}
|
||||
alt st {
|
||||
|
@ -1320,14 +1307,14 @@ fn hash_type_structure(st: sty) -> uint {
|
|||
ty_str. { ret 17u; }
|
||||
ty_tag(did, tys) {
|
||||
let h = hash_def(18u, did);
|
||||
for typ: t in tys { h += (h << 5u) + hash_ty(typ); }
|
||||
for typ: t in tys { h += (h << 5u) + typ; }
|
||||
ret h;
|
||||
}
|
||||
ty_box(mt) { ret hash_subty(19u, mt.ty); }
|
||||
ty_vec(mt) { ret hash_subty(21u, mt.ty); }
|
||||
ty_rec(fields) {
|
||||
let h = 26u;
|
||||
for f: field in fields { h += (h << 5u) + hash_ty(f.mt.ty); }
|
||||
for f: field in fields { h += (h << 5u) + f.mt.ty; }
|
||||
ret h;
|
||||
}
|
||||
ty_tup(ts) { ret hash_subtys(25u, ts); }
|
||||
|
@ -1366,13 +1353,6 @@ fn hash_type_structure(st: sty) -> uint {
|
|||
|
||||
fn hash_raw_ty(&&rt: @raw_t) -> uint { ret rt.hash; }
|
||||
|
||||
fn hash_ty(&&typ: t) -> uint { ret typ; }
|
||||
|
||||
|
||||
// Type equality. This function is private to this module (and slow); external
|
||||
// users should use `eq_ty()` instead.
|
||||
fn eq_int(&&x: uint, &&y: uint) -> bool { ret x == y; }
|
||||
|
||||
fn arg_eq<T>(eq: fn(T, T) -> bool, a: @sp_constr_arg<T>, b: @sp_constr_arg<T>)
|
||||
-> bool {
|
||||
alt a.node {
|
||||
|
@ -1401,6 +1381,7 @@ fn args_eq<T>(eq: fn(T, T) -> bool, a: [@sp_constr_arg<T>],
|
|||
}
|
||||
|
||||
fn constr_eq(c: @constr, d: @constr) -> bool {
|
||||
fn eq_int(&&x: uint, &&y: uint) -> bool { ret x == y; }
|
||||
ret path_to_str(c.node.path) == path_to_str(d.node.path) &&
|
||||
// FIXME: hack
|
||||
args_eq(eq_int, c.node.args, d.node.args);
|
||||
|
@ -1413,52 +1394,6 @@ fn constrs_eq(cs: [@constr], ds: [@constr]) -> bool {
|
|||
ret true;
|
||||
}
|
||||
|
||||
// This function is private to this module.
|
||||
fn eq_raw_ty(&&a: @raw_t, &&b: @raw_t) -> bool {
|
||||
ret a.hash == b.hash && a.struct == b.struct;
|
||||
}
|
||||
|
||||
|
||||
// This is the equality function the public should use. It works as long as
|
||||
// the types are interned.
|
||||
fn eq_ty(&&a: t, &&b: t) -> bool { a == b }
|
||||
|
||||
|
||||
// Convert type to machine type
|
||||
// (i.e. replace uint, int, float with target architecture machine types)
|
||||
//
|
||||
// FIXME somewhat expensive but this should only be called rarely
|
||||
fn ty_to_machine_ty(cx: ctxt, ty: t) -> t {
|
||||
fn sub_fn(cx: ctxt, uint_ty: t, int_ty: t, float_ty: t, in: t) -> t {
|
||||
alt struct(cx, in) {
|
||||
ty_uint(ast::ty_u.) { ret uint_ty; }
|
||||
ty_int(ast::ty_i.) { ret int_ty; }
|
||||
ty_float(ast::ty_f.) { ret float_ty; }
|
||||
_ { ret in; }
|
||||
}
|
||||
}
|
||||
|
||||
let cfg = cx.sess.get_targ_cfg();
|
||||
let uint_ty = mk_mach_uint(cx, cfg.uint_type);
|
||||
let int_ty = mk_mach_int(cx, cfg.int_type);
|
||||
let float_ty = mk_mach_float(cx, cfg.float_type);
|
||||
let fold_m = fm_general(bind sub_fn(cx, uint_ty, int_ty, float_ty, _));
|
||||
|
||||
ret fold_ty(cx, fold_m, ty);
|
||||
}
|
||||
|
||||
// Two types are trivially equal if they are either
|
||||
// equal or if they are equal after substituting all occurences of
|
||||
// machine independent primitive types by their machine type equivalents
|
||||
// for the current target architecture
|
||||
fn triv_eq_ty(cx: ctxt, &&a: t, &&b: t) -> bool {
|
||||
let a = alt interner::get(*cx.ts, a).struct
|
||||
{ ty_named(t, _) { t } _ { a } };
|
||||
let b = alt interner::get(*cx.ts, b).struct
|
||||
{ ty_named(t, _) { t } _ { b } };
|
||||
a == b || ty_to_machine_ty(cx, a) == ty_to_machine_ty(cx, b)
|
||||
}
|
||||
|
||||
// Type lookups
|
||||
fn node_id_to_ty_param_substs_opt_and_ty(cx: ctxt, id: ast::node_id) ->
|
||||
ty_param_substs_opt_and_ty {
|
||||
|
@ -1745,7 +1680,7 @@ mod unify {
|
|||
type var_bindings =
|
||||
{sets: ufind::ufind, types: smallintmap::smallintmap<t>};
|
||||
|
||||
type ctxt = {vb: @var_bindings, tcx: ty_ctxt};
|
||||
type ctxt = {vb: option::t<@var_bindings>, tcx: ty_ctxt};
|
||||
|
||||
fn mk_var_bindings() -> @var_bindings {
|
||||
ret @{sets: ufind::make(), types: smallintmap::mk::<t>()};
|
||||
|
@ -1754,31 +1689,32 @@ mod unify {
|
|||
// Unifies two sets.
|
||||
fn union(cx: @ctxt, set_a: uint, set_b: uint,
|
||||
variance: variance) -> union_result {
|
||||
ufind::grow(cx.vb.sets, float::max(set_a, set_b) + 1u);
|
||||
let root_a = ufind::find(cx.vb.sets, set_a);
|
||||
let root_b = ufind::find(cx.vb.sets, set_b);
|
||||
let vb = option::get(cx.vb);
|
||||
ufind::grow(vb.sets, float::max(set_a, set_b) + 1u);
|
||||
let root_a = ufind::find(vb.sets, set_a);
|
||||
let root_b = ufind::find(vb.sets, set_b);
|
||||
|
||||
let replace_type =
|
||||
bind fn (cx: @ctxt, t: t, set_a: uint, set_b: uint) {
|
||||
ufind::union(cx.vb.sets, set_a, set_b);
|
||||
let root_c: uint = ufind::find(cx.vb.sets, set_a);
|
||||
smallintmap::insert::<t>(cx.vb.types, root_c, t);
|
||||
bind fn (vb: @var_bindings, t: t, set_a: uint, set_b: uint) {
|
||||
ufind::union(vb.sets, set_a, set_b);
|
||||
let root_c: uint = ufind::find(vb.sets, set_a);
|
||||
smallintmap::insert::<t>(vb.types, root_c, t);
|
||||
}(_, _, set_a, set_b);
|
||||
|
||||
|
||||
alt smallintmap::find(cx.vb.types, root_a) {
|
||||
alt smallintmap::find(vb.types, root_a) {
|
||||
none. {
|
||||
alt smallintmap::find(cx.vb.types, root_b) {
|
||||
none. { ufind::union(cx.vb.sets, set_a, set_b); ret unres_ok; }
|
||||
some(t_b) { replace_type(cx, t_b); ret unres_ok; }
|
||||
alt smallintmap::find(vb.types, root_b) {
|
||||
none. { ufind::union(vb.sets, set_a, set_b); ret unres_ok; }
|
||||
some(t_b) { replace_type(vb, t_b); ret unres_ok; }
|
||||
}
|
||||
}
|
||||
some(t_a) {
|
||||
alt smallintmap::find(cx.vb.types, root_b) {
|
||||
none. { replace_type(cx, t_a); ret unres_ok; }
|
||||
alt smallintmap::find(vb.types, root_b) {
|
||||
none. { replace_type(vb, t_a); ret unres_ok; }
|
||||
some(t_b) {
|
||||
alt unify_step(cx, t_a, t_b, variance) {
|
||||
ures_ok(t_c) { replace_type(cx, t_c); ret unres_ok; }
|
||||
ures_ok(t_c) { replace_type(vb, t_c); ret unres_ok; }
|
||||
ures_err(terr) { ret unres_err(terr); }
|
||||
}
|
||||
}
|
||||
|
@ -1803,10 +1739,11 @@ mod unify {
|
|||
fn record_var_binding(
|
||||
cx: @ctxt, key: int, typ: t, variance: variance) -> result {
|
||||
|
||||
ufind::grow(cx.vb.sets, (key as uint) + 1u);
|
||||
let root = ufind::find(cx.vb.sets, key as uint);
|
||||
let vb = option::get(cx.vb);
|
||||
ufind::grow(vb.sets, (key as uint) + 1u);
|
||||
let root = ufind::find(vb.sets, key as uint);
|
||||
let result_type = typ;
|
||||
alt smallintmap::find::<t>(cx.vb.types, root) {
|
||||
alt smallintmap::find(vb.types, root) {
|
||||
some(old_type) {
|
||||
alt unify_step(cx, old_type, typ, variance) {
|
||||
ures_ok(unified_type) { result_type = unified_type; }
|
||||
|
@ -1815,7 +1752,7 @@ mod unify {
|
|||
}
|
||||
none. {/* fall through */ }
|
||||
}
|
||||
smallintmap::insert::<t>(cx.vb.types, root, result_type);
|
||||
smallintmap::insert::<t>(vb.types, root, result_type);
|
||||
ret ures_ok(typ);
|
||||
}
|
||||
|
||||
|
@ -2136,12 +2073,15 @@ mod unify {
|
|||
|
||||
fn unify_step(cx: @ctxt, expected: t, actual: t,
|
||||
variance: variance) -> result {
|
||||
// TODO: rewrite this using tuple pattern matching when available, to
|
||||
// FIXME: rewrite this using tuple pattern matching when available, to
|
||||
// avoid all this rightward drift and spikiness.
|
||||
// NOTE: we have tuple matching now, but that involves copying the
|
||||
// matched elements into a tuple first, which is expensive, since sty
|
||||
// holds vectors, which are currently unique
|
||||
|
||||
// Fast path.
|
||||
if expected == actual { ret ures_ok(expected); }
|
||||
|
||||
if eq_ty(expected, actual) { ret ures_ok(expected); }
|
||||
// Stage 1: Handle the cases in which one side or another is a type
|
||||
// variable.
|
||||
|
||||
|
@ -2149,6 +2089,7 @@ mod unify {
|
|||
// If the RHS is a variable type, then just do the
|
||||
// appropriate binding.
|
||||
ty::ty_var(actual_id) {
|
||||
assert option::is_some(cx.vb);
|
||||
let actual_n = actual_id as uint;
|
||||
alt struct(cx.tcx, expected) {
|
||||
ty::ty_var(expected_id) {
|
||||
|
@ -2173,8 +2114,8 @@ mod unify {
|
|||
}
|
||||
alt struct(cx.tcx, expected) {
|
||||
ty::ty_var(expected_id) {
|
||||
assert option::is_some(cx.vb);
|
||||
// Add a binding. (`actual` can't actually be a var here.)
|
||||
|
||||
alt record_var_binding_for_expected(
|
||||
cx, expected_id, actual,
|
||||
variance) {
|
||||
|
@ -2490,8 +2431,8 @@ mod unify {
|
|||
}
|
||||
}
|
||||
}
|
||||
fn unify(expected: t, actual: t, vb: @var_bindings, tcx: ty_ctxt) ->
|
||||
result {
|
||||
fn unify(expected: t, actual: t, vb: option::t<@var_bindings>,
|
||||
tcx: ty_ctxt) -> result {
|
||||
let cx = @{vb: vb, tcx: tcx};
|
||||
ret unify_step(cx, expected, actual, covariant);
|
||||
}
|
||||
|
@ -2564,6 +2505,19 @@ mod unify {
|
|||
}
|
||||
}
|
||||
|
||||
fn same_type(cx: ctxt, a: t, b: t) -> bool {
|
||||
alt unify::unify(a, b, none, cx) {
|
||||
unify::ures_ok(_) { true }
|
||||
_ { false }
|
||||
}
|
||||
}
|
||||
fn same_method(cx: ctxt, a: method, b: method) -> bool {
|
||||
a.proto == b.proto && a.ident == b.ident &&
|
||||
vec::all2(a.inputs, b.inputs,
|
||||
{|a, b| a.mode == b.mode && same_type(cx, a.ty, b.ty) }) &&
|
||||
same_type(cx, a.output, b.output) && a.cf == b.cf
|
||||
}
|
||||
|
||||
fn type_err_to_str(err: ty::type_err) -> str {
|
||||
alt err {
|
||||
terr_mismatch. { ret "types differ"; }
|
||||
|
@ -2669,45 +2623,34 @@ fn def_has_ty_params(def: ast::def) -> bool {
|
|||
// Tag information
|
||||
type variant_info = @{args: [ty::t], ctor_ty: ty::t, id: ast::def_id};
|
||||
|
||||
fn tag_variants(cx: ctxt, id: ast::def_id) -> @mutable [variant_info] {
|
||||
if ast::local_crate != id.crate {
|
||||
ret @mutable csearch::get_tag_variants(cx, id);
|
||||
}
|
||||
assert (id.node >= 0);
|
||||
alt smallintmap::find(*cx.tag_var_cache, id.node as uint) {
|
||||
option::some(variants) { ret variants; }
|
||||
fn tag_variants(cx: ctxt, id: ast::def_id) -> @[variant_info] {
|
||||
alt cx.tag_var_cache.find(id) {
|
||||
some(variants) { ret variants; }
|
||||
_ { /* fallthrough */ }
|
||||
}
|
||||
let item =
|
||||
alt cx.items.find(id.node) {
|
||||
some(i) { i }
|
||||
none. { cx.sess.bug("expected to find cached node_item") }
|
||||
};
|
||||
alt item {
|
||||
ast_map::node_item(item) {
|
||||
alt item.node {
|
||||
ast::item_tag(variants, _) {
|
||||
let result: @mutable [variant_info] = @mutable [];
|
||||
for variant: ast::variant in variants {
|
||||
let ctor_ty = node_id_to_monotype(cx, variant.node.id);
|
||||
let arg_tys: [t] = [];
|
||||
if vec::len(variant.node.args) > 0u {
|
||||
for a: arg in ty_fn_args(cx, ctor_ty) {
|
||||
arg_tys += [a.ty];
|
||||
}
|
||||
}
|
||||
let did = variant.node.id;
|
||||
*result +=
|
||||
[@{args: arg_tys,
|
||||
ctor_ty: ctor_ty,
|
||||
id: ast_util::local_def(did)}];
|
||||
let result = if ast::local_crate != id.crate {
|
||||
@csearch::get_tag_variants(cx, id)
|
||||
} else {
|
||||
alt cx.items.get(id.node) {
|
||||
ast_map::node_item(item) {
|
||||
alt item.node {
|
||||
ast::item_tag(variants, _) {
|
||||
@vec::map(variants, {|variant|
|
||||
let ctor_ty = node_id_to_monotype(cx, variant.node.id);
|
||||
let arg_tys = if vec::len(variant.node.args) > 0u {
|
||||
vec::map(ty_fn_args(cx, ctor_ty), {|a| a.ty})
|
||||
} else { [] };
|
||||
@{args: arg_tys,
|
||||
ctor_ty: ctor_ty,
|
||||
id: ast_util::local_def(variant.node.id)}
|
||||
})
|
||||
}
|
||||
}
|
||||
smallintmap::insert(*cx.tag_var_cache, id.node as uint, result);
|
||||
ret result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
cx.tag_var_cache.insert(id, result);
|
||||
result
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -791,7 +791,8 @@ mod collect {
|
|||
mod unify {
|
||||
fn unify(fcx: @fn_ctxt, expected: ty::t, actual: ty::t) ->
|
||||
ty::unify::result {
|
||||
ret ty::unify::unify(expected, actual, fcx.var_bindings, fcx.ccx.tcx);
|
||||
ret ty::unify::unify(expected, actual, some(fcx.var_bindings),
|
||||
fcx.ccx.tcx);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1106,7 +1107,7 @@ fn gather_locals(ccx: @crate_ctxt,
|
|||
alt ty_opt {
|
||||
none. {/* nothing to do */ }
|
||||
some(typ) {
|
||||
ty::unify::unify(ty::mk_var(tcx, var_id), typ, vb, tcx);
|
||||
ty::unify::unify(ty::mk_var(tcx, var_id), typ, some(vb), tcx);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1198,8 +1199,8 @@ fn check_pat(fcx: @fn_ctxt, map: ast_util::pat_id_map, pat: @ast::pat,
|
|||
check_expr_with(fcx, end, expected);
|
||||
let b_ty = resolve_type_vars_if_possible(fcx, expr_ty(fcx.ccx.tcx,
|
||||
begin));
|
||||
if b_ty != resolve_type_vars_if_possible(fcx, expr_ty(fcx.ccx.tcx,
|
||||
end)) {
|
||||
if !ty::same_type(fcx.ccx.tcx, b_ty, resolve_type_vars_if_possible(
|
||||
fcx, expr_ty(fcx.ccx.tcx, end))) {
|
||||
fcx.ccx.tcx.sess.span_err(pat.span, "mismatched types in range");
|
||||
} else if !ty::type_is_numeric(fcx.ccx.tcx, b_ty) {
|
||||
fcx.ccx.tcx.sess.span_err(pat.span,
|
||||
|
@ -1850,21 +1851,8 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
|
|||
}
|
||||
ast::expr_be(e) {
|
||||
// FIXME: prove instead of assert
|
||||
assert (ast_util::is_tail_call_expr(e));
|
||||
assert (ast_util::is_call_expr(e));
|
||||
check_expr_with(fcx, e, fcx.ret_ty);
|
||||
|
||||
alt e.node {
|
||||
ast::expr_cast(_, _) {
|
||||
alt tcx.cast_map.find(e.id) {
|
||||
option::some(ty::triv_cast.) { }
|
||||
_ { tcx.sess.span_err(expr.span,
|
||||
"non-trivial cast of tail-call return value");
|
||||
}
|
||||
}
|
||||
}
|
||||
_ { /* regular tail call */ }
|
||||
}
|
||||
|
||||
bot = true;
|
||||
write::nil_ty(tcx, id);
|
||||
}
|
||||
|
@ -2066,19 +2054,19 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
|
|||
ast::expr_cast(e, t) {
|
||||
bot = check_expr(fcx, e);
|
||||
let t_1 = ast_ty_to_ty_crate(fcx.ccx, t);
|
||||
let t_e = expr_ty(tcx, e);
|
||||
let t_e = ty::expr_ty(tcx, e);
|
||||
|
||||
if ty::type_is_nil(tcx, t_e) {
|
||||
tcx.sess.span_err(expr.span,
|
||||
"cast from nil: " +
|
||||
ty_to_str(tcx, expr_ty(tcx, e)) + " as " +
|
||||
ty_to_str(tcx, t_e) + " as " +
|
||||
ty_to_str(tcx, t_1));
|
||||
}
|
||||
|
||||
if ty::type_is_nil(tcx, t_1) {
|
||||
tcx.sess.span_err(expr.span,
|
||||
"cast to nil: " +
|
||||
ty_to_str(tcx, expr_ty(tcx, e)) + " as " +
|
||||
ty_to_str(tcx, t_e) + " as " +
|
||||
ty_to_str(tcx, t_1));
|
||||
}
|
||||
|
||||
|
@ -2087,14 +2075,9 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
|
|||
&& type_is_scalar(fcx, expr.span, t_1)) {
|
||||
tcx.sess.span_err(expr.span,
|
||||
"non-scalar cast: " +
|
||||
ty_to_str(tcx, expr_ty(tcx, e)) + " as " +
|
||||
ty_to_str(tcx, t_e) + " as " +
|
||||
ty_to_str(tcx, t_1));
|
||||
}
|
||||
|
||||
// mark as triv_cast for later dropping in trans
|
||||
if ty::triv_eq_ty(tcx, t_1, t_e)
|
||||
{ tcx.cast_map.insert(expr.id, ty::triv_cast); }
|
||||
|
||||
write::ty_only_fixup(fcx, id, t_1);
|
||||
}
|
||||
ast::expr_vec(args, mut) {
|
||||
|
@ -2342,7 +2325,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
|
|||
// We'd better be overriding with one of the same
|
||||
// type. Check to make sure.
|
||||
let new_type = ty_of_method(ccx.tcx, m_check, om);
|
||||
if new_type != m {
|
||||
if !ty::same_method(ccx.tcx, new_type, m) {
|
||||
ccx.tcx.sess.span_fatal
|
||||
(om.span, "attempted to override method "
|
||||
+ m.ident + " with one of a different type");
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import core::{str, option, int};
|
||||
import std::map;
|
||||
import codemap::span;
|
||||
import ast::*;
|
||||
|
||||
|
@ -7,13 +5,6 @@ fn respan<copy T>(sp: span, t: T) -> spanned<T> {
|
|||
ret {node: t, span: sp};
|
||||
}
|
||||
|
||||
fn new_node_hash<copy V>() -> map::hashmap<node_id, V> {
|
||||
fn node_id_hash(&&i: node_id) -> uint { ret int::hash(i as int); }
|
||||
fn node_id_eq(&&a: node_id, &&b: node_id) -> bool
|
||||
{ ret int::eq(a as int, b as int); }
|
||||
ret map::mk_hashmap(node_id_hash, node_id_eq);
|
||||
}
|
||||
|
||||
/* assuming that we're not in macro expansion */
|
||||
fn mk_sp(lo: uint, hi: uint) -> span {
|
||||
ret {lo: lo, hi: hi, expanded_from: codemap::os_none};
|
||||
|
@ -198,14 +189,6 @@ pure fn is_call_expr(e: @expr) -> bool {
|
|||
alt e.node { expr_call(_, _, _) { true } _ { false } }
|
||||
}
|
||||
|
||||
pure fn is_tail_call_expr(e: @expr) -> bool {
|
||||
alt e.node {
|
||||
expr_call(_, _, _) { true }
|
||||
expr_cast(inner_e, _) { is_call_expr(inner_e) }
|
||||
_ { false }
|
||||
}
|
||||
}
|
||||
|
||||
fn is_constraint_arg(e: @expr) -> bool {
|
||||
alt e.node {
|
||||
expr_lit(_) { ret true; }
|
||||
|
|
|
@ -961,7 +961,7 @@ fn parse_bottom_expr(p: parser) -> @ast::expr {
|
|||
let e = parse_expr(p);
|
||||
|
||||
// FIXME: Is this the right place for this check?
|
||||
if /*check*/ ast_util::is_tail_call_expr(e) {
|
||||
if /*check*/ast_util::is_call_expr(e) {
|
||||
hi = e.span.hi;
|
||||
ex = ast::expr_be(e);
|
||||
} else { p.fatal("Non-call expression in tail call"); }
|
||||
|
|
|
@ -482,7 +482,7 @@ Function: acos
|
|||
Returns the arccosine of an angle (measured in rad)
|
||||
*/
|
||||
pure fn acos(x: float) -> float
|
||||
{ be m_float::acos(x as m_float) as float }
|
||||
{ ret m_float::acos(x as m_float) as float }
|
||||
|
||||
/*
|
||||
Function: asin
|
||||
|
@ -490,7 +490,7 @@ Function: asin
|
|||
Returns the arcsine of an angle (measured in rad)
|
||||
*/
|
||||
pure fn asin(x: float) -> float
|
||||
{ be m_float::asin(x as m_float) as float }
|
||||
{ ret m_float::asin(x as m_float) as float }
|
||||
|
||||
/*
|
||||
Function: atan
|
||||
|
@ -498,7 +498,7 @@ Function: atan
|
|||
Returns the arctangents of an angle (measured in rad)
|
||||
*/
|
||||
pure fn atan(x: float) -> float
|
||||
{ be m_float::atan(x as m_float) as float }
|
||||
{ ret m_float::atan(x as m_float) as float }
|
||||
|
||||
|
||||
/*
|
||||
|
@ -507,7 +507,7 @@ Function: atan2
|
|||
Returns the arctangent of an angle (measured in rad)
|
||||
*/
|
||||
pure fn atan2(y: float, x: float) -> float
|
||||
{ be m_float::atan2(y as m_float, x as m_float) as float }
|
||||
{ ret m_float::atan2(y as m_float, x as m_float) as float }
|
||||
|
||||
/*
|
||||
Function: ceil
|
||||
|
@ -515,7 +515,7 @@ Function: ceil
|
|||
Returns the smallest integral value less than or equal to `n`
|
||||
*/
|
||||
pure fn ceil(n: float) -> float
|
||||
{ be m_float::ceil(n as m_float) as float }
|
||||
{ ret m_float::ceil(n as m_float) as float }
|
||||
|
||||
/*
|
||||
Function: cos
|
||||
|
@ -523,7 +523,7 @@ Function: cos
|
|||
Returns the cosine of an angle `x` (measured in rad)
|
||||
*/
|
||||
pure fn cos(x: float) -> float
|
||||
{ be m_float::cos(x as m_float) as float }
|
||||
{ ret m_float::cos(x as m_float) as float }
|
||||
|
||||
/*
|
||||
Function: cosh
|
||||
|
@ -532,7 +532,7 @@ Returns the hyperbolic cosine of `x`
|
|||
|
||||
*/
|
||||
pure fn cosh(x: float) -> float
|
||||
{ be m_float::cosh(x as m_float) as float }
|
||||
{ ret m_float::cosh(x as m_float) as float }
|
||||
|
||||
|
||||
/*
|
||||
|
@ -541,7 +541,7 @@ Function: exp
|
|||
Returns `consts::e` to the power of `n*
|
||||
*/
|
||||
pure fn exp(n: float) -> float
|
||||
{ be m_float::exp(n as m_float) as float }
|
||||
{ ret m_float::exp(n as m_float) as float }
|
||||
|
||||
/*
|
||||
Function: abs
|
||||
|
@ -549,7 +549,7 @@ Function: abs
|
|||
Returns the absolute value of `n`
|
||||
*/
|
||||
pure fn abs(n: float) -> float
|
||||
{ be m_float::abs(n as m_float) as float }
|
||||
{ ret m_float::abs(n as m_float) as float }
|
||||
|
||||
/*
|
||||
Function: floor
|
||||
|
@ -557,7 +557,7 @@ Function: floor
|
|||
Returns the largest integral value less than or equal to `n`
|
||||
*/
|
||||
pure fn floor(n: float) -> float
|
||||
{ be m_float::floor(n as m_float) as float }
|
||||
{ ret m_float::floor(n as m_float) as float }
|
||||
|
||||
/*
|
||||
Function: fmod
|
||||
|
@ -565,7 +565,7 @@ Function: fmod
|
|||
Returns the floating-point remainder of `x/y`
|
||||
*/
|
||||
pure fn fmod(x: float, y: float) -> float
|
||||
{ be m_float::fmod(x as m_float, y as m_float) as float }
|
||||
{ ret m_float::fmod(x as m_float, y as m_float) as float }
|
||||
|
||||
/*
|
||||
Function: ln
|
||||
|
@ -573,7 +573,7 @@ Function: ln
|
|||
Returns the natural logaritm of `n`
|
||||
*/
|
||||
pure fn ln(n: float) -> float
|
||||
{ be m_float::ln(n as m_float) as float }
|
||||
{ ret m_float::ln(n as m_float) as float }
|
||||
|
||||
/*
|
||||
Function: ldexp
|
||||
|
@ -581,7 +581,7 @@ Function: ldexp
|
|||
Returns `x` multiplied by 2 to the power of `n`
|
||||
*/
|
||||
pure fn ldexp(n: float, i: int) -> float
|
||||
{ be m_float::ldexp(n as m_float, i as c_int) as float }
|
||||
{ ret m_float::ldexp(n as m_float, i as c_int) as float }
|
||||
|
||||
/*
|
||||
Function: ln1p
|
||||
|
@ -590,7 +590,7 @@ Returns the natural logarithm of `1+n` accurately,
|
|||
even for very small values of `n`
|
||||
*/
|
||||
pure fn ln1p(n: float) -> float
|
||||
{ be m_float::ln1p(n as m_float) as float }
|
||||
{ ret m_float::ln1p(n as m_float) as float }
|
||||
|
||||
/*
|
||||
Function: log10
|
||||
|
@ -598,7 +598,7 @@ Function: log10
|
|||
Returns the logarithm to base 10 of `n`
|
||||
*/
|
||||
pure fn log10(n: float) -> float
|
||||
{ be m_float::log10(n as m_float) as float }
|
||||
{ ret m_float::log10(n as m_float) as float }
|
||||
|
||||
/*
|
||||
Function: log2
|
||||
|
@ -606,7 +606,7 @@ Function: log2
|
|||
Returns the logarithm to base 2 of `n`
|
||||
*/
|
||||
pure fn log2(n: float) -> float
|
||||
{ be m_float::log2(n as m_float) as float }
|
||||
{ ret m_float::log2(n as m_float) as float }
|
||||
|
||||
/*
|
||||
Function: modf
|
||||
|
@ -622,7 +622,7 @@ The fractional part of `n`
|
|||
*/
|
||||
#[no(warn_trivial_casts)] // FIXME Implement
|
||||
pure fn modf(n: float, &iptr: float) -> float { unsafe {
|
||||
be m_float::modf(n as m_float, ptr::addr_of(iptr) as *m_float) as float
|
||||
ret m_float::modf(n as m_float, ptr::addr_of(iptr) as *m_float) as float
|
||||
} }
|
||||
|
||||
/*
|
||||
|
@ -640,13 +640,13 @@ Returns:
|
|||
The fractional part of `n`
|
||||
*/
|
||||
pure fn frexp(n: float, &exp: c_int) -> float
|
||||
{ be m_float::frexp(n as m_float, exp) as float }
|
||||
{ ret m_float::frexp(n as m_float, exp) as float }
|
||||
|
||||
/*
|
||||
Function: pow
|
||||
*/
|
||||
pure fn pow(v: float, e: float) -> float
|
||||
{ be m_float::pow(v as m_float, e as m_float) as float }
|
||||
{ ret m_float::pow(v as m_float, e as m_float) as float }
|
||||
|
||||
|
||||
/*
|
||||
|
@ -656,7 +656,7 @@ Returns the integral value nearest to `x` (according to the
|
|||
prevailing rounding mode) in floating-point format
|
||||
*/
|
||||
pure fn rint(x: float) -> float
|
||||
{ be m_float::rint(x as m_float) as float }
|
||||
{ ret m_float::rint(x as m_float) as float }
|
||||
|
||||
/*
|
||||
Function: round
|
||||
|
@ -666,7 +666,7 @@ Return the integral value nearest to `x` rounding half-way
|
|||
cases away from zero, regardless of the current rounding direction.
|
||||
*/
|
||||
pure fn round(x: float) -> float
|
||||
{ be m_float::round(x as m_float) as float }
|
||||
{ ret m_float::round(x as m_float) as float }
|
||||
|
||||
/*
|
||||
Function: sin
|
||||
|
@ -674,7 +674,7 @@ Function: sin
|
|||
Returns the sine of an angle `x` (measured in rad)
|
||||
*/
|
||||
pure fn sin(x: float) -> float
|
||||
{ be m_float::sin(x as m_float) as float }
|
||||
{ ret m_float::sin(x as m_float) as float }
|
||||
|
||||
/*
|
||||
Function: sinh
|
||||
|
@ -682,7 +682,7 @@ Function: sinh
|
|||
Returns the hyperbolic sine of an angle `x` (measured in rad)
|
||||
*/
|
||||
pure fn sinh(x: float) -> float
|
||||
{ be m_float::sinh(x as m_float) as float }
|
||||
{ ret m_float::sinh(x as m_float) as float }
|
||||
|
||||
/*
|
||||
Function: sqrt
|
||||
|
@ -690,7 +690,7 @@ Function: sqrt
|
|||
Returns the square root of `x`
|
||||
*/
|
||||
pure fn sqrt(x: float) -> float
|
||||
{ be m_float::sqrt(x as m_float) as float }
|
||||
{ ret m_float::sqrt(x as m_float) as float }
|
||||
|
||||
/*
|
||||
Function: tan
|
||||
|
@ -699,7 +699,7 @@ Returns the tangent of an angle `x` (measured in rad)
|
|||
|
||||
*/
|
||||
pure fn tan(x: float) -> float
|
||||
{ be m_float::tan(x as m_float) as float }
|
||||
{ ret m_float::tan(x as m_float) as float }
|
||||
|
||||
/*
|
||||
Function: tanh
|
||||
|
@ -708,7 +708,7 @@ Returns the hyperbolic tangent of an angle `x` (measured in rad)
|
|||
|
||||
*/
|
||||
pure fn tanh(x: float) -> float
|
||||
{ be m_float::tanh(x as m_float) as float }
|
||||
{ ret m_float::tanh(x as m_float) as float }
|
||||
|
||||
/*
|
||||
Function: trunc
|
||||
|
@ -717,7 +717,7 @@ Returns the integral value nearest to but no larger in magnitude than `x`
|
|||
|
||||
*/
|
||||
pure fn trunc(x: float) -> float
|
||||
{ be m_float::trunc(x as m_float) as float }
|
||||
{ ret m_float::trunc(x as m_float) as float }
|
||||
|
||||
//
|
||||
// Local Variables:
|
||||
|
|
|
@ -34,6 +34,8 @@ tag json {
|
|||
list(@[json]);
|
||||
/* Variant: dict */
|
||||
dict(map::hashmap<str,json>);
|
||||
/* Variant: null */
|
||||
null;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -63,6 +65,7 @@ fn to_str(j: json) -> str {
|
|||
});
|
||||
str::concat(["{ ", str::connect(parts, ", "), " }"])
|
||||
}
|
||||
null { "null" }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -233,6 +236,14 @@ fn from_str_bool(s: str) -> (option::t<json>, str) {
|
|||
}
|
||||
}
|
||||
|
||||
fn from_str_null(s: str) -> (option::t<json>, str) {
|
||||
if (str::starts_with(s, "null")) {
|
||||
(some(null), str::slice(s, 4u, str::byte_len(s)))
|
||||
} else {
|
||||
(none, s)
|
||||
}
|
||||
}
|
||||
|
||||
fn from_str_helper(s: str) -> (option::t<json>, str) {
|
||||
let s = str::trim_left(s);
|
||||
if str::is_empty(s) { ret (none, s); }
|
||||
|
@ -243,6 +254,7 @@ fn from_str_helper(s: str) -> (option::t<json>, str) {
|
|||
'{' { from_str_dict(s) }
|
||||
'0' to '9' | '-' | '+' | '.' { from_str_float(s) }
|
||||
't' | 'f' { from_str_bool(s) }
|
||||
'n' { from_str_null(s) }
|
||||
_ { ret (none, s); }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
// error-pattern: non-trivial cast of tail-call return value
|
||||
import core::mtypes::*;
|
||||
|
||||
fn foo_float() -> m_float { ret 0.0 as m_float; }
|
||||
fn bar_float() -> bool { be foo_float() as bool; }
|
||||
|
||||
fn foo_int() -> m_int { ret 0 as m_int; }
|
||||
fn bar_int() -> bool { be foo_int() as bool; }
|
||||
|
||||
fn foo_uint() -> m_uint { ret 0u as m_uint; }
|
||||
fn bar_uint() -> bool { be foo_uint() as bool; }
|
||||
|
||||
fn main() {
|
||||
assert bar_float() == 0.0;
|
||||
assert bar_int() == 0.0;
|
||||
assert bar_uint() == 0.0;
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
import core::ctypes::*;
|
||||
|
||||
import core::mtypes::m_float;
|
||||
import core::mtypes::m_int;
|
||||
import core::mtypes::m_uint;
|
||||
|
||||
fn foo_float() -> m_float { ret 0.0 as m_float; }
|
||||
fn bar_float() -> float { be foo_float() as float; }
|
||||
|
||||
fn foo_int() -> m_int { ret 0 as m_int; }
|
||||
fn bar_int() -> int { be foo_int() as int; }
|
||||
|
||||
fn foo_uint() -> m_uint { ret 0u as m_uint; }
|
||||
fn bar_uint() -> uint { be foo_uint() as uint; }
|
||||
|
||||
fn foo_long() -> long { ret 0 as long; }
|
||||
fn bar_long() -> int { be foo_long() as int; }
|
||||
|
||||
fn foo_ulong() -> ulong { ret 0u as ulong; }
|
||||
fn bar_ulong() -> uint { be foo_uint() as uint; }
|
||||
|
||||
fn main() {
|
||||
assert bar_float() == 0.0;
|
||||
assert bar_int() == 0;
|
||||
assert bar_uint() == 0u;
|
||||
assert bar_long() == 0;
|
||||
assert bar_ulong() == 0u;
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
import core::mtypes::m_int;
|
||||
|
||||
// This will be more interesting once there is support
|
||||
// for consts that refer to other consts, i.e. math_f64::consts::pi as m_float
|
||||
#[cfg(target_arch="x86")]
|
||||
const foo: m_int = 0i32 as m_int;
|
||||
|
||||
#[cfg(target_arch="x86_64")]
|
||||
const foo: m_int = 0i64 as m_int;
|
||||
|
||||
fn main() {
|
||||
assert foo == 0 as m_int;
|
||||
}
|
|
@ -5,6 +5,11 @@ import option;
|
|||
import std::json::*;
|
||||
import option::{none, some};
|
||||
|
||||
#[test]
|
||||
fn test_from_str_null() {
|
||||
assert(from_str("null") == some(null));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_str_num() {
|
||||
assert(from_str("3") == some(num(3f)));
|
||||
|
@ -31,6 +36,7 @@ fn test_from_str_bool() {
|
|||
fn test_from_str_list() {
|
||||
assert(from_str("[]") == some(list(@[])));
|
||||
assert(from_str("[true]") == some(list(@[boolean(true)])));
|
||||
assert(from_str("[null]") == some(list(@[null])));
|
||||
assert(from_str("[3, 1]") == some(list(@[num(3f), num(1f)])));
|
||||
assert(from_str("[2, [4, 1]]") ==
|
||||
some(list(@[num(2f), list(@[num(4f), num(1f)])])));
|
||||
|
@ -44,6 +50,7 @@ fn test_from_str_list() {
|
|||
fn test_from_str_dict() {
|
||||
assert(from_str("{}") != none);
|
||||
assert(from_str("{\"a\": 3}") != none);
|
||||
assert(from_str("{\"a\": null}") != none);
|
||||
assert(from_str("{\"a\": }") == none);
|
||||
assert(from_str("{\"a\" }") == none);
|
||||
assert(from_str("{\"a\"") == none);
|
||||
|
|
|
@ -15,6 +15,12 @@ fn test_from_vec() {
|
|||
assert (head(tail(tail(l))) == 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_vec_empty() {
|
||||
let empty : list::list<int> = from_vec([]);
|
||||
assert (empty == list::nil::<int>);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_vec_mut() {
|
||||
let l = from_vec([mutable 0, 1, 2]);
|
||||
|
@ -25,10 +31,11 @@ fn test_from_vec_mut() {
|
|||
|
||||
#[test]
|
||||
fn test_foldl() {
|
||||
let l = from_vec([0, 1, 2, 3, 4]);
|
||||
fn add(&&a: uint, &&b: int) -> uint { ret a + (b as uint); }
|
||||
let rs = list::foldl(l, 0u, add);
|
||||
assert (rs == 10u);
|
||||
let l = from_vec([0, 1, 2, 3, 4]);
|
||||
let empty = list::nil::<int>;
|
||||
assert (list::foldl(l, 0u, add) == 10u);
|
||||
assert (list::foldl(empty, 0u, add) == 0u);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -37,26 +44,25 @@ fn test_foldl2() {
|
|||
a - b
|
||||
}
|
||||
let l = from_vec([1, 2, 3, 4]);
|
||||
let sum = list::foldl(l, 0, sub);
|
||||
assert sum == -10;
|
||||
assert (list::foldl(l, 0, sub) == -10);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_find_success() {
|
||||
let l = from_vec([0, 1, 2]);
|
||||
fn match(&&i: int) -> option::t<int> {
|
||||
ret if i == 2 { option::some(i) } else { option::none::<int> };
|
||||
}
|
||||
let rs = list::find(l, match);
|
||||
assert (rs == option::some(2));
|
||||
let l = from_vec([0, 1, 2]);
|
||||
assert (list::find(l, match) == option::some(2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_find_fail() {
|
||||
let l = from_vec([0, 1, 2]);
|
||||
fn match(&&_i: int) -> option::t<int> { ret option::none::<int>; }
|
||||
let rs = list::find(l, match);
|
||||
assert (rs == option::none::<int>);
|
||||
let l = from_vec([0, 1, 2]);
|
||||
let empty = list::nil::<int>;
|
||||
assert (list::find(l, match) == option::none::<int>);
|
||||
assert (list::find(empty, match) == option::none::<int>);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -72,6 +78,8 @@ fn test_has() {
|
|||
#[test]
|
||||
fn test_len() {
|
||||
let l = from_vec([0, 1, 2]);
|
||||
let empty = list::nil::<int>;
|
||||
assert (list::len(l) == 3u);
|
||||
assert (list::len(empty) == 0u);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue