diff --git a/src/comp/metadata/tydecode.rs b/src/comp/metadata/tydecode.rs index 961d7f1f400d..523aada6e623 100644 --- a/src/comp/metadata/tydecode.rs +++ b/src/comp/metadata/tydecode.rs @@ -236,6 +236,13 @@ fn parse_ty(st: @pstate, sd: str_def) -> ty::t { st.pos = st.pos + 1u; 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' { let func = parse_ty_fn(st, sd); ret ty::mk_fn(st.tcx, ast::proto_fn, func.args, func.ty, func.cf, diff --git a/src/comp/metadata/tyencode.rs b/src/comp/metadata/tyencode.rs index 4a58a613fc36..71f9e2ca113c 100644 --- a/src/comp/metadata/tyencode.rs +++ b/src/comp/metadata/tyencode.rs @@ -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); } 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_uniq(t) { w.write_char('~'); enc_ty(w, cx, t); } ty::ty_ptr(mt) { w.write_char('*'); enc_mt(w, cx, mt); } diff --git a/src/comp/middle/alias.rs b/src/comp/middle/alias.rs index 613f8510fe0b..8f19665ea566 100644 --- a/src/comp/middle/alias.rs +++ b/src/comp/middle/alias.rs @@ -678,6 +678,14 @@ fn ty_can_unsafely_include(cx: &ctx, needle: ty::t, haystack: ty::t, } 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. ty::ty_fn(_, _, _, _, _) { diff --git a/src/comp/middle/gc.rs b/src/comp/middle/gc.rs index 056adf94cc5c..c2b0819d5ff5 100644 --- a/src/comp/middle/gc.rs +++ b/src/comp/middle/gc.rs @@ -46,6 +46,12 @@ fn type_is_gc_relevant(cx: &ty::ctxt, ty: &ty::t) -> bool { } 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) { let variants = ty::tag_variants(cx, did); diff --git a/src/comp/middle/shape.rs b/src/comp/middle/shape.rs index 9cbb546535b1..7c01a8e2751a 100644 --- a/src/comp/middle/shape.rs +++ b/src/comp/middle/shape.rs @@ -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); } 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_native_fn(_,_,_) { s += ~[shape_u32]; } diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 13bac3218bbc..0cc9176a66f5 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -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_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); 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]; } 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) { let bcx = cx; // 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); 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); + } } } @@ -1811,7 +1833,7 @@ fn iter_structural_ty_full(cx: &@block_ctxt, av: ValueRef, t: &ty::t, alt ty::struct(bcx_tcx(cx), t) { ty::ty_rec(fields) { let i: int = 0; - for fld: ty::field in fields { + for fld: ty::field in fields { 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, fld.mt.ty), @@ -1819,6 +1841,16 @@ fn iter_structural_ty_full(cx: &@block_ctxt, av: ValueRef, t: &ty::t, 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) { let tcx = bcx_tcx(cx); 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); } +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) -> result { 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); } 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_fail(expr) { ret trans_fail_expr(cx, some(e.span), expr); } ast::expr_log(lvl, a) { ret trans_log(lvl, cx, a); } diff --git a/src/comp/middle/trans_comm.rs b/src/comp/middle/trans_comm.rs index 272da1251289..343fb055e08b 100644 --- a/src/comp/middle/trans_comm.rs +++ b/src/comp/middle/trans_comm.rs @@ -174,9 +174,9 @@ fn mk_spawn_wrapper(cx: &@block_ctxt, func: &@ast::expr, args_ty: &ty::t) -> // unpack the arguments alt ty::struct(fcx.lcx.ccx.tcx, args_ty) { - ty::ty_rec(fields) { + ty::ty_tup(elts) { 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)]); i += 1; let child_arg = fbcx.build.Load(src); diff --git a/src/comp/middle/tstate/pre_post_conditions.rs b/src/comp/middle/tstate/pre_post_conditions.rs index 338d514011d1..4f651da9f8f8 100644 --- a/src/comp/middle/tstate/pre_post_conditions.rs +++ b/src/comp/middle/tstate/pre_post_conditions.rs @@ -404,6 +404,9 @@ fn find_pre_post_expr(fcx: &fn_ctxt, e: @expr) { alt maybe_base { none. {/* no-op */ } some(b) { es += ~[b]; } } 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_swap(lhs, rhs) { handle_update(fcx, e, lhs, rhs, oper_swap); } expr_assign(lhs, rhs) { handle_update(fcx, e, lhs, rhs, oper_assign); } diff --git a/src/comp/middle/tstate/states.rs b/src/comp/middle/tstate/states.rs index e1ceb0625242..d3b5701dd526 100644 --- a/src/comp/middle/tstate/states.rs +++ b/src/comp/middle/tstate/states.rs @@ -388,6 +388,12 @@ fn find_pre_post_state_expr(fcx: &fn_ctxt, pres: &prestate, e: @expr) -> } 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) { ret find_pre_post_state_two(fcx, pres, lhs, rhs, e.id, oper_move); } diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index 37dcce69a50c..b0d0ab7b7e9f 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -47,6 +47,7 @@ export expr_ty_params_and_ty; export fold_ty; export field; export field_idx; +export field_num; export fm_general; export get_element_type; export hash_ty; @@ -69,6 +70,7 @@ export mk_float; export mk_fn; export mk_imm_box; export mk_mut_ptr; +export mk_imm_tup; export mk_imm_vec; export mk_int; export mk_istr; @@ -83,10 +85,10 @@ export mk_param; export mk_port; export mk_ptr; export mk_rec; -export mk_imm_tup; export mk_str; export mk_tag; export mk_task; +export mk_tup; export mk_type; export mk_uint; export mk_uniq; @@ -146,6 +148,7 @@ export ty_rec; export ty_str; export ty_tag; export ty_task; +export ty_tup; export ty_type; export ty_uint; export ty_uniq; @@ -279,6 +282,7 @@ tag sty { ty_native_fn(ast::native_abi, [arg], t); ty_obj([method]); ty_res(def_id, t, [t]); + ty_tup([mt]); ty_var(int); // type variable ty_param(uint, ast::kind); // fn/tag type param @@ -301,6 +305,8 @@ tag type_err { terr_controlflow_mismatch; terr_box_mutability; terr_vec_mutability; + terr_tuple_size(uint, uint); + terr_tuple_mutability; terr_record_size(uint, uint); terr_record_mutability; 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); } } + ty_tup(mts) { + for m in mts { + derive_flags_mt(cx, has_params, has_vars, m); + } + } ty_fn(_, 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_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 { 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, cf: &controlflow, constrs: &[@constr]) -> t { 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) { 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, _, _) { for a: arg in args { walk_ty(cx, walker, a.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_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) { let new_args: [arg] = ~[]; 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 { alt struct(cx, ty) { ty_rec(_) { ret true; } + ty_tup(_) { ret true; } ty_tag(_, _) { ret true; } ty_fn(_, _, _, _, _) { ret true; } ty_obj(_) { ret true; } @@ -925,6 +947,7 @@ fn type_is_tup_like(cx: &ctxt, ty: &t) -> bool { alt struct(cx, ty) { ty_box(_) { ret true; } ty_rec(_) { ret true; } + ty_tup(_) { ret true; } ty_tag(_, _) { ret true; } _ { 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 { alt struct(cx, 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) + " - 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) { let variants = tag_variants(cx, did); for variant: variant_info in variants { @@ -1196,6 +1225,14 @@ fn type_has_dynamic_size(cx: &ctxt, ty: &t) -> bool { } 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_native_fn(_, _, _) { 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; } } } + ty_tup(elts) { + for m in elts { + if type_owns_heap_mem(cx, m.ty) { result = true; } + } + } ty_res(_, inner, tps) { result = type_owns_heap_mem(cx, substitute_type_params(cx, tps, inner)); } - ty_ptr(_) { 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; } } } + ty_tup(elts) { + for elt in elts { + if !type_is_pod(cx, elt.ty) { result = false; } + } + } ty_res(_, inner, tps) { result = type_is_pod(cx, 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); } 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, _, _) { @@ -1698,6 +1749,22 @@ fn equal_type_structures(a: &sty, b: &sty) -> bool { _ { 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) { alt b { ty_fn(p_b, args_b, rty_b, cf_b, constrs_b) { @@ -2659,6 +2726,44 @@ mod unify { _ { 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, expected_constrs) { 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_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) { ret "expected a record with " + uint::to_str(e_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_ivec(_) { tycat_vec } ty_rec(_) { tycat_struct } + ty_tup(_) { tycat_struct } ty_tag(_, _) { tycat_struct } ty_bot. { tycat_bot } _ { tycat_other } diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 7484fd92996f..64b900f80530 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -339,6 +339,10 @@ fn ast_ty_to_ty(tcx: &ty::ctxt, getter: &ty_getter, ast_ty: &@ast::ty) -> ast::ty_chan(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) { let flds: [field] = ~[]; 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); } 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 { 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); } + 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) { alt base { none. {/* no-op */ } some(b_0) { check_expr(fcx, b_0); } } let fields_t: [spanned[field]] = ~[]; diff --git a/src/comp/syntax/ast.rs b/src/comp/syntax/ast.rs index 4c82771f69d5..4052c5cc1d8c 100644 --- a/src/comp/syntax/ast.rs +++ b/src/comp/syntax/ast.rs @@ -292,6 +292,7 @@ tag expr_ { expr_vec([@expr], mutability, seq_kind); expr_rec([field], option::t[@expr]); expr_call(@expr, [@expr]); + expr_tup([elt]); expr_self_method(ident); expr_bind(@expr, [option::t[@expr]]); expr_spawn(spawn_dom, option::t[str], @expr, [@expr]); @@ -447,6 +448,7 @@ tag ty_ { ty_rec([ty_field]); ty_fn(proto, [ty_arg], @ty, controlflow, [@constr]); ty_obj([ty_method]); + ty_tup([mt]); ty_path(path, node_id); ty_type; ty_constr(@ty, [@ty_constr]); diff --git a/src/comp/syntax/fold.rs b/src/comp/syntax/fold.rs index aa0f45be9970..4819e893bdb9 100644 --- a/src/comp/syntax/fold.rs +++ b/src/comp/syntax/fold.rs @@ -338,6 +338,13 @@ fn noop_fold_expr(e: &expr_, fld: ast_fold) -> expr_ { expr_rec(ivec::map(fold_field, fields), 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(fld.fold_expr(f), fld.map_exprs(fld.fold_expr, args)) } diff --git a/src/comp/syntax/parse/parser.rs b/src/comp/syntax/parse/parser.rs index 39843072c2af..58c7b618ec3a 100644 --- a/src/comp/syntax/parse/parser.rs +++ b/src/comp/syntax/parse/parser.rs @@ -1569,6 +1569,7 @@ fn stmt_ends_with_semi(stmt: &ast::stmt) -> bool { ret alt e.node { ast::expr_vec(_, _, _) { true } ast::expr_rec(_, _) { true } + ast::expr_tup(_) { true } ast::expr_call(_, _) { true } ast::expr_self_method(_) { false } ast::expr_bind(_, _) { true } diff --git a/src/comp/syntax/print/pprust.rs b/src/comp/syntax/print/pprust.rs index 45fd48bcd862..deae225a2216 100644 --- a/src/comp/syntax/print/pprust.rs +++ b/src/comp/syntax/print/pprust.rs @@ -322,6 +322,11 @@ fn print_type(s: &ps, ty: &ast::ty) { commasep_cmnt(s, consistent, fields, print_field, get_span); 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) { 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 { ast::sk_rc. { word(s.s, "["); } ast::sk_unique. { word(s.s, "~["); } + } if mut == ast::mut { word(s.s, "mutable"); @@ -746,6 +752,18 @@ fn print_expr(s: &ps, expr: &@ast::expr) { } 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) { print_expr_parens_if_unary(s, func); popen(s); diff --git a/src/comp/syntax/visit.rs b/src/comp/syntax/visit.rs index f7e7c3b352da..4b1f709a9fca 100644 --- a/src/comp/syntax/visit.rs +++ b/src/comp/syntax/visit.rs @@ -133,6 +133,9 @@ fn visit_ty[E](t: &@ty, e: &E, v: &vt[E]) { ty_rec(flds) { 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) { for a: ty_arg in args { v.visit_ty(a.node.ty, e, v); } 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); } visit_expr_opt(base, e, v); } + expr_tup(elts) { + for el in elts { v.visit_expr(el.expr, e, v); } + } expr_call(callee, args) { v.visit_expr(callee, e, v); visit_exprs(args, e, v); diff --git a/src/comp/util/ppaux.rs b/src/comp/util/ppaux.rs index 2873bfa7ccd7..eadcb1422d0d 100644 --- a/src/comp/util/ppaux.rs +++ b/src/comp/util/ppaux.rs @@ -103,6 +103,11 @@ fn ty_to_str(cx: &ctxt, typ: &t) -> str { for fld: field in elems { strs += ~[field_to_str(cx, fld)]; } 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) { // The user should never see this if the cname is set properly!