1
Fork 0

Tuple types back, not constructable yet

This commit is contained in:
Marijn Haverbeke 2011-08-15 11:40:26 +02:00
parent 25b85df370
commit 9538b00363
17 changed files with 278 additions and 16 deletions

View file

@ -236,6 +236,13 @@ fn parse_ty(st: @pstate, sd: str_def) -> ty::t {
st.pos = st.pos + 1u; st.pos = st.pos + 1u;
ret ty::mk_rec(st.tcx, fields); ret ty::mk_rec(st.tcx, fields);
} }
'T' {
assert (next(st) as char == '[');
let params = ~[];
while peek(st) as char != ']' { params += ~[parse_mt(st, sd)]; }
st.pos = st.pos + 1u;
ret ty::mk_tup(st.tcx, params);
}
'F' { 'F' {
let func = parse_ty_fn(st, sd); let func = parse_ty_fn(st, sd);
ret ty::mk_fn(st.tcx, ast::proto_fn, func.args, func.ty, func.cf, ret ty::mk_fn(st.tcx, ast::proto_fn, func.args, func.ty, func.cf,

View file

@ -120,6 +120,11 @@ fn enc_sty(w: &io::writer, cx: &@ctxt, st: &ty::sty) {
for t: ty::t in tys { enc_ty(w, cx, t); } for t: ty::t in tys { enc_ty(w, cx, t); }
w.write_char(']'); w.write_char(']');
} }
ty::ty_tup(mts) {
w.write_str("T[");
for mt in mts { enc_mt(w, cx, mt); }
w.write_char(']');
}
ty::ty_box(mt) { w.write_char('@'); enc_mt(w, cx, mt); } ty::ty_box(mt) { w.write_char('@'); enc_mt(w, cx, mt); }
ty::ty_uniq(t) { w.write_char('~'); enc_ty(w, cx, t); } ty::ty_uniq(t) { w.write_char('~'); enc_ty(w, cx, t); }
ty::ty_ptr(mt) { w.write_char('*'); enc_mt(w, cx, mt); } ty::ty_ptr(mt) { w.write_char('*'); enc_mt(w, cx, mt); }

View file

@ -678,6 +678,14 @@ fn ty_can_unsafely_include(cx: &ctx, needle: ty::t, haystack: ty::t,
} }
ret false; ret false;
} }
ty::ty_tup(mts) {
for mt in mts {
if helper(tcx, needle, mt.ty, get_mut(mut, mt)) {
ret true;
}
}
ret false;
}
// These may contain anything. // These may contain anything.
ty::ty_fn(_, _, _, _, _) { ty::ty_fn(_, _, _, _, _) {

View file

@ -46,6 +46,12 @@ fn type_is_gc_relevant(cx: &ty::ctxt, ty: &ty::t) -> bool {
} }
ret false; ret false;
} }
ty::ty_tup(elts) {
for elt in elts {
if type_is_gc_relevant(cx, elt.ty) { ret true; }
}
ret false;
}
ty::ty_tag(did, tps) { ty::ty_tag(did, tps) {
let variants = ty::tag_variants(cx, did); let variants = ty::tag_variants(cx, did);

View file

@ -371,6 +371,12 @@ fn shape_of(ccx : &@crate_ctxt, t : ty::t) -> [u8] {
for f : field in fields { sub += shape_of(ccx, f.mt.ty); } for f : field in fields { sub += shape_of(ccx, f.mt.ty); }
add_substr(s, sub); add_substr(s, sub);
} }
ty::ty_tup(elts) {
s += ~[shape_struct];
let sub = ~[];
for elt in elts { sub += shape_of(ccx, elt.ty); }
add_substr(s, sub);
}
ty::ty_fn(_,_,_,_,_) { s += ~[shape_fn]; } ty::ty_fn(_,_,_,_,_) { s += ~[shape_fn]; }
ty::ty_native_fn(_,_,_) { s += ~[shape_u32]; } ty::ty_native_fn(_,_,_) { s += ~[shape_u32]; }

View file

@ -253,6 +253,13 @@ fn type_of_inner(cx: &@crate_ctxt, sp: &span, t: &ty::t) -> TypeRef {
} }
ty::ty_param(_, _) { llty = T_typaram(cx.tn); } ty::ty_param(_, _) { llty = T_typaram(cx.tn); }
ty::ty_type. { llty = T_ptr(cx.tydesc_type); } ty::ty_type. { llty = T_ptr(cx.tydesc_type); }
ty::ty_tup(elts) {
let tys = ~[];
for elt in elts {
tys += ~[type_of_inner(cx, sp, elt.ty)];
}
llty = T_struct(tys);
}
} }
assert (llty as int != 0); assert (llty as int != 0);
cx.lltypes.insert(t, llty); cx.lltypes.insert(t, llty);
@ -577,6 +584,11 @@ fn dynamic_size_of(cx: &@block_ctxt, t: ty::t) -> result {
for f: ty::field in flds { tys += ~[f.mt.ty]; } for f: ty::field in flds { tys += ~[f.mt.ty]; }
ret align_elements(cx, tys); ret align_elements(cx, tys);
} }
ty::ty_tup(elts) {
let tys = ~[];
for mt in elts { tys += ~[mt.ty]; }
ret align_elements(cx, tys);
}
ty::ty_tag(tid, tps) { ty::ty_tag(tid, tps) {
let bcx = cx; let bcx = cx;
// Compute max(variant sizes). // Compute max(variant sizes).
@ -645,6 +657,16 @@ fn dynamic_align_of(cx: &@block_ctxt, t: &ty::t) -> result {
let llalign = umax(bcx, llalign_of(T_int()), llunitalign); let llalign = umax(bcx, llalign_of(T_int()), llunitalign);
ret rslt(bcx, llalign); ret rslt(bcx, llalign);
} }
ty::ty_tup(elts) {
let a = C_int(1);
let bcx = cx;
for e in elts {
let align = align_of(bcx, e.ty);
bcx = align.bcx;
a = umax(bcx, a, align.val);
}
ret rslt(bcx, a);
}
} }
} }
@ -1819,6 +1841,16 @@ fn iter_structural_ty_full(cx: &@block_ctxt, av: ValueRef, t: &ty::t,
i += 1; i += 1;
} }
} }
ty::ty_tup(args) {
let i = 0;
for arg in args {
r = GEP_tup_like(r.bcx, t, av, ~[0, i]);
let llfld_a = r.val;
r = f(r.bcx, load_if_immediate(r.bcx, llfld_a, arg.ty),
arg.ty);
i += 1;
}
}
ty::ty_res(_, inner, tps) { ty::ty_res(_, inner, tps) {
let tcx = bcx_tcx(cx); let tcx = bcx_tcx(cx);
let inner1 = ty::substitute_type_params(tcx, tps, inner); let inner1 = ty::substitute_type_params(tcx, tps, inner);
@ -4737,6 +4769,26 @@ fn trans_call(cx: &@block_ctxt, f: &@ast::expr,
ret rslt(bcx, retval); ret rslt(bcx, retval);
} }
fn trans_tup(cx: &@block_ctxt, elts: &[ast::elt], id: ast::node_id)
-> result {
let bcx = cx;
let t = node_id_type(bcx.fcx.lcx.ccx, id);
let tup_res = alloc_ty(bcx, t);
let tup_val = tup_res.val;
bcx = tup_res.bcx;
add_clean_temp(cx, tup_val, t);
let i: int = 0;
for e in elts {
let e_ty = ty::expr_ty(cx.fcx.lcx.ccx.tcx, e.expr);
let src = trans_lval(bcx, e.expr);
bcx = src.res.bcx;
let dst_res = GEP_tup_like(bcx, t, tup_val, ~[0, i]);
bcx = move_val_if_temp(dst_res.bcx, INIT, dst_res.val, src, e_ty).bcx;
i += 1;
}
ret rslt(bcx, tup_val);
}
fn trans_vec(cx: &@block_ctxt, args: &[@ast::expr], id: ast::node_id) -> fn trans_vec(cx: &@block_ctxt, args: &[@ast::expr], id: ast::node_id) ->
result { result {
let t = node_id_type(bcx_ccx(cx), id); let t = node_id_type(bcx_ccx(cx), id);
@ -5085,6 +5137,7 @@ fn trans_expr_out(cx: &@block_ctxt, e: &@ast::expr, output: out_method) ->
ret trans_ivec(cx, args, e.id); ret trans_ivec(cx, args, e.id);
} }
ast::expr_rec(args, base) { ret trans_rec(cx, args, base, e.id); } ast::expr_rec(args, base) { ret trans_rec(cx, args, base, e.id); }
ast::expr_tup(args) { ret trans_tup(cx, args, e.id); }
ast::expr_mac(_) { ret bcx_ccx(cx).sess.bug("unexpanded macro"); } ast::expr_mac(_) { ret bcx_ccx(cx).sess.bug("unexpanded macro"); }
ast::expr_fail(expr) { ret trans_fail_expr(cx, some(e.span), expr); } ast::expr_fail(expr) { ret trans_fail_expr(cx, some(e.span), expr); }
ast::expr_log(lvl, a) { ret trans_log(lvl, cx, a); } ast::expr_log(lvl, a) { ret trans_log(lvl, cx, a); }

View file

@ -174,9 +174,9 @@ fn mk_spawn_wrapper(cx: &@block_ctxt, func: &@ast::expr, args_ty: &ty::t) ->
// unpack the arguments // unpack the arguments
alt ty::struct(fcx.lcx.ccx.tcx, args_ty) { alt ty::struct(fcx.lcx.ccx.tcx, args_ty) {
ty::ty_rec(fields) { ty::ty_tup(elts) {
let i = 0; let i = 0;
for f: ty::field in fields { for elt in elts {
let src = fbcx.build.GEP(arg, ~[C_int(0), C_int(i)]); let src = fbcx.build.GEP(arg, ~[C_int(0), C_int(i)]);
i += 1; i += 1;
let child_arg = fbcx.build.Load(src); let child_arg = fbcx.build.Load(src);

View file

@ -404,6 +404,9 @@ fn find_pre_post_expr(fcx: &fn_ctxt, e: @expr) {
alt maybe_base { none. {/* no-op */ } some(b) { es += ~[b]; } } alt maybe_base { none. {/* no-op */ } some(b) { es += ~[b]; } }
find_pre_post_exprs(fcx, es, e.id); find_pre_post_exprs(fcx, es, e.id);
} }
expr_tup(elts) {
find_pre_post_exprs(fcx, elt_exprs(elts), e.id);
}
expr_move(lhs, rhs) { handle_update(fcx, e, lhs, rhs, oper_move); } expr_move(lhs, rhs) { handle_update(fcx, e, lhs, rhs, oper_move); }
expr_swap(lhs, rhs) { handle_update(fcx, e, lhs, rhs, oper_swap); } expr_swap(lhs, rhs) { handle_update(fcx, e, lhs, rhs, oper_swap); }
expr_assign(lhs, rhs) { handle_update(fcx, e, lhs, rhs, oper_assign); } expr_assign(lhs, rhs) { handle_update(fcx, e, lhs, rhs, oper_assign); }

View file

@ -388,6 +388,12 @@ fn find_pre_post_state_expr(fcx: &fn_ctxt, pres: &prestate, e: @expr) ->
} }
ret changed; ret changed;
} }
expr_tup(elts) {
ret find_pre_post_state_exprs(fcx, pres, e.id,
ivec::init_elt(init_assign,
ivec::len(elts)),
elt_exprs(elts), return);
}
expr_move(lhs, rhs) { expr_move(lhs, rhs) {
ret find_pre_post_state_two(fcx, pres, lhs, rhs, e.id, oper_move); ret find_pre_post_state_two(fcx, pres, lhs, rhs, e.id, oper_move);
} }

View file

@ -47,6 +47,7 @@ export expr_ty_params_and_ty;
export fold_ty; export fold_ty;
export field; export field;
export field_idx; export field_idx;
export field_num;
export fm_general; export fm_general;
export get_element_type; export get_element_type;
export hash_ty; export hash_ty;
@ -69,6 +70,7 @@ export mk_float;
export mk_fn; export mk_fn;
export mk_imm_box; export mk_imm_box;
export mk_mut_ptr; export mk_mut_ptr;
export mk_imm_tup;
export mk_imm_vec; export mk_imm_vec;
export mk_int; export mk_int;
export mk_istr; export mk_istr;
@ -83,10 +85,10 @@ export mk_param;
export mk_port; export mk_port;
export mk_ptr; export mk_ptr;
export mk_rec; export mk_rec;
export mk_imm_tup;
export mk_str; export mk_str;
export mk_tag; export mk_tag;
export mk_task; export mk_task;
export mk_tup;
export mk_type; export mk_type;
export mk_uint; export mk_uint;
export mk_uniq; export mk_uniq;
@ -146,6 +148,7 @@ export ty_rec;
export ty_str; export ty_str;
export ty_tag; export ty_tag;
export ty_task; export ty_task;
export ty_tup;
export ty_type; export ty_type;
export ty_uint; export ty_uint;
export ty_uniq; export ty_uniq;
@ -279,6 +282,7 @@ tag sty {
ty_native_fn(ast::native_abi, [arg], t); ty_native_fn(ast::native_abi, [arg], t);
ty_obj([method]); ty_obj([method]);
ty_res(def_id, t, [t]); ty_res(def_id, t, [t]);
ty_tup([mt]);
ty_var(int); // type variable ty_var(int); // type variable
ty_param(uint, ast::kind); // fn/tag type param ty_param(uint, ast::kind); // fn/tag type param
@ -301,6 +305,8 @@ tag type_err {
terr_controlflow_mismatch; terr_controlflow_mismatch;
terr_box_mutability; terr_box_mutability;
terr_vec_mutability; terr_vec_mutability;
terr_tuple_size(uint, uint);
terr_tuple_mutability;
terr_record_size(uint, uint); terr_record_size(uint, uint);
terr_record_mutability; terr_record_mutability;
terr_record_fields(ast::ident, ast::ident); terr_record_fields(ast::ident, ast::ident);
@ -485,6 +491,11 @@ fn mk_raw_ty(cx: &ctxt, st: &sty, in_cname: &option::t[str]) -> @raw_t {
derive_flags_mt(cx, has_params, has_vars, f.mt); derive_flags_mt(cx, has_params, has_vars, f.mt);
} }
} }
ty_tup(mts) {
for m in mts {
derive_flags_mt(cx, has_params, has_vars, m);
}
}
ty_fn(_, args, tt, _, _) { ty_fn(_, args, tt, _, _) {
derive_flags_sig(cx, has_params, has_vars, args, tt); derive_flags_sig(cx, has_params, has_vars, args, tt);
} }
@ -590,20 +601,19 @@ fn mk_task(cx: &ctxt) -> t { ret gen_ty(cx, ty_task); }
fn mk_rec(cx: &ctxt, fs: &[field]) -> t { ret gen_ty(cx, ty_rec(fs)); } fn mk_rec(cx: &ctxt, fs: &[field]) -> t { ret gen_ty(cx, ty_rec(fs)); }
fn mk_imm_tup(cx: &ctxt, tys: &[t]) -> t {
let fields = ~[];
let i = 0u;
for typ: t in tys {
fields += ~[{ident: #fmt("_%u", i), mt: {ty: typ, mut: ast::imm}}];
i += 1u;
}
ret gen_ty(cx, ty_rec(fields));
}
fn mk_constr(cx: &ctxt, t: &t, cs: &[@type_constr]) -> t { fn mk_constr(cx: &ctxt, t: &t, cs: &[@type_constr]) -> t {
ret gen_ty(cx, ty_constr(t, cs)); ret gen_ty(cx, ty_constr(t, cs));
} }
fn mk_tup(cx: &ctxt, tms: &[mt]) -> t { ret gen_ty(cx, ty_tup(tms)); }
fn mk_imm_tup(cx: &ctxt, tys: &[t]) -> t {
// TODO: map
let mts = ~[];
for typ in tys { mts += ~[{ty: typ, mut: ast::imm}]; }
ret mk_tup(cx, mts);
}
fn mk_fn(cx: &ctxt, proto: &ast::proto, args: &[arg], ty: &t, fn mk_fn(cx: &ctxt, proto: &ast::proto, args: &[arg], ty: &t,
cf: &controlflow, constrs: &[@constr]) -> t { cf: &controlflow, constrs: &[@constr]) -> t {
ret gen_ty(cx, ty_fn(proto, args, ty, cf, constrs)); ret gen_ty(cx, ty_fn(proto, args, ty, cf, constrs));
@ -677,6 +687,9 @@ fn walk_ty(cx: &ctxt, walker: ty_walk, ty: t) {
ty_rec(fields) { ty_rec(fields) {
for fl: field in fields { walk_ty(cx, walker, fl.mt.ty); } for fl: field in fields { walk_ty(cx, walker, fl.mt.ty); }
} }
ty_tup(mts) {
for tm in mts { walk_ty(cx, walker, tm.ty); }
}
ty_fn(proto, args, ret_ty, _, _) { ty_fn(proto, args, ret_ty, _, _) {
for a: arg in args { walk_ty(cx, walker, a.ty); } for a: arg in args { walk_ty(cx, walker, a.ty); }
walk_ty(cx, walker, ret_ty); walk_ty(cx, walker, ret_ty);
@ -762,6 +775,14 @@ fn fold_ty(cx: &ctxt, fld: fold_mode, ty_0: t) -> t {
} }
ty = copy_cname(cx, mk_rec(cx, new_fields), ty); ty = copy_cname(cx, mk_rec(cx, new_fields), ty);
} }
ty_tup(mts) {
let new_mts = ~[];
for tm in mts {
let new_subty = fold_ty(cx, fld, tm.ty);
new_mts += ~[{ty: new_subty, mut: tm.mut}];
}
ty = copy_cname(cx, mk_tup(cx, new_mts), ty);
}
ty_fn(proto, args, ret_ty, cf, constrs) { ty_fn(proto, args, ret_ty, cf, constrs) {
let new_args: [arg] = ~[]; let new_args: [arg] = ~[];
for a: arg in args { for a: arg in args {
@ -861,6 +882,7 @@ fn type_is_task(cx: &ctxt, ty: &t) -> bool {
fn type_is_structural(cx: &ctxt, ty: &t) -> bool { fn type_is_structural(cx: &ctxt, ty: &t) -> bool {
alt struct(cx, ty) { alt struct(cx, ty) {
ty_rec(_) { ret true; } ty_rec(_) { ret true; }
ty_tup(_) { ret true; }
ty_tag(_, _) { ret true; } ty_tag(_, _) { ret true; }
ty_fn(_, _, _, _, _) { ret true; } ty_fn(_, _, _, _, _) { ret true; }
ty_obj(_) { ret true; } ty_obj(_) { ret true; }
@ -925,6 +947,7 @@ fn type_is_tup_like(cx: &ctxt, ty: &t) -> bool {
alt struct(cx, ty) { alt struct(cx, ty) {
ty_box(_) { ret true; } ty_box(_) { ret true; }
ty_rec(_) { ret true; } ty_rec(_) { ret true; }
ty_tup(_) { ret true; }
ty_tag(_, _) { ret true; } ty_tag(_, _) { ret true; }
_ { ret false; } _ { ret false; }
} }
@ -933,6 +956,7 @@ fn type_is_tup_like(cx: &ctxt, ty: &t) -> bool {
fn get_element_type(cx: &ctxt, ty: &t, i: uint) -> t { fn get_element_type(cx: &ctxt, ty: &t, i: uint) -> t {
alt struct(cx, ty) { alt struct(cx, ty) {
ty_rec(flds) { ret flds.(i).mt.ty; } ty_rec(flds) { ret flds.(i).mt.ty; }
ty_tup(mts) { ret mts.(i).ty; }
_ { _ {
cx.sess.bug("get_element_type called on type " + ty_to_str(cx, ty) + cx.sess.bug("get_element_type called on type " + ty_to_str(cx, ty) +
" - expected a \ " - expected a \
@ -1006,6 +1030,11 @@ fn type_has_pointers(cx: &ctxt, ty: &t) -> bool {
} }
} }
} }
ty_tup(elts) {
for m in elts {
if type_has_pointers(cx, m.ty) { result = true; }
}
}
ty_tag(did, tps) { ty_tag(did, tps) {
let variants = tag_variants(cx, did); let variants = tag_variants(cx, did);
for variant: variant_info in variants { for variant: variant_info in variants {
@ -1196,6 +1225,14 @@ fn type_has_dynamic_size(cx: &ctxt, ty: &t) -> bool {
} }
ret false; ret false;
} }
ty_tup(mts) {
let i = 0u;
while i < ivec::len(mts) {
if type_has_dynamic_size(cx, mts.(i).ty) { ret true; }
i += 1u;
}
ret false;
}
ty_fn(_, _, _, _, _) { ret false; } ty_fn(_, _, _, _, _) { ret false; }
ty_native_fn(_, _, _) { ret false; } ty_native_fn(_, _, _) { ret false; }
ty_obj(_) { ret false; } ty_obj(_) { ret false; }
@ -1317,12 +1354,16 @@ fn type_owns_heap_mem(cx: &ctxt, ty: &t) -> bool {
if type_owns_heap_mem(cx, f.mt.ty) { result = true; } if type_owns_heap_mem(cx, f.mt.ty) { result = true; }
} }
} }
ty_tup(elts) {
for m in elts {
if type_owns_heap_mem(cx, m.ty) { result = true; }
}
}
ty_res(_, inner, tps) { ty_res(_, inner, tps) {
result = result =
type_owns_heap_mem(cx, substitute_type_params(cx, tps, inner)); type_owns_heap_mem(cx, substitute_type_params(cx, tps, inner));
} }
ty_ptr(_) { ty_ptr(_) {
result = false; result = false;
} }
@ -1368,6 +1409,11 @@ fn type_is_pod(cx : &ctxt, ty : &t) -> bool {
if !type_is_pod(cx, f.mt.ty) { result = false; } if !type_is_pod(cx, f.mt.ty) { result = false; }
} }
} }
ty_tup(elts) {
for elt in elts {
if !type_is_pod(cx, elt.ty) { result = false; }
}
}
ty_res(_, inner, tps) { ty_res(_, inner, tps) {
result = type_is_pod(cx, result = type_is_pod(cx,
substitute_type_params(cx, tps, inner)); substitute_type_params(cx, tps, inner));
@ -1517,6 +1563,11 @@ fn hash_type_structure(st: &sty) -> uint {
for f: field in fields { h += h << 5u + hash_ty(f.mt.ty); } for f: field in fields { h += h << 5u + hash_ty(f.mt.ty); }
ret h; ret h;
} }
ty_tup(mts) {
let h = 25u;
for tm in mts { h += h << 5u + hash_ty(tm.ty); }
ret h;
}
// ??? // ???
ty_fn(_, args, rty, _, _) { ty_fn(_, args, rty, _, _) {
@ -1698,6 +1749,22 @@ fn equal_type_structures(a: &sty, b: &sty) -> bool {
_ { ret false; } _ { ret false; }
} }
} }
ty_tup(mts_a) {
alt (b) {
ty_tup(mts_b) {
let len = ivec::len(mts_a);
if len != ivec::len(mts_b) { ret false; }
let i = 0u;
while i < len {
if !equal_mt(mts_a.(i), mts_b.(i)) { ret false; }
i += 1u;
}
ret true;
}
_ { ret false; }
}
}
ty_fn(p_a, args_a, rty_a, cf_a, constrs_a) { ty_fn(p_a, args_a, rty_a, cf_a, constrs_a) {
alt b { alt b {
ty_fn(p_b, args_b, rty_b, cf_b, constrs_b) { ty_fn(p_b, args_b, rty_b, cf_b, constrs_b) {
@ -2659,6 +2726,44 @@ mod unify {
_ { ret ures_err(terr_mismatch); } _ { ret ures_err(terr_mismatch); }
} }
} }
ty::ty_tup(expected_elems) {
alt struct(cx.tcx, actual) {
ty::ty_tup(actual_elems) {
let expected_len = ivec::len(expected_elems);
let actual_len = ivec::len(actual_elems);
if (expected_len != actual_len) {
let err = terr_tuple_size(expected_len, actual_len);
ret ures_err(err);
}
// TODO: implement an iterator that can iterate over
// two arrays simultaneously.
let result_elems = ~[];
let i = 0u;
while i < expected_len {
let expected_elem = expected_elems.(i);
let actual_elem = actual_elems.(i);
let mut;
alt unify_mut(expected_elem.mut, actual_elem.mut) {
none. { ret ures_err(terr_tuple_mutability); }
some(m) { mut = m; }
}
let result = unify_step(cx, expected_elem.ty,
actual_elem.ty);
alt result {
ures_ok(rty) {
let mt = {ty: rty, mut: mut};
result_elems += ~[mt];
}
_ { ret result; }
}
i += 1u;
}
ret ures_ok(mk_tup(cx.tcx, result_elems));
}
_ { ret ures_err(terr_mismatch); }
}
}
ty::ty_fn(ep, expected_inputs, expected_output, expected_cf, ty::ty_fn(ep, expected_inputs, expected_output, expected_cf,
expected_constrs) { expected_constrs) {
alt struct(cx.tcx, actual) { alt struct(cx.tcx, actual) {
@ -2802,6 +2907,14 @@ fn type_err_to_str(err: &ty::type_err) -> str {
} }
terr_box_mutability. { ret "boxed values differ in mutability"; } terr_box_mutability. { ret "boxed values differ in mutability"; }
terr_vec_mutability. { ret "vectors differ in mutability"; } terr_vec_mutability. { ret "vectors differ in mutability"; }
terr_tuple_size(e_sz, a_sz) {
ret "expected a tuple with " + uint::to_str(e_sz, 10u) +
" elements but found one with " + uint::to_str(a_sz, 10u)
+ " elements";
}
terr_tuple_mutability. {
ret "tuple elements differ in mutability";
}
terr_record_size(e_sz, a_sz) { terr_record_size(e_sz, a_sz) {
ret "expected a record with " + uint::to_str(e_sz, 10u) + ret "expected a record with " + uint::to_str(e_sz, 10u) +
" fields but found one with " + uint::to_str(a_sz, 10u) + " fields but found one with " + uint::to_str(a_sz, 10u) +
@ -3044,6 +3157,7 @@ fn is_binopable(cx: &ctxt, ty: t, op: ast::binop) -> bool {
ty_vec(_) { tycat_vec } ty_vec(_) { tycat_vec }
ty_ivec(_) { tycat_vec } ty_ivec(_) { tycat_vec }
ty_rec(_) { tycat_struct } ty_rec(_) { tycat_struct }
ty_tup(_) { tycat_struct }
ty_tag(_, _) { tycat_struct } ty_tag(_, _) { tycat_struct }
ty_bot. { tycat_bot } ty_bot. { tycat_bot }
_ { tycat_other } _ { tycat_other }

View file

@ -339,6 +339,10 @@ fn ast_ty_to_ty(tcx: &ty::ctxt, getter: &ty_getter, ast_ty: &@ast::ty) ->
ast::ty_chan(t) { ast::ty_chan(t) {
typ = ty::mk_chan(tcx, ast_ty_to_ty(tcx, getter, t)); typ = ty::mk_chan(tcx, ast_ty_to_ty(tcx, getter, t));
} }
ast::ty_tup(fields) {
let flds = ivec::map(bind ast_mt_to_mt(tcx, getter, _), fields);
typ = ty::mk_tup(tcx, flds);
}
ast::ty_rec(fields) { ast::ty_rec(fields) {
let flds: [field] = ~[]; let flds: [field] = ~[];
for f: ast::ty_field in fields { for f: ast::ty_field in fields {
@ -2160,7 +2164,7 @@ fn check_expr_with_unifier(fcx: &@fn_ctxt, expr: &@ast::expr,
write::ty_only_fixup(fcx, id, t_1); write::ty_only_fixup(fcx, id, t_1);
} }
ast::expr_vec(args, mut, kind) { ast::expr_vec(args, mut, kind) {
let t: ty::t = next_ty_var(fcx);; let t: ty::t = next_ty_var(fcx);
for e: @ast::expr in args { for e: @ast::expr in args {
bot |= check_expr_with(fcx, e, t); bot |= check_expr_with(fcx, e, t);
} }
@ -2173,6 +2177,17 @@ fn check_expr_with_unifier(fcx: &@fn_ctxt, expr: &@ast::expr,
} }
write::ty_only_fixup(fcx, id, typ); write::ty_only_fixup(fcx, id, typ);
} }
ast::expr_tup(elts) {
let elts_mt = ~[];
ivec::reserve(elts_mt, ivec::len(elts));
for e in elts {
check_expr(fcx, e.expr);
let ety = expr_ty(fcx.ccx.tcx, e.expr);
elts_mt += ~[{ty: ety, mut: e.mut}];
}
let typ = ty::mk_tup(fcx.ccx.tcx, elts_mt);
write::ty_only_fixup(fcx, id, typ);
}
ast::expr_rec(fields, base) { ast::expr_rec(fields, base) {
alt base { none. {/* no-op */ } some(b_0) { check_expr(fcx, b_0); } } alt base { none. {/* no-op */ } some(b_0) { check_expr(fcx, b_0); } }
let fields_t: [spanned[field]] = ~[]; let fields_t: [spanned[field]] = ~[];

View file

@ -292,6 +292,7 @@ tag expr_ {
expr_vec([@expr], mutability, seq_kind); expr_vec([@expr], mutability, seq_kind);
expr_rec([field], option::t[@expr]); expr_rec([field], option::t[@expr]);
expr_call(@expr, [@expr]); expr_call(@expr, [@expr]);
expr_tup([elt]);
expr_self_method(ident); expr_self_method(ident);
expr_bind(@expr, [option::t[@expr]]); expr_bind(@expr, [option::t[@expr]]);
expr_spawn(spawn_dom, option::t[str], @expr, [@expr]); expr_spawn(spawn_dom, option::t[str], @expr, [@expr]);
@ -447,6 +448,7 @@ tag ty_ {
ty_rec([ty_field]); ty_rec([ty_field]);
ty_fn(proto, [ty_arg], @ty, controlflow, [@constr]); ty_fn(proto, [ty_arg], @ty, controlflow, [@constr]);
ty_obj([ty_method]); ty_obj([ty_method]);
ty_tup([mt]);
ty_path(path, node_id); ty_path(path, node_id);
ty_type; ty_type;
ty_constr(@ty, [@ty_constr]); ty_constr(@ty, [@ty_constr]);

View file

@ -338,6 +338,13 @@ fn noop_fold_expr(e: &expr_, fld: ast_fold) -> expr_ {
expr_rec(ivec::map(fold_field, fields), expr_rec(ivec::map(fold_field, fields),
option::map(fld.fold_expr, maybe_expr)) option::map(fld.fold_expr, maybe_expr))
} }
expr_tup(elts) {
let elts_ = ~[];
for elt in elts {
elts_ += ~[{mut: elt.mut, expr: fld.fold_expr(elt.expr)}];
}
expr_tup(elts_)
}
expr_call(f, args) { expr_call(f, args) {
expr_call(fld.fold_expr(f), fld.map_exprs(fld.fold_expr, args)) expr_call(fld.fold_expr(f), fld.map_exprs(fld.fold_expr, args))
} }

View file

@ -1569,6 +1569,7 @@ fn stmt_ends_with_semi(stmt: &ast::stmt) -> bool {
ret alt e.node { ret alt e.node {
ast::expr_vec(_, _, _) { true } ast::expr_vec(_, _, _) { true }
ast::expr_rec(_, _) { true } ast::expr_rec(_, _) { true }
ast::expr_tup(_) { true }
ast::expr_call(_, _) { true } ast::expr_call(_, _) { true }
ast::expr_self_method(_) { false } ast::expr_self_method(_) { false }
ast::expr_bind(_, _) { true } ast::expr_bind(_, _) { true }

View file

@ -322,6 +322,11 @@ fn print_type(s: &ps, ty: &ast::ty) {
commasep_cmnt(s, consistent, fields, print_field, get_span); commasep_cmnt(s, consistent, fields, print_field, get_span);
word(s.s, "}"); word(s.s, "}");
} }
ast::ty_tup(elts) {
popen(s);
commasep(s, inconsistent, elts, print_mt);
pclose(s);
}
ast::ty_fn(proto, inputs, output, cf, constrs) { ast::ty_fn(proto, inputs, output, cf, constrs) {
print_ty_fn(s, proto, none[str], inputs, output, cf, constrs); print_ty_fn(s, proto, none[str], inputs, output, cf, constrs);
} }
@ -713,6 +718,7 @@ fn print_expr(s: &ps, expr: &@ast::expr) {
alt kind { alt kind {
ast::sk_rc. { word(s.s, "["); } ast::sk_rc. { word(s.s, "["); }
ast::sk_unique. { word(s.s, "~["); } ast::sk_unique. { word(s.s, "~["); }
} }
if mut == ast::mut { if mut == ast::mut {
word(s.s, "mutable"); word(s.s, "mutable");
@ -746,6 +752,18 @@ fn print_expr(s: &ps, expr: &@ast::expr) {
} }
word(s.s, "}"); word(s.s, "}");
} }
ast::expr_tup(exprs) {
fn printElt(s: &ps, elt: &ast::elt) {
ibox(s, indent_unit);
if elt.mut == ast::mut { word_nbsp(s, "mutable"); }
print_expr(s, elt.expr);
end(s);
}
fn get_span(elt: &ast::elt) -> codemap::span { ret elt.expr.span; }
popen(s);
commasep_cmnt(s, inconsistent, exprs, printElt, get_span);
pclose(s);
}
ast::expr_call(func, args) { ast::expr_call(func, args) {
print_expr_parens_if_unary(s, func); print_expr_parens_if_unary(s, func);
popen(s); popen(s);

View file

@ -133,6 +133,9 @@ fn visit_ty[E](t: &@ty, e: &E, v: &vt[E]) {
ty_rec(flds) { ty_rec(flds) {
for f: ty_field in flds { v.visit_ty(f.node.mt.ty, e, v); } for f: ty_field in flds { v.visit_ty(f.node.mt.ty, e, v); }
} }
ty_tup(mts) {
for mt in mts { v.visit_ty(mt.ty, e, v); }
}
ty_fn(_, args, out, _, constrs) { ty_fn(_, args, out, _, constrs) {
for a: ty_arg in args { v.visit_ty(a.node.ty, e, v); } for a: ty_arg in args { v.visit_ty(a.node.ty, e, v); }
for c: @constr in constrs { for c: @constr in constrs {
@ -244,6 +247,9 @@ fn visit_expr[E](ex: &@expr, e: &E, v: &vt[E]) {
for f: field in flds { v.visit_expr(f.node.expr, e, v); } for f: field in flds { v.visit_expr(f.node.expr, e, v); }
visit_expr_opt(base, e, v); visit_expr_opt(base, e, v);
} }
expr_tup(elts) {
for el in elts { v.visit_expr(el.expr, e, v); }
}
expr_call(callee, args) { expr_call(callee, args) {
v.visit_expr(callee, e, v); v.visit_expr(callee, e, v);
visit_exprs(args, e, v); visit_exprs(args, e, v);

View file

@ -103,6 +103,11 @@ fn ty_to_str(cx: &ctxt, typ: &t) -> str {
for fld: field in elems { strs += ~[field_to_str(cx, fld)]; } for fld: field in elems { strs += ~[field_to_str(cx, fld)]; }
s += "{" + str::connect(strs, ",") + "}"; s += "{" + str::connect(strs, ",") + "}";
} }
ty_tup(elems) {
let strs = ~[];
for tm in elems { strs += ~[mt_to_str(cx, tm)]; }
s += "(" + str::connect(strs, ",") + ")";
}
ty_tag(id, tps) { ty_tag(id, tps) {
// The user should never see this if the cname is set properly! // The user should never see this if the cname is set properly!