rustc: Implement "for" over interior vectors

This commit is contained in:
Patrick Walton 2011-06-20 16:52:43 -07:00
parent 23d6a6bde1
commit 062c6b946b
3 changed files with 41 additions and 15 deletions

View file

@ -335,7 +335,11 @@ fn check_for(&ctx cx, &@ast::local local, &@ast::expr seq, &ast::block block,
case (ty::ty_vec(?mt)) {
if (mt.mut != ast::imm) { unsafe = [seq_t]; }
}
case (ty::ty_str) { }
case (ty::ty_str) { /* no-op */ }
case (ty::ty_ivec(?mt)) {
if (mt.mut != ast::imm) { unsafe = [seq_t]; }
}
case (ty::ty_istr) { /* no-op */ }
}
auto new_sc =
@rec(root_vars=root_def,

View file

@ -2691,15 +2691,24 @@ fn iter_sequence_inner(&@block_ctxt cx, ValueRef src,
fn iter_sequence(@block_ctxt cx, ValueRef v, &ty::t t, &val_and_ty_fn f) ->
result {
fn iter_sequence_body(@block_ctxt cx, ValueRef v, &ty::t elt_ty,
&val_and_ty_fn f, bool trailing_null) -> result {
auto p0 = cx.build.GEP(v, [C_int(0), C_int(abi::vec_elt_data)]);
auto lenptr = cx.build.GEP(v, [C_int(0), C_int(abi::vec_elt_fill)]);
auto llunit_ty;
if (ty::type_has_dynamic_size(cx.fcx.lcx.ccx.tcx, elt_ty)) {
llunit_ty = T_i8();
} else { llunit_ty = type_of(cx.fcx.lcx.ccx, cx.sp, elt_ty); }
auto bcx = cx;
auto len = bcx.build.Load(lenptr);
&val_and_ty_fn f, bool trailing_null, bool interior)
-> result {
auto p0;
auto len;
auto bcx;
if (!interior) {
p0 = cx.build.GEP(v, [C_int(0), C_int(abi::vec_elt_data)]);
auto lp = cx.build.GEP(v, [C_int(0), C_int(abi::vec_elt_fill)]);
len = cx.build.Load(lp);
bcx = cx;
} else {
auto len_and_data_rslt = ivec::get_len_and_data(cx, v, elt_ty);
len = len_and_data_rslt._0;
p0 = len_and_data_rslt._1;
bcx = len_and_data_rslt._2;
}
auto llunit_ty = type_of_or_i8(cx, elt_ty);
if (trailing_null) {
auto unit_sz = size_of(bcx, elt_ty);
bcx = unit_sz.bcx;
@ -2709,13 +2718,21 @@ fn iter_sequence(@block_ctxt cx, ValueRef v, &ty::t t, &val_and_ty_fn f) ->
vi2p(bcx, bcx.build.Add(vp2i(bcx, p0), len), T_ptr(llunit_ty));
ret iter_sequence_inner(bcx, p0, p1, elt_ty, f);
}
alt (ty::struct(cx.fcx.lcx.ccx.tcx, t)) {
case (ty::ty_vec(?elt)) {
ret iter_sequence_body(cx, v, elt.ty, f, false);
ret iter_sequence_body(cx, v, elt.ty, f, false, false);
}
case (ty::ty_str) {
auto et = ty::mk_mach(cx.fcx.lcx.ccx.tcx, common::ty_u8);
ret iter_sequence_body(cx, v, et, f, true);
ret iter_sequence_body(cx, v, et, f, true, false);
}
case (ty::ty_ivec(?elt)) {
ret iter_sequence_body(cx, v, elt.ty, f, false, true);
}
case (ty::ty_istr) {
auto et = ty::mk_mach(cx.fcx.lcx.ccx.tcx, common::ty_u8);
ret iter_sequence_body(cx, v, et, f, true, true);
}
case (_) {
cx.fcx.lcx.ccx.sess.bug("unexpected type in " +

View file

@ -1683,15 +1683,20 @@ fn check_expr(&@fn_ctxt fcx, &@ast::expr expr) {
case (ast::expr_for(?decl, ?seq, ?body, ?id)) {
check_expr(fcx, seq);
auto elt_ty;
alt (structure_of(fcx, expr.span, expr_ty(fcx.ccx.tcx, seq))) {
auto ety = expr_ty(fcx.ccx.tcx, seq);
alt (structure_of(fcx, expr.span, ety)) {
case (ty::ty_vec(?vec_elt_ty)) { elt_ty = vec_elt_ty.ty; }
case (ty::ty_str) {
elt_ty = ty::mk_mach(fcx.ccx.tcx, util::common::ty_u8);
}
case (ty::ty_ivec(?vec_elt_ty)) { elt_ty = vec_elt_ty.ty; }
case (ty::ty_istr) {
elt_ty = ty::mk_mach(fcx.ccx.tcx, util::common::ty_u8);
}
case (_) {
fcx.ccx.tcx.sess.span_fatal(expr.span,
"type of for loop iterator \
is not a vector or string");
"mismatched types: expected vector or string but " +
"found " + ty_to_str(fcx.ccx.tcx, ety));
}
}
check_for_or_for_each(fcx, decl, elt_ty, body, id);