Add vstore/evec/estr to compiler.

This commit is contained in:
Graydon Hoare 2012-04-09 17:32:49 -07:00
parent 0c94cd5d43
commit 7a3b290245
19 changed files with 605 additions and 107 deletions

View file

@ -169,6 +169,14 @@ enum proto {
proto_block, // fn&
}
#[auto_serialize]
enum vstore {
vstore_fixed(option<uint>), // [1,2,3,4]/_ or 4 FIXME: uint -> @expr
vstore_uniq, // [1,2,3,4]/~
vstore_box, // [1,2,3,4]/@
vstore_slice(region) // [1,2,3,4]/&(foo)?
}
pure fn is_blockish(p: ast::proto) -> bool {
alt p {
proto_any | proto_block { true }
@ -278,6 +286,7 @@ enum alt_mode { alt_check, alt_exhaustive, }
#[auto_serialize]
enum expr_ {
expr_vstore(@expr, vstore),
expr_vec([@expr], mutability),
expr_rec([field], option<@expr>),
expr_call(@expr, [@expr], bool),
@ -459,6 +468,7 @@ enum ty_ {
ty_tup([@ty]),
ty_path(@path, node_id),
ty_constr(@ty, [@ty_constr]),
ty_vstore(@ty, vstore),
ty_mac(mac),
// ty_infer means the type should be inferred instead of it having been
// specified. This should only appear at the "top level" of a type and not

View file

@ -367,8 +367,7 @@ fn ser_ty(cx: ext_ctxt, tps: ser_tps_map,
}
ast::ty_ptr(_) | ast::ty_rptr(_, _) {
cx.span_err(
ty.span, #fmt["Cannot serialize pointer types"]);
cx.span_err(ty.span, "cannot serialize pointer types");
[]
}
@ -390,8 +389,7 @@ fn ser_ty(cx: ext_ctxt, tps: ser_tps_map,
}
ast::ty_fn(_, _) {
cx.span_err(
ty.span, #fmt["Cannot serialize function types"]);
cx.span_err(ty.span, "cannot serialize function types");
[]
}
@ -448,17 +446,19 @@ fn ser_ty(cx: ext_ctxt, tps: ser_tps_map,
}
ast::ty_mac(_) {
cx.span_err(
ty.span, #fmt["Cannot serialize macro types"]);
cx.span_err(ty.span, "cannot serialize macro types");
[]
}
ast::ty_infer {
cx.span_err(
ty.span, #fmt["Cannot serialize inferred types"]);
cx.span_err(ty.span, "cannot serialize inferred types");
[]
}
ast::ty_vstore(_, _) {
cx.span_unimpl(ty.span, "serialization for vstore types");
}
ast::ty_vec(mt) {
let ser_e =
cx.expr(
@ -675,6 +675,10 @@ fn deser_ty(cx: ext_ctxt, tps: deser_tps_map,
#ast{ fail }
}
ast::ty_vstore(_, _) {
cx.span_unimpl(ty.span, "deserialization for vstore types");
}
ast::ty_vec(mt) {
let l = deser_lambda(cx, tps, mt.ty, cx.clone(d));
#ast{ std::serialization::read_to_vec($(d), $(l)) }

View file

@ -389,6 +389,9 @@ fn noop_fold_expr(e: expr_, fld: ast_fold) -> expr_ {
fld.new_id(i),
fld.fold_expr(v))
}
expr_vstore(e, v) {
expr_vstore(fld.fold_expr(e), v)
}
expr_vec(exprs, mutt) {
expr_vec(fld.map_exprs(fld.fold_expr, exprs), mutt)
}
@ -497,6 +500,7 @@ fn noop_fold_ty(t: ty_, fld: ast_fold) -> ty_ {
ty_path(path, id) {ty_path(fld.fold_path(path), fld.new_id(id))}
// FIXME: constrs likely needs to be folded...
ty_constr(ty, constrs) {ty_constr(fld.fold_ty(ty), constrs)}
ty_vstore(t, vs) {ty_vstore(fld.fold_ty(t), vs)}
ty_mac(mac) {ty_mac(fold_mac(mac))}
ty_infer {t}
}

View file

@ -382,15 +382,32 @@ fn parse_type_constraints(p: parser) -> [@ast::ty_constr] {
fn parse_ty_postfix(orig_t: ast::ty_, p: parser, colons_before_params: bool,
lo: uint) -> @ast::ty {
fn mk_ty(p: parser, t: ast::ty_, lo: uint, hi: uint) -> @ast::ty {
@{id: p.get_id(),
node: t,
span: ast_util::mk_sp(lo, hi)}
}
if p.token == token::BINOP(token::SLASH) {
let orig_hi = p.last_span.hi;
alt parse_maybe_vstore(p) {
none { }
some(v) {
let t = ast::ty_vstore(mk_ty(p, orig_t, lo, orig_hi), v);
ret mk_ty(p, t, lo, p.last_span.hi);
}
}
}
if colons_before_params && p.token == token::MOD_SEP {
p.bump();
expect(p, token::LT);
} else if !colons_before_params && p.token == token::LT {
p.bump();
} else {
ret @{id: p.get_id(),
node: orig_t,
span: ast_util::mk_sp(lo, p.last_span.hi)};
ret mk_ty(p, orig_t, lo, p.last_span.hi);
}
// If we're here, we have explicit type parameter instantiation.
@ -399,12 +416,11 @@ fn parse_ty_postfix(orig_t: ast::ty_, p: parser, colons_before_params: bool,
alt orig_t {
ast::ty_path(pth, ann) {
ret @{id: p.get_id(),
node: ast::ty_path(@spanned(lo, p.last_span.hi,
{global: pth.node.global,
idents: pth.node.idents,
types: seq}), ann),
span: ast_util::mk_sp(lo, p.last_span.hi)};
ret mk_ty(p, ast::ty_path(@spanned(lo, p.last_span.hi,
{global: pth.node.global,
idents: pth.node.idents,
types: seq}), ann),
lo, p.last_span.hi);
}
_ { p.fatal("type parameter instantiation only allowed for paths"); }
}
@ -428,22 +444,33 @@ fn parse_ret_ty(p: parser) -> (ast::ret_style, @ast::ty) {
}
}
fn parse_region(p: parser) -> ast::region {
let region_ = alt p.token {
token::IDENT(sid, _) if p.look_ahead(1u) == token::DOT {
let string = p.get_str(sid);
p.bump(); p.bump();
if string == "self" {
ast::re_self
} else if string == "static" {
ast::re_static
} else {
ast::re_named(string)
}
fn region_from_name(p: parser, s: option<str>) -> ast::region {
let r = alt s {
some (string) {
if string == "self" {
ast::re_self
} else if string == "static" {
ast::re_static
} else {
ast::re_named(string)
}
_ { ast::re_inferred }
}
none { ast::re_inferred }
};
ret {id: p.get_id(), node: region_};
{id: p.get_id(), node: r}
}
fn parse_region(p: parser) -> ast::region {
let name =
alt p.token {
token::IDENT(sid, _) if p.look_ahead(1u) == token::DOT {
p.bump(); p.bump();
some(p.get_str(sid))
}
_ { none }
};
region_from_name(p, name)
}
fn parse_ty(p: parser, colons_before_params: bool) -> @ast::ty {
@ -666,6 +693,44 @@ fn have_dollar(p: parser) -> option<ast::mac_> {
}
}
fn parse_maybe_vstore(p: parser) -> option<ast::vstore> {
if p.token == token::BINOP(token::SLASH) {
p.bump();
alt p.token {
token::AT {
p.bump(); some(ast::vstore_box)
}
token::TILDE {
p.bump(); some(ast::vstore_uniq)
}
token::UNDERSCORE {
p.bump(); some(ast::vstore_fixed(none))
}
token::LIT_INT(i, ast::ty_i) if i >= 0 {
p.bump(); some(ast::vstore_fixed(some(i as uint)))
}
token::BINOP(token::AND) {
p.bump();
alt p.token {
token::IDENT(sid, _) {
p.bump();
let n = p.get_str(sid);
some(ast::vstore_slice(region_from_name(p, some(n))))
}
_ {
some(ast::vstore_slice(region_from_name(p, none)))
}
}
}
_ {
none
}
}
} else {
none
}
}
fn lit_from_token(p: parser, tok: token::token) -> ast::lit_ {
alt tok {
token::LIT_INT(i, it) { ast::lit_int(i, it) }
@ -678,7 +743,7 @@ fn lit_from_token(p: parser, tok: token::token) -> ast::lit_ {
}
fn parse_lit(p: parser) -> ast::lit {
let sp = p.span;
let lo = p.span.lo;
let lit = if eat_word(p, "true") {
ast::lit_bool(true)
} else if eat_word(p, "false") {
@ -688,7 +753,7 @@ fn parse_lit(p: parser) -> ast::lit {
p.bump();
lit_from_token(p, tok)
};
ret {node: lit, span: sp};
ret {node: lit, span: ast_util::mk_sp(lo, p.last_span.hi)};
}
fn is_ident(t: token::token) -> bool {
@ -891,6 +956,7 @@ fn parse_bottom_expr(p: parser) -> pexpr {
let es =
parse_seq_to_end(token::RBRACKET, seq_sep(token::COMMA),
parse_expr, p);
hi = p.span.hi;
ex = ast::expr_vec(es, mutbl);
} else if p.token == token::POUND_LT {
p.bump();
@ -988,6 +1054,23 @@ fn parse_bottom_expr(p: parser) -> pexpr {
hi = lit.span.hi;
ex = ast::expr_lit(@lit);
}
// Vstore is legal following expr_lit(lit_str(...)) and expr_vec(...)
// only.
alt ex {
ast::expr_lit(@{node: ast::lit_str(_), span: _}) |
ast::expr_vec(_, _) {
alt parse_maybe_vstore(p) {
none { }
some(v) {
hi = p.span.hi;
ex = ast::expr_vstore(mk_expr(p, lo, hi, ex), v);
}
}
}
_ { }
}
ret mk_pexpr(p, lo, hi, ex);
}
@ -1194,10 +1277,10 @@ type op_spec = {tok: token::token, op: ast::binop, prec: int};
// FIXME make this a const, don't store it in parser state
fn prec_table() -> @[op_spec] {
ret @[// 'as' sits between here with 12
{tok: token::BINOP(token::STAR), op: ast::mul, prec: 11},
{tok: token::BINOP(token::SLASH), op: ast::div, prec: 11},
{tok: token::BINOP(token::PERCENT), op: ast::rem, prec: 11},
ret @[{tok: token::BINOP(token::STAR), op: ast::mul, prec: 12},
{tok: token::BINOP(token::SLASH), op: ast::div, prec: 12},
{tok: token::BINOP(token::PERCENT), op: ast::rem, prec: 12},
// 'as' sits between here with 11
{tok: token::BINOP(token::PLUS), op: ast::add, prec: 10},
{tok: token::BINOP(token::MINUS), op: ast::subtract, prec: 10},
{tok: token::BINOP(token::LSL), op: ast::lsl, prec: 9},
@ -1222,7 +1305,7 @@ fn parse_binops(p: parser) -> @ast::expr {
const unop_prec: int = 100;
const as_prec: int = 12;
const as_prec: int = 11;
fn parse_more_binops(p: parser, plhs: pexpr, min_prec: int) ->
@ast::expr {

View file

@ -378,6 +378,10 @@ fn print_type(s: ps, &&ty: @ast::ty) {
space(s.s);
word(s.s, constrs_str(cs, ty_constr_to_str));
}
ast::ty_vstore(t, v) {
print_type(s, t);
print_vstore(s, v);
}
ast::ty_mac(_) {
fail "print_type doesn't know how to print a ty_mac";
}
@ -810,12 +814,36 @@ fn print_mac(s: ps, m: ast::mac) {
}
}
fn print_vstore(s: ps, t: ast::vstore) {
alt t {
ast::vstore_fixed(some(i)) { word_space(s, #fmt("/%u", i)); }
ast::vstore_fixed(none) { word_space(s, "/_"); }
ast::vstore_uniq { word_space(s, "/~"); }
ast::vstore_box { word_space(s, "/@"); }
ast::vstore_slice(r) {
alt r.node {
ast::re_inferred { word_space(s, "/&"); }
ast::re_self { word_space(s, "/&self"); }
ast::re_static { word_space(s, "/&static"); }
ast::re_named(name) {
word(s.s, "/&");
word_space(s, name);
}
}
}
}
}
fn print_expr(s: ps, &&expr: @ast::expr) {
maybe_print_comment(s, expr.span.lo);
ibox(s, indent_unit);
let ann_node = node_expr(s, expr);
s.ann.pre(ann_node);
alt expr.node {
ast::expr_vstore(e, v) {
print_expr(s, e);
print_vstore(s, v);
}
ast::expr_vec(exprs, mutbl) {
ibox(s, indent_unit);
word(s.s, "[");

View file

@ -170,11 +170,10 @@ fn skip_ty<E>(_t: @ty, _e: E, _v: vt<E>) {}
fn visit_ty<E>(t: @ty, e: E, v: vt<E>) {
alt t.node {
ty_box(mt) { v.visit_ty(mt.ty, e, v); }
ty_uniq(mt) { v.visit_ty(mt.ty, e, v); }
ty_vec(mt) { v.visit_ty(mt.ty, e, v); }
ty_ptr(mt) { v.visit_ty(mt.ty, e, v); }
ty_rptr(_, mt) { v.visit_ty(mt.ty, e, v); }
ty_box(mt) | ty_uniq(mt) |
ty_vec(mt) | ty_ptr(mt) | ty_rptr(_, mt) {
v.visit_ty(mt.ty, e, v);
}
ty_rec(flds) {
for flds.each {|f| v.visit_ty(f.node.mt.ty, e, v); }
}
@ -187,6 +186,9 @@ fn visit_ty<E>(t: @ty, e: E, v: vt<E>) {
v.visit_ty(decl.output, e, v);
}
ty_path(p, _) { visit_path(p, e, v); }
ty_vstore(t, _) {
v.visit_ty(t, e, v);
}
ty_constr(t, cs) {
v.visit_ty(t, e, v);
for cs.each {|tc|
@ -335,6 +337,7 @@ fn visit_expr<E>(ex: @expr, e: E, v: vt<E>) {
v.visit_expr(pool, e, v);
v.visit_expr(val, e, v);
}
expr_vstore(x, _) { v.visit_expr(x, e, v); }
expr_vec(es, _) { visit_exprs(es, e, v); }
expr_rec(flds, base) {
for flds.each {|f| v.visit_expr(f.node.expr, e, v); }

View file

@ -176,6 +176,7 @@ fn enc_sty(w: io::writer, cx: @ctxt, st: ty::sty) {
ty_f64 { w.write_str("MF"); }
}
}
ty::ty_estr(_) { cx.tcx.sess.unimpl("tyencode::enc_sty on estr"); }
ty::ty_str { w.write_char('S'); }
ty::ty_enum(def, tys) {
w.write_str("t[");
@ -204,6 +205,7 @@ fn enc_sty(w: io::writer, cx: @ctxt, st: ty::sty) {
enc_region(w, r);
enc_mt(w, cx, mt);
}
ty::ty_evec(_, _) { cx.tcx.sess.unimpl("tyencode::enc_sty on evec"); }
ty::ty_vec(mt) { w.write_char('I'); enc_mt(w, cx, mt); }
ty::ty_rec(fields) {
w.write_str("R[");

View file

@ -92,12 +92,14 @@ fn expr_root_(tcx: ty::ctxt, ctor_self: option<node_id>,
expr_index(base, _) {
let auto_unbox = maybe_auto_unbox(tcx, ty::expr_ty(tcx, base));
alt ty::get(auto_unbox.t).struct {
ty::ty_evec(mt, _) |
ty::ty_vec(mt) {
ds +=
[@{mutbl: mt.mutbl == m_mutbl,
kind: index,
outer_t: auto_unbox.t}];
}
ty::ty_estr(_) |
ty::ty_str {
ds += [@{mutbl: false, kind: index, outer_t: auto_unbox.t}];
}

View file

@ -414,6 +414,7 @@ fn resolve_ty(ty: @ast::ty, cx: ctxt, visitor: visit::vt<ctxt>) {
cx.region_map.ast_type_to_inferred_region.insert(ty.id, inferred_region);
alt ty.node {
ast::ty_vstore(_, ast::vstore_slice(r)) |
ast::ty_rptr(r, _) {
resolve_region_binding(cx, ty.span, r);
}

View file

@ -573,7 +573,8 @@ fn make_take_glue(bcx: block, v: ValueRef, t: ty::t) {
let _icx = bcx.insn_ctxt("make_take_glue");
// NB: v is a *pointer* to type t here, not a direct value.
let bcx = alt ty::get(t).struct {
ty::ty_box(_) | ty::ty_opaque_box {
ty::ty_box(_) | ty::ty_opaque_box |
ty::ty_evec(_, ty::vstore_box) | ty::ty_estr(ty::vstore_box) {
incr_refcnt_of_boxed(bcx, Load(bcx, v)); bcx
}
ty::ty_uniq(_) {
@ -581,7 +582,8 @@ fn make_take_glue(bcx: block, v: ValueRef, t: ty::t) {
Store(bcx, val, v);
bcx
}
ty::ty_vec(_) | ty::ty_str {
ty::ty_vec(_) | ty::ty_str |
ty::ty_evec(_, ty::vstore_uniq) | ty::ty_estr(ty::vstore_uniq) {
let {bcx, val} = tvec::duplicate(bcx, Load(bcx, v), t);
Store(bcx, val, v);
bcx
@ -629,6 +631,12 @@ fn make_free_glue(bcx: block, v: ValueRef, t: ty::t) {
let bcx = drop_ty(bcx, body, body_mt.ty);
trans_free(bcx, v)
}
ty::ty_estr(ty::vstore_box) {
let v = PointerCast(bcx, v, type_of(ccx, t));
trans_free(bcx, v)
}
ty::ty_opaque_box {
let v = PointerCast(bcx, v, type_of(ccx, t));
let td = Load(bcx, GEPi(bcx, v, [0, abi::box_field_tydesc]));
@ -641,9 +649,13 @@ fn make_free_glue(bcx: block, v: ValueRef, t: ty::t) {
let v = PointerCast(bcx, v, type_of(ccx, t));
uniq::make_free_glue(bcx, v, t)
}
ty::ty_evec(_, ty::vstore_uniq) | ty::ty_estr(ty::vstore_uniq) |
ty::ty_vec(_) | ty::ty_str {
tvec::make_free_glue(bcx, PointerCast(bcx, v, type_of(ccx, t)), t)
}
ty::ty_evec(_, _) {
bcx.sess().unimpl("trans::base::make_free_glue on other evec");
}
ty::ty_fn(_) {
closure::make_fn_glue(bcx, v, t, free_ty)
}
@ -660,7 +672,8 @@ fn make_drop_glue(bcx: block, v0: ValueRef, t: ty::t) {
let _icx = bcx.insn_ctxt("make_drop_glue");
let ccx = bcx.ccx();
let bcx = alt ty::get(t).struct {
ty::ty_box(_) | ty::ty_opaque_box {
ty::ty_box(_) | ty::ty_opaque_box |
ty::ty_estr(ty::vstore_box) {
decr_refcnt_maybe_free(bcx, Load(bcx, v0), t)
}
ty::ty_uniq(_) | ty::ty_vec(_) | ty::ty_str {
@ -900,6 +913,10 @@ fn iter_structural_ty(cx: block, av: ValueRef, t: ty::t,
cx = f(cx, llfld_a, fld.mt.ty);
}
}
ty::ty_estr(ty::vstore_fixed(n)) |
ty::ty_evec(_, ty::vstore_fixed(n)) {
cx = tvec::iter_vec_raw(cx, av, t, C_uint(cx.ccx(), n), f);
}
ty::ty_tup(args) {
for vec::eachi(args) {|i, arg|
let llfld_a = GEPi(cx, av, [0, i as int]);
@ -1111,8 +1128,14 @@ fn drop_ty(cx: block, v: ValueRef, t: ty::t) -> block {
fn drop_ty_immediate(bcx: block, v: ValueRef, t: ty::t) -> block {
let _icx = bcx.insn_ctxt("drop_ty_immediate");
alt ty::get(t).struct {
ty::ty_uniq(_) | ty::ty_vec(_) | ty::ty_str { free_ty(bcx, v, t) }
ty::ty_box(_) | ty::ty_opaque_box {
ty::ty_uniq(_) | ty::ty_vec(_) | ty::ty_str |
ty::ty_evec(_, ty::vstore_uniq) |
ty::ty_estr(ty::vstore_uniq) {
free_ty(bcx, v, t)
}
ty::ty_box(_) | ty::ty_opaque_box |
ty::ty_evec(_, ty::vstore_box) |
ty::ty_estr(ty::vstore_box) {
decr_refcnt_maybe_free(bcx, v, t)
}
_ { bcx.tcx().sess.bug("drop_ty_immediate: non-box ty"); }
@ -1122,14 +1145,20 @@ fn drop_ty_immediate(bcx: block, v: ValueRef, t: ty::t) -> block {
fn take_ty_immediate(bcx: block, v: ValueRef, t: ty::t) -> result {
let _icx = bcx.insn_ctxt("take_ty_immediate");
alt ty::get(t).struct {
ty::ty_box(_) | ty::ty_opaque_box {
ty::ty_box(_) | ty::ty_opaque_box |
ty::ty_evec(_, ty::vstore_box) |
ty::ty_estr(ty::vstore_box) {
incr_refcnt_of_boxed(bcx, v);
rslt(bcx, v)
}
ty::ty_uniq(_) {
uniq::duplicate(bcx, v, t)
}
ty::ty_str | ty::ty_vec(_) { tvec::duplicate(bcx, v, t) }
ty::ty_str | ty::ty_vec(_) |
ty::ty_evec(_, ty::vstore_uniq) |
ty::ty_estr(ty::vstore_uniq) {
tvec::duplicate(bcx, v, t)
}
_ { rslt(bcx, v) }
}
}
@ -1299,9 +1328,9 @@ fn trans_lit(cx: block, lit: ast::lit, dest: dest) -> block {
let _icx = cx.insn_ctxt("trans_lit");
if dest == ignore { ret cx; }
alt lit.node {
ast::lit_str(s) { ret tvec::trans_str(cx, s, dest); }
ast::lit_str(s) { tvec::trans_str(cx, s, dest) }
_ {
ret store_in_dest(cx, trans_crate_lit(cx.ccx(), lit), dest);
store_in_dest(cx, trans_crate_lit(cx.ccx(), lit), dest)
}
}
}
@ -2255,8 +2284,29 @@ fn trans_index(cx: block, ex: @ast::expr, base: @ast::expr,
maybe_name_value(cx.ccx(), unit_sz, "unit_sz");
let scaled_ix = Mul(bcx, ix_val, unit_sz);
maybe_name_value(cx.ccx(), scaled_ix, "scaled_ix");
let lim = tvec::get_fill(bcx, v);
let body = tvec::get_dataptr(bcx, v, type_of(ccx, unit_ty));
let (lim, body) = alt ty::get(base_ty).struct {
ty::ty_estr(ty::vstore_fixed(n)) |
ty::ty_evec(_, ty::vstore_fixed(n)) {
// FIXME: support static bounds-check elimination
// and/or error checking here.
let lim = C_uint(bcx.ccx(), n);
let body = GEPi(bcx, v, [0, 0]);
(lim, body)
}
ty::ty_estr(_) | ty::ty_evec(_, _) {
bcx.sess().unimpl(#fmt("unsupported evec/estr type trans_index"));
}
_ {
let lim = tvec::get_fill(bcx, v);
let body = tvec::get_dataptr(bcx, v, type_of(ccx, unit_ty));
(lim, body)
}
};
#debug("trans_index: lim %s", val_str(bcx.ccx().tn, lim));
#debug("trans_index: body %s", val_str(bcx.ccx().tn, body));
let bounds_check = ICmp(bcx, lib::llvm::IntUGE, scaled_ix, lim);
let bcx = with_cond(bcx, bounds_check) {|bcx|
// fail: bad bounds check.
@ -3017,6 +3067,7 @@ fn trans_expr(bcx: block, e: @ast::expr, dest: dest) -> block {
ret trans_rec(bcx, args, base, e.id, dest);
}
ast::expr_tup(args) { ret trans_tup(bcx, args, dest); }
ast::expr_vstore(e, v) { ret tvec::trans_vstore(bcx, e, v, dest); }
ast::expr_lit(lit) { ret trans_lit(bcx, *lit, dest); }
ast::expr_vec(args, _) { ret tvec::trans_vec(bcx, args, e.id, dest); }
ast::expr_binary(op, lhs, rhs) {

View file

@ -58,6 +58,8 @@ const shape_bare_fn: u8 = 27u8;
const shape_tydesc: u8 = 28u8;
const shape_send_tydesc: u8 = 29u8;
const shape_rptr: u8 = 31u8;
const shape_fixedvec: u8 = 32u8;
const shape_slice: u8 = 33u8;
fn hash_res_info(ri: res_info) -> uint {
let mut h = 5381u;
@ -305,6 +307,7 @@ fn shape_of(ccx: @crate_ctxt, t: ty::t, ty_param_map: [uint]) -> [u8] {
ty::ty_int(ast::ty_i64) { [shape_i64] }
ty::ty_float(ast::ty_f32) { [shape_f32] }
ty::ty_float(ast::ty_f64) { [shape_f64] }
ty::ty_estr(ty::vstore_uniq) |
ty::ty_str {
let mut s = [shape_vec];
add_bool(s, true); // type is POD
@ -340,18 +343,67 @@ fn shape_of(ccx: @crate_ctxt, t: ty::t, ty_param_map: [uint]) -> [u8] {
}
}
}
ty::ty_estr(ty::vstore_box) |
ty::ty_evec(_, ty::vstore_box) |
ty::ty_box(_) | ty::ty_opaque_box { [shape_box] }
ty::ty_uniq(mt) {
let mut s = [shape_uniq];
add_substr(s, shape_of(ccx, mt.ty, ty_param_map));
s
}
ty::ty_evec(mt, ty::vstore_uniq) |
ty::ty_vec(mt) {
let mut s = [shape_vec];
add_bool(s, ty::type_is_pod(ccx.tcx, mt.ty));
add_substr(s, shape_of(ccx, mt.ty, ty_param_map));
s
}
// FIXME: grotesque hacks for encoding fixed-size evecs and estrs.
ty::ty_estr(ty::vstore_fixed(n)) {
let mut s = [shape_struct], sub = [];
let mut i = 0u;
let u8_t = ty::mk_mach_uint(ccx.tcx, ast::ty_u8);
while i < n {
sub += shape_of(ccx, u8_t, ty_param_map);
}
add_substr(s, sub);
s
}
ty::ty_evec(mt, ty::vstore_fixed(n)) {
let mut s = [shape_struct], sub = [];
let mut i = 0u;
while i < n {
sub += shape_of(ccx, mt.ty, ty_param_map);
}
add_substr(s, sub);
s
}
// FIXME: slightly-less-grotesque hack for encoding slic,e evecs and
// estrs.
ty::ty_estr(ty::vstore_slice(r)) {
let mut s = [shape_struct], sub = [];
let u8_mt = {ty: ty::mk_mach_uint(ccx.tcx, ast::ty_u8),
mutbl: ast::m_imm };
sub += shape_of(ccx, ty::mk_rptr(ccx.tcx, r, u8_mt), ty_param_map);
sub += shape_of(ccx, ty::mk_uint(ccx.tcx), ty_param_map);
add_substr(s, sub);
s
}
ty::ty_evec(mt, ty::vstore_slice(r)) {
let mut s = [shape_struct], sub = [];
sub += shape_of(ccx, ty::mk_rptr(ccx.tcx, r, mt), ty_param_map);
sub += shape_of(ccx, ty::mk_uint(ccx.tcx), ty_param_map);
add_substr(s, sub);
s
}
ty::ty_rec(fields) {
let mut s = [shape_struct], sub = [];
for vec::each(fields) {|f|
@ -632,12 +684,18 @@ fn simplify_type(tcx: ty::ctxt, typ: ty::t) -> ty::t {
fn simplifier(tcx: ty::ctxt, typ: ty::t) -> ty::t {
alt ty::get(typ).struct {
ty::ty_box(_) | ty::ty_opaque_box | ty::ty_uniq(_) | ty::ty_vec(_) |
ty::ty_evec(_, ty::vstore_uniq) | ty::ty_evec(_, ty::vstore_box) |
ty::ty_estr(ty::vstore_uniq) | ty::ty_estr(ty::vstore_box) |
ty::ty_ptr(_) | ty::ty_rptr(_,_) { nilptr(tcx) }
ty::ty_fn(_) { ty::mk_tup(tcx, [nilptr(tcx), nilptr(tcx)]) }
ty::ty_res(_, sub, tps) {
let sub1 = ty::substitute_type_params(tcx, tps, sub);
ty::mk_tup(tcx, [ty::mk_int(tcx), simplify_type(tcx, sub1)])
}
ty::ty_evec(_, ty::vstore_slice(_)) |
ty::ty_estr(ty::vstore_slice(_)) {
ty::mk_tup(tcx, [nilptr(tcx), ty::mk_int(tcx)])
}
_ { typ }
}
}

View file

@ -6,6 +6,7 @@ import base::{call_memmove, shared_malloc,
INIT, copy_val, load_if_immediate, get_tydesc,
sub_block, do_spill_noroot,
dest, bcx_icx};
import syntax::codemap::span;
import shape::llsize_of;
import build::*;
import common::*;
@ -129,6 +130,48 @@ fn trans_vec(bcx: block, args: [@ast::expr], id: ast::node_id,
ret base::store_in_dest(bcx, vptr, dest);
}
fn trans_vstore(bcx: block, e: @ast::expr,
v: ast::vstore, dest: dest) -> block {
alt e.node {
ast::expr_lit(@{node: ast::lit_str(s), span: _}) {
ret trans_estr(bcx, s, v, e.span, dest);
}
ast::expr_vec(es, mutbl) {
bcx.ccx().sess.span_unimpl(e.span, "unhandled tvec::trans_vstore");
}
_ {
bcx.sess().span_bug(e.span, "vstore on non-sequence type");
}
}
}
fn trans_estr(bcx: block, s: str, vstore: ast::vstore,
sp: span, dest: dest) -> block {
let _icx = bcx.insn_ctxt("tvec::trans_estr");
alt vstore {
ast::vstore_fixed(_)
{
let c = str::as_bytes(s) {|bytes|
// NB: The byte vector we have here includes the trailing \0,
// but we are doing a fixed-size str, meaning we _exclude_
// the trailing \0. And we don't let LLVM null-terminate
// either.
unsafe {
lib::llvm::llvm::LLVMConstString(
unsafe::reinterpret_cast(vec::unsafe::to_ptr(bytes)),
(bytes.len() - 1u) as libc::c_uint, lib::llvm::True)
}
};
#debug("trans_estr: src %s",val_str(bcx.ccx().tn, c));
ret base::store_in_dest(bcx, c, dest);
}
_ {
bcx.ccx().sess.span_unimpl(sp, "unhandled tvec::trans_estr");
}
}
}
fn trans_str(bcx: block, s: str, dest: dest) -> block {
let _icx = bcx.insn_ctxt("tvec::trans_str");
let ccx = bcx.ccx();

View file

@ -48,14 +48,37 @@ fn type_of(cx: @crate_ctxt, t: ty::t) -> TypeRef {
ty::ty_int(t) { T_int_ty(cx, t) }
ty::ty_uint(t) { T_uint_ty(cx, t) }
ty::ty_float(t) { T_float_ty(cx, t) }
ty::ty_estr(ty::vstore_uniq) |
ty::ty_str { T_ptr(T_vec(cx, T_i8())) }
ty::ty_enum(did, _) { type_of_enum(cx, did, t) }
ty::ty_estr(ty::vstore_box) { T_ptr(T_box(cx, T_i8())) }
ty::ty_evec(mt, ty::vstore_box) |
ty::ty_box(mt) { T_ptr(T_box(cx, type_of(cx, mt.ty))) }
ty::ty_opaque_box { T_ptr(T_box(cx, T_i8())) }
ty::ty_uniq(mt) { T_ptr(type_of(cx, mt.ty)) }
ty::ty_evec(mt, ty::vstore_uniq) |
ty::ty_vec(mt) { T_ptr(T_vec(cx, type_of(cx, mt.ty))) }
ty::ty_ptr(mt) { T_ptr(type_of(cx, mt.ty)) }
ty::ty_rptr(_, mt) { T_ptr(type_of(cx, mt.ty)) }
ty::ty_evec(mt, ty::vstore_slice(_)) {
T_struct([T_ptr(type_of(cx, mt.ty)),
T_uint_ty(cx, ast::ty_u)])
}
ty::ty_estr(ty::vstore_slice(_)) {
T_struct([T_ptr(T_i8()),
T_uint_ty(cx, ast::ty_u)])
}
ty::ty_estr(ty::vstore_fixed(n)) {
T_array(T_i8(), n)
}
ty::ty_evec(mt, ty::vstore_fixed(n)) {
T_array(type_of(cx, mt.ty), n)
}
ty::ty_rec(fields) {
let mut tys: [TypeRef] = [];
for vec::each(fields) {|f|

View file

@ -136,7 +136,9 @@ fn node_type_needs(cx: ctx, use: uint, id: node_id) {
fn mark_for_expr(cx: ctx, e: @expr) {
alt e.node {
expr_vec(_, _) | expr_rec(_, _) | expr_tup(_) |
expr_vstore(_, _) |
expr_vec(_, _) |
expr_rec(_, _) | expr_tup(_) |
expr_unary(box(_), _) | expr_unary(uniq(_), _) |
expr_cast(_, _) | expr_binary(add, _, _) |
expr_copy(_) | expr_move(_, _) {

View file

@ -321,7 +321,14 @@ fn find_pre_post_expr(fcx: fn_ctxt, e: @expr) {
_ { }
}
}
expr_vec(args, _) { find_pre_post_exprs(fcx, args, e.id); }
expr_vstore(ee, _) {
find_pre_post_expr(fcx, ee);
let p = expr_pp(fcx.ccx, ee);
set_pre_and_post(fcx.ccx, e.id, p.precondition, p.postcondition);
}
expr_vec(args, _) {
find_pre_post_exprs(fcx, args, e.id);
}
expr_path(p) {
let rslt = expr_pp(fcx.ccx, e);
clear_pp(rslt);

View file

@ -358,6 +358,12 @@ fn find_pre_post_state_expr(fcx: fn_ctxt, pres: prestate, e: @expr) -> bool {
expr_new(p, _, v) {
ret find_pre_post_state_two(fcx, pres, p, v, e.id, oper_pure);
}
expr_vstore(ee, _) {
let mut changed = find_pre_post_state_expr(fcx, pres, ee);
set_prestate_ann(fcx.ccx, e.id, expr_prestate(fcx.ccx, ee));
set_poststate_ann(fcx.ccx, e.id, expr_poststate(fcx.ccx, ee));
ret changed;
}
expr_vec(elts, _) {
ret find_pre_post_state_exprs(fcx, pres, e.id,
vec::from_elem(vec::len(elts),

View file

@ -80,6 +80,9 @@ export ty_fn_proto, ty_fn_ret, ty_fn_ret_style;
export ty_int, mk_int, mk_mach_int, mk_char;
export ty_str, mk_str, type_is_str;
export ty_vec, mk_vec, type_is_vec;
export ty_estr, mk_estr;
export ty_evec, mk_evec;
export vstore, vstore_fixed, vstore_uniq, vstore_box, vstore_slice;
export ty_nil, mk_nil, type_is_nil;
export ty_iface, mk_iface;
export ty_res, mk_res;
@ -164,6 +167,13 @@ type constr_table = hashmap<ast::node_id, [constr]>;
type mt = {ty: t, mutbl: ast::mutability};
enum vstore {
vstore_fixed(uint),
vstore_uniq,
vstore_box,
vstore_slice(region)
}
type field_ty = {
ident: ident,
id: def_id,
@ -293,10 +303,12 @@ enum sty {
ty_uint(ast::uint_ty),
ty_float(ast::float_ty),
ty_str,
ty_estr(vstore),
ty_enum(def_id, [t]),
ty_box(mt),
ty_uniq(mt),
ty_vec(mt),
ty_evec(mt, vstore),
ty_ptr(mt),
ty_rptr(region, mt),
ty_rec([field]),
@ -458,8 +470,15 @@ fn mk_t_with_id(cx: ctxt, st: sty, o_def_id: option<ast::def_id>) -> t {
has_rptrs |= t.has_rptrs;
}
alt st {
ty_estr(vstore_slice(_)) {
has_rptrs = true;
}
ty_evec(mt, vstore_slice(_)) {
has_rptrs = true;
derive_flags(has_params, has_vars, has_rptrs, mt.ty);
}
ty_nil | ty_bot | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) |
ty_str | ty_type | ty_opaque_closure_ptr(_) |
ty_str | ty_estr(_) | ty_type | ty_opaque_closure_ptr(_) |
ty_opaque_box {}
ty_param(_, _) { has_params = true; }
ty_var(_) | ty_self(_) { has_vars = true; }
@ -468,7 +487,7 @@ fn mk_t_with_id(cx: ctxt, st: sty, o_def_id: option<ast::def_id>) -> t {
derive_flags(has_params, has_vars, has_rptrs, tt);
}
}
ty_box(m) | ty_uniq(m) | ty_vec(m) | ty_ptr(m) {
ty_box(m) | ty_uniq(m) | ty_vec(m) | ty_evec(m, _) | ty_ptr(m) {
derive_flags(has_params, has_vars, has_rptrs, m.ty);
}
ty_rptr(r, m) {
@ -536,6 +555,10 @@ fn mk_char(cx: ctxt) -> t { mk_t(cx, ty_int(ast::ty_char)) }
fn mk_str(cx: ctxt) -> t { mk_t(cx, ty_str) }
fn mk_estr(cx: ctxt, t: vstore) -> t {
mk_t(cx, ty_estr(t))
}
fn mk_enum(cx: ctxt, did: ast::def_id, tys: [t]) -> t {
mk_t(cx, ty_enum(did, tys))
}
@ -567,6 +590,10 @@ fn mk_nil_ptr(cx: ctxt) -> t {
fn mk_vec(cx: ctxt, tm: mt) -> t { mk_t(cx, ty_vec(tm)) }
fn mk_evec(cx: ctxt, tm: mt, t: vstore) -> t {
mk_t(cx, ty_evec(tm, t))
}
fn mk_rec(cx: ctxt, fs: [field]) -> t { mk_t(cx, ty_rec(fs)) }
fn mk_constr(cx: ctxt, t: t, cs: [@type_constr]) -> t {
@ -630,9 +657,10 @@ fn maybe_walk_ty(ty: t, f: fn(t) -> bool) {
if !f(ty) { ret; }
alt get(ty).struct {
ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
ty_str | ty_type | ty_opaque_box |
ty_str | ty_estr(_) | ty_type | ty_opaque_box |
ty_opaque_closure_ptr(_) | ty_var(_) | ty_param(_, _) {}
ty_box(tm) | ty_vec(tm) | ty_ptr(tm) | ty_rptr(_, tm) {
ty_box(tm) | ty_vec(tm) | ty_evec(tm, _) |
ty_ptr(tm) | ty_rptr(_, tm) {
maybe_walk_ty(tm.ty, f);
}
ty_enum(_, subtys) | ty_iface(_, subtys) | ty_class(_, subtys)
@ -674,6 +702,9 @@ fn fold_sty(sty: sty, fldop: fn(t) -> t) -> sty {
ty_vec(tm) {
ty_vec({ty: fldop(tm.ty), mutbl: tm.mutbl})
}
ty_evec(tm, vst) {
ty_evec({ty: fldop(tm.ty), mutbl: tm.mutbl}, vst)
}
ty_enum(tid, subtys) {
ty_enum(tid, vec::map(subtys) {|t| fldop(t) })
}
@ -718,7 +749,7 @@ fn fold_sty(sty: sty, fldop: fn(t) -> t) -> sty {
ty_class(did, new_tps)
}
ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
ty_str | ty_type | ty_opaque_closure_ptr(_) |
ty_str | ty_estr(_) | ty_type | ty_opaque_closure_ptr(_) |
ty_opaque_box | ty_var(_) | ty_param(_, _) {
sty
}
@ -751,6 +782,15 @@ fn fold_region(cx: ctxt, t0: t, fldop: fn(region, bool) -> region) -> t {
let m_t1 = do_fold(cx, t1, true, fldop);
ty::mk_rptr(cx, m_r, {ty: m_t1, mutbl: m})
}
ty_estr(vstore_slice(r)) {
let m_r = fldop(r, under_r);
ty::mk_estr(cx, vstore_slice(m_r))
}
ty_evec({ty: t1, mutbl: m}, vstore_slice(r)) {
let m_r = fldop(r, under_r);
let m_t1 = do_fold(cx, t1, true, fldop);
ty::mk_evec(cx, {ty: m_t1, mutbl: m}, vstore_slice(m_r))
}
ty_fn(_) {
// do not recurse into functions, which introduce fresh bindings
t0
@ -786,7 +826,8 @@ fn type_is_bool(ty: t) -> bool { get(ty).struct == ty_bool }
fn type_is_structural(ty: t) -> bool {
alt get(ty).struct {
ty_rec(_) | ty_class(_,_) | ty_tup(_) | ty_enum(_, _) | ty_fn(_) |
ty_iface(_, _) | ty_res(_, _, _) { true }
ty_iface(_, _) | ty_res(_, _, _) | ty_evec(_, vstore_fixed(_))
| ty_estr(vstore_fixed(_)) { true }
_ { false }
}
}
@ -797,18 +838,22 @@ fn type_is_copyable(cx: ctxt, ty: t) -> bool {
fn type_is_sequence(ty: t) -> bool {
alt get(ty).struct {
ty_str { ret true; }
ty_vec(_) { ret true; }
_ { ret false; }
ty_str | ty_estr(_) | ty_vec(_) | ty_evec(_, _) { true }
_ { false }
}
}
fn type_is_str(ty: t) -> bool { get(ty).struct == ty_str }
fn type_is_str(ty: t) -> bool {
alt get(ty).struct {
ty_str | ty_estr(_) { true }
_ { false }
}
}
fn sequence_element_type(cx: ctxt, ty: t) -> t {
alt get(ty).struct {
ty_str { ret mk_mach_uint(cx, ast::ty_u8); }
ty_vec(mt) { ret mt.ty; }
ty_str | ty_estr(_) { ret mk_mach_uint(cx, ast::ty_u8); }
ty_vec(mt) | ty_evec(mt, _) { ret mt.ty; }
_ { cx.sess.bug("sequence_element_type called on non-sequence value"); }
}
}
@ -858,8 +903,8 @@ pure fn type_is_unsafe_ptr(ty: t) -> bool {
pure fn type_is_vec(ty: t) -> bool {
ret alt get(ty).struct {
ty_vec(_) { true }
ty_str { true }
ty_vec(_) | ty_evec(_, _) { true }
ty_str | ty_estr(_) { true }
_ { false }
};
}
@ -867,8 +912,8 @@ pure fn type_is_vec(ty: t) -> bool {
pure fn type_is_unique(ty: t) -> bool {
alt get(ty).struct {
ty_uniq(_) { ret true; }
ty_vec(_) { true }
ty_str { true }
ty_vec(_) | ty_evec(_, vstore_uniq) { true }
ty_str | ty_estr(vstore_uniq) { true }
_ { ret false; }
}
}
@ -897,7 +942,10 @@ fn type_needs_drop(cx: ctxt, ty: t) -> bool {
let result = alt get(ty).struct {
// scalar types
ty_nil | ty_bot | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) |
ty_type | ty_ptr(_) | ty_rptr(_, _) { false }
ty_type | ty_ptr(_) | ty_rptr(_, _) |
ty_estr(vstore_fixed(_)) | ty_estr(vstore_slice(_)) |
ty_evec(_, vstore_slice(_)) { false }
ty_evec(mt, vstore_fixed(_)) { type_needs_drop(cx, mt.ty) }
ty_rec(flds) {
for flds.each {|f| if type_needs_drop(cx, f.mt.ty) { accum = true; } }
accum
@ -983,7 +1031,12 @@ fn type_needs_unwind_cleanup_(cx: ctxt, ty: t,
}
!needs_unwind_cleanup
}
ty_uniq(_) | ty_str | ty_vec(_) | ty_res(_, _, _) {
ty_uniq(_) | ty_str | ty_vec(_) | ty_res(_, _, _) |
ty_estr(vstore_uniq) |
ty_estr(vstore_box) |
ty_evec(_, vstore_uniq) |
ty_evec(_, vstore_box)
{
// Once we're inside a box, the annihilator will find
// it and destroy it.
if !encountered_box {
@ -1046,6 +1099,17 @@ fn lower_kind(a: kind, b: kind) -> kind {
if kind_lteq(a, b) { a } else { b }
}
#[test]
fn test_kinds() {
// The kind "lattice" is nocopy <= copy <= send
assert kind_lteq(kind_sendable, kind_sendable);
assert kind_lteq(kind_copyable, kind_sendable);
assert kind_lteq(kind_copyable, kind_copyable);
assert kind_lteq(kind_noncopyable, kind_sendable);
assert kind_lteq(kind_noncopyable, kind_copyable);
assert kind_lteq(kind_noncopyable, kind_noncopyable);
}
fn type_kind(cx: ctxt, ty: t) -> kind {
alt cx.kind_cache.find(ty) {
some(result) { ret result; }
@ -1061,15 +1125,33 @@ fn type_kind(cx: ctxt, ty: t) -> kind {
ty_ptr(_) | ty_str { kind_sendable }
ty_type { kind_copyable }
ty_fn(f) { proto_kind(f.proto) }
// Closures have kind determined by capture mode
ty_opaque_closure_ptr(ck_block) { kind_noncopyable }
ty_opaque_closure_ptr(ck_box) { kind_copyable }
ty_opaque_closure_ptr(ck_uniq) { kind_sendable }
// Those with refcounts-to-inner raise pinned to shared,
// lower unique to shared. Therefore just set result to shared.
// Those with refcounts raise noncopyable to copyable,
// lower sendable to copyable. Therefore just set result to copyable.
ty_box(_) | ty_iface(_, _) | ty_opaque_box { kind_copyable }
ty_rptr(_, _) { kind_copyable }
// Boxes and unique pointers raise pinned to shared.
// Unique boxes and vecs have the kind of their contained type.
ty_vec(tm) | ty_uniq(tm) { type_kind(cx, tm.ty) }
// Slice and refcounted evecs are copyable; uniques and interiors
// depend on the their contained type.
ty_evec(_, vstore_box) |
ty_evec(_, vstore_slice(_)) { kind_copyable }
ty_evec(tm, vstore_uniq) |
ty_evec(tm, vstore_fixed(_)) { type_kind(cx, tm.ty) }
// All estrs are copyable; uniques and interiors are sendable.
ty_estr(vstore_box) |
ty_estr(vstore_slice(_)) { kind_copyable }
ty_estr(vstore_uniq) |
ty_estr(vstore_fixed(_)) { kind_sendable }
// Records lower to the lowest of their members.
ty_rec(flds) {
let mut lowest = kind_sendable;
@ -1152,6 +1234,7 @@ fn is_instantiable(cx: ctxt, r_ty: t) -> bool {
ty_uint(_) |
ty_float(_) |
ty_str |
ty_estr(_) |
ty_fn(_) |
ty_var(_) |
ty_param(_, _) |
@ -1159,6 +1242,7 @@ fn is_instantiable(cx: ctxt, r_ty: t) -> bool {
ty_type |
ty_opaque_box |
ty_opaque_closure_ptr(_) |
ty_evec(_, _) |
ty_vec(_) {
false
}
@ -1277,6 +1361,9 @@ fn type_structurally_contains(cx: ctxt, ty: t, test: fn(sty) -> bool) ->
let sty = substitute_type_params(cx, tps, sub);
ret type_structurally_contains(cx, sty, test);
}
ty_evec(mt, vstore_fixed(_)) {
ret type_structurally_contains(cx, mt.ty, test);
}
_ { ret false; }
}
}
@ -1288,6 +1375,11 @@ fn type_allows_implicit_copy(cx: ctxt, ty: t) -> bool {
ret !type_structurally_contains(cx, ty, {|sty|
alt sty {
ty_param(_, _) { true }
ty_evec(_, _) | ty_estr(_) {
cx.sess.unimpl("estr/evec in type_allows_implicit_copy");
}
ty_vec(mt) {
mt.mutbl != ast::m_imm
}
@ -1302,9 +1394,11 @@ fn type_allows_implicit_copy(cx: ctxt, ty: t) -> bool {
fn type_structurally_contains_uniques(cx: ctxt, ty: t) -> bool {
ret type_structurally_contains(cx, ty, {|sty|
alt sty {
ty_uniq(_) { true }
ty_vec(_) { true }
ty_str { true }
ty_uniq(_) |
ty_vec(_) |
ty_evec(_, vstore_uniq) |
ty_str |
ty_estr(vstore_uniq) { true }
_ { false }
}
});
@ -1365,6 +1459,10 @@ fn type_is_pod(cx: ctxt, ty: t) -> bool {
ty_tup(elts) {
for elts.each {|elt| if !type_is_pod(cx, elt) { result = false; } }
}
ty_estr(vstore_fixed(_)) { result = true; }
ty_evec(mt, vstore_fixed(_)) {
result = type_is_pod(cx, mt.ty);
}
ty_res(_, inner, tps) {
result = type_is_pod(cx, substitute_type_params(cx, tps, inner));
}
@ -1503,6 +1601,7 @@ fn hash_type_structure(st: sty) -> uint {
ty_float(t) {
alt t { ast::ty_f { 13u } ast::ty_f32 { 14u } ast::ty_f64 { 15u } }
}
ty_estr(_) { 16u }
ty_str { 17u }
ty_enum(did, tys) {
let mut h = hash_def(18u, did);
@ -1510,6 +1609,7 @@ fn hash_type_structure(st: sty) -> uint {
h
}
ty_box(mt) { hash_subty(19u, mt.ty) }
ty_evec(mt, _) { hash_subty(20u, mt.ty) }
ty_vec(mt) { hash_subty(21u, mt.ty) }
ty_rec(fields) {
let mut h = 26u;
@ -1849,15 +1949,15 @@ fn set_default_mode(cx: ctxt, m: ast::mode, m_def: ast::rmode) {
fn ty_sort_str(cx: ctxt, t: t) -> str {
alt get(t).struct {
ty_nil | ty_bot | ty_bool | ty_int(_) |
ty_uint(_) | ty_float(_) | ty_str | ty_type | ty_opaque_box |
ty_opaque_closure_ptr(_) {
ty_uint(_) | ty_float(_) | ty_estr(_) | ty_str |
ty_type | ty_opaque_box | ty_opaque_closure_ptr(_) {
ty_to_str(cx, t)
}
ty_enum(_, _) { "enum" }
ty_box(_) { "@-ptr" }
ty_uniq(_) { "~-ptr" }
ty_vec(_) { "vector" }
ty_evec(_, _) | ty_vec(_) { "vector" }
ty_ptr(_) { "*-ptr" }
ty_rptr(_, _) { "&-ptr" }
ty_rec(_) { "record" }
@ -2312,14 +2412,11 @@ fn is_binopable(_cx: ctxt, ty: t, op: ast::binop) -> bool {
fn tycat(ty: t) -> int {
alt get(ty).struct {
ty_bool { tycat_bool }
ty_int(_) { tycat_int }
ty_uint(_) { tycat_int }
ty_int(_) | ty_uint(_) { tycat_int }
ty_float(_) { tycat_float }
ty_str { tycat_str }
ty_vec(_) { tycat_vec }
ty_rec(_) { tycat_struct }
ty_tup(_) { tycat_struct }
ty_enum(_, _) { tycat_struct }
ty_estr(_) | ty_str { tycat_str }
ty_evec(_, _) | ty_vec(_) { tycat_vec }
ty_rec(_) | ty_tup(_) | ty_enum(_, _) { tycat_struct }
ty_bot { tycat_bot }
_ { tycat_other }
}

View file

@ -276,6 +276,53 @@ fn type_is_c_like_enum(fcx: @fn_ctxt, sp: span, typ: ty::t) -> bool {
enum mode { m_collect, m_check, m_check_tyvar(@fn_ctxt), }
fn ast_region_to_region(tcx: ty::ctxt,
region: ast::region) -> ty::region {
alt region.node {
ast::re_inferred {
// this must be replaced later by a fixup_regions() pass
ty::re_default
}
ast::re_self | ast::re_named(_) {
tcx.region_map.ast_type_to_region.get(region.id)
}
ast::re_static {
ty::re_static
}
}
}
fn ast_vstore_to_vstore(tcx: ty::ctxt, span: span, n: option<uint>,
v: ast::vstore) -> ty::vstore {
alt v {
ast::vstore_fixed(none) {
alt n {
some(n) { ty::vstore_fixed(n) }
none {
tcx.sess.bug("implied fixed length in ast_vstore_to_vstore with \
no default length")
}
}
}
ast::vstore_fixed(some(u)) {
alt n {
some(n) if n != u {
tcx.sess.span_err(span,
#fmt("fixed-size sequence mismatch: %u vs. %u",
u, n));
}
_ { }
}
ty::vstore_fixed(u)
}
ast::vstore_uniq { ty::vstore_uniq }
ast::vstore_box { ty::vstore_box }
ast::vstore_slice(region) {
ty::vstore_slice(ast_region_to_region(tcx, region))
}
}
}
// Parses the programmer's textual representation of a type into our
// internal notion of a type. `getter` is a function that returns the type
// corresponding to a definition ID:
@ -361,19 +408,8 @@ fn ast_ty_to_ty(tcx: ty::ctxt, mode: mode, &&ast_ty: @ast::ty) -> ty::t {
ty::mk_ptr(tcx, ast_mt_to_mt(tcx, mode, mt))
}
ast::ty_rptr(region, mt) {
let r = alt region.node {
ast::re_inferred {
// this must be replaced later by a fixup_regions() pass
ty::re_default
}
ast::re_self | ast::re_named(_) {
tcx.region_map.ast_type_to_region.get(region.id)
}
ast::re_static {
ty::re_static
}
};
ty::mk_rptr(tcx, r, ast_mt_to_mt(tcx, mode, mt))
let region = ast_region_to_region(tcx, region);
ty::mk_rptr(tcx, region, ast_mt_to_mt(tcx, mode, mt))
}
ast::ty_tup(fields) {
let flds = vec::map(fields, bind do_ast_ty_to_ty(tcx, mode, _));
@ -436,6 +472,18 @@ fn ast_ty_to_ty(tcx: ty::ctxt, mode: mode, &&ast_ty: @ast::ty) -> ty::t {
}
}
}
ast::ty_vstore(t, vst) {
let vst = ast_vstore_to_vstore(tcx, ast_ty.span, none, vst);
alt ty::get(do_ast_ty_to_ty(tcx, mode, t)).struct {
ty::ty_vec(mt) { ty::mk_evec(tcx, mt, vst) }
ty::ty_str { ty::mk_estr(tcx, vst) }
_ {
tcx.sess.span_fatal(ast_ty.span,
"found sequence storage modifier \
on non-sequence type");
}
}
}
ast::ty_constr(t, cs) {
let mut out_cs = [];
for cs.each {|constr|
@ -2799,6 +2847,31 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
let id = expr.id;
let mut bot = false;
alt expr.node {
ast::expr_vstore(ev, vst) {
alt ev.node {
ast::expr_lit(@{node: ast::lit_str(s), span:_}) {
let tt = ast_vstore_to_vstore(tcx, expr.span,
some(str::len(s)), vst);
let typ = ty::mk_estr(tcx, tt);
fcx.write_ty(ev.id, typ);
fcx.write_ty(id, typ);
}
ast::expr_vec(args, mutbl) {
let tt = ast_vstore_to_vstore(tcx, expr.span,
some(vec::len(args)), vst);
let t: ty::t = next_ty_var(fcx);
for args.each {|e| bot |= check_expr_with(fcx, e, t); }
let typ = ty::mk_evec(tcx, {ty: t, mutbl: mutbl}, tt);
fcx.write_ty(ev.id, typ);
fcx.write_ty(id, typ);
}
_ {
tcx.sess.span_err(expr.span, "vstore modifier on non-sequence");
}
}
}
ast::expr_lit(lit) {
let typ = check_lit(fcx.ccx, lit);
fcx.write_ty(id, typ);
@ -3319,10 +3392,12 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
bot |= check_expr(fcx, idx);
let idx_t = fcx.expr_ty(idx);
alt structure_of(fcx, expr.span, base_t) {
ty::ty_evec(mt, _) |
ty::ty_vec(mt) {
require_integral(fcx, idx.span, idx_t);
fcx.write_ty(id, mt.ty);
}
ty::ty_estr(_) |
ty::ty_str {
require_integral(fcx, idx.span, idx_t);
let typ = ty::mk_mach_uint(tcx, ast::ty_u8);

View file

@ -1,9 +1,8 @@
// xfail-test
fn main() {
let x : str/5 = "hello"/5;
let y : str/5 = "there"/_;
let _y : str/5 = "there"/_;
let mut z = "thing"/_;
z = x;
assert z[1] == 'h' as u8;
assert z[4] == 'g' as u8;
assert z[0] == ('h' as u8);
assert z[4] == ('o' as u8);
}