Change decl to local in expr_for and expr_for_each
Since the decl in a for or for-each loop must always be a local decl, I changed the AST to express this. Fewer potential match failures and "the impossible happened" error messages = yay!
This commit is contained in:
parent
ff8af3c2db
commit
d65ad8c31c
15 changed files with 149 additions and 222 deletions
|
@ -221,16 +221,17 @@ tag init_op {
|
|||
type initializer = rec(init_op op,
|
||||
@expr expr);
|
||||
|
||||
type local = rec(option::t[@ty] ty,
|
||||
type local_ = rec(option::t[@ty] ty,
|
||||
bool infer,
|
||||
ident ident,
|
||||
option::t[initializer] init,
|
||||
def_id id,
|
||||
ann ann);
|
||||
type local = spanned[@local_];
|
||||
|
||||
type decl = spanned[decl_];
|
||||
tag decl_ {
|
||||
decl_local(@local);
|
||||
decl_local(@local_);
|
||||
decl_item(@item);
|
||||
}
|
||||
|
||||
|
@ -266,8 +267,8 @@ tag expr_ {
|
|||
expr_cast(@expr, @ty, ann);
|
||||
expr_if(@expr, block, option::t[@expr], ann);
|
||||
expr_while(@expr, block, ann);
|
||||
expr_for(@decl, @expr, block, ann);
|
||||
expr_for_each(@decl, @expr, block, ann);
|
||||
expr_for(@local, @expr, block, ann);
|
||||
expr_for_each(@local, @expr, block, ann);
|
||||
expr_do_while(block, @expr, ann);
|
||||
expr_alt(@expr, vec[arm], ann);
|
||||
expr_block(block, ann);
|
||||
|
|
|
@ -1367,15 +1367,14 @@ fn parse_else_expr(&parser p) -> @ast::expr {
|
|||
}
|
||||
}
|
||||
|
||||
fn parse_head_local(&parser p) -> @ast::decl {
|
||||
fn parse_head_local(&parser p) -> @ast::local {
|
||||
auto lo = p.get_lo_pos();
|
||||
let @ast::local local;
|
||||
if (is_word(p, "auto")) {
|
||||
local = parse_auto_local(p);
|
||||
} else {
|
||||
local = parse_typed_local(p);
|
||||
}
|
||||
ret @spanned(lo, p.get_hi_pos(), ast::decl_local(local));
|
||||
let @ast::local_ l = if (is_word(p, "auto")) {
|
||||
parse_auto_local(p)
|
||||
} else {
|
||||
parse_typed_local(p)
|
||||
};
|
||||
ret @spanned(lo, p.get_hi_pos(), l);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1567,7 +1566,7 @@ fn parse_pat(&parser p) -> @ast::pat {
|
|||
}
|
||||
|
||||
fn parse_local_full(&option::t[@ast::ty] tyopt,
|
||||
&parser p) -> @ast::local {
|
||||
&parser p) -> @ast::local_ {
|
||||
auto ident = parse_value_ident(p);
|
||||
auto init = parse_initializer(p);
|
||||
ret @rec(ty = tyopt,
|
||||
|
@ -1578,12 +1577,12 @@ fn parse_local_full(&option::t[@ast::ty] tyopt,
|
|||
ann = p.get_ann());
|
||||
}
|
||||
|
||||
fn parse_typed_local(&parser p) -> @ast::local {
|
||||
fn parse_typed_local(&parser p) -> @ast::local_ {
|
||||
auto ty = parse_ty(p);
|
||||
ret parse_local_full(some(ty), p);
|
||||
}
|
||||
|
||||
fn parse_auto_local(&parser p) -> @ast::local {
|
||||
fn parse_auto_local(&parser p) -> @ast::local_ {
|
||||
ret parse_local_full(none[@ast::ty], p);
|
||||
}
|
||||
|
||||
|
|
|
@ -247,15 +247,13 @@ fn arm_defnums(&ast::arm arm) -> vec[def_num] {
|
|||
ret dnums;
|
||||
}
|
||||
|
||||
fn check_for_each(&ctx cx, &@ast::decl decl, &@ast::expr call,
|
||||
fn check_for_each(&ctx cx, &@ast::local local, &@ast::expr call,
|
||||
&ast::block block, &scope sc, &vt[scope] v) {
|
||||
visit::visit_expr(call, sc, v);
|
||||
alt (call.node) {
|
||||
case (ast::expr_call(?f, ?args, _)) {
|
||||
auto data = check_call(cx, f, args, sc);
|
||||
auto defnum = alt (decl.node) {
|
||||
case (ast::decl_local(?l)) { l.id._1 }
|
||||
};
|
||||
auto defnum = local.node.id._1;
|
||||
|
||||
auto new_sc = @rec(root_vars=data.root_vars,
|
||||
block_defnum=defnum,
|
||||
|
@ -268,12 +266,10 @@ fn check_for_each(&ctx cx, &@ast::decl decl, &@ast::expr call,
|
|||
}
|
||||
}
|
||||
|
||||
fn check_for(&ctx cx, &@ast::decl decl, &@ast::expr seq,
|
||||
fn check_for(&ctx cx, &@ast::local local, &@ast::expr seq,
|
||||
&ast::block block, &scope sc, &vt[scope] v) {
|
||||
visit::visit_expr(seq, sc, v);
|
||||
auto defnum = alt (decl.node) {
|
||||
case (ast::decl_local(?l)) { l.id._1 }
|
||||
};
|
||||
auto defnum = local.node.id._1;
|
||||
|
||||
auto root = expr_root(cx, seq, false);
|
||||
auto root_def = alt (path_def_id(cx, root.ex)) {
|
||||
|
|
|
@ -39,7 +39,7 @@ tag scope {
|
|||
scope_item(@ast::item);
|
||||
scope_fn(ast::fn_decl, vec[ast::ty_param]);
|
||||
scope_native_item(@ast::native_item);
|
||||
scope_loop(@ast::decl); // there's only 1 decl per loop.
|
||||
scope_loop(@ast::local_); // there's only 1 decl per loop.
|
||||
scope_block(ast::block);
|
||||
scope_arm(ast::arm);
|
||||
}
|
||||
|
@ -341,10 +341,10 @@ fn visit_arm_with_scope(&ast::arm a, &scopes sc, &vt[scopes] v) {
|
|||
fn visit_expr_with_scope(&@ast::expr x, &scopes sc, &vt[scopes] v) {
|
||||
auto new_sc = alt (x.node) {
|
||||
case (ast::expr_for(?d, _, _, _)) {
|
||||
cons[scope](scope_loop(d), @sc)
|
||||
cons[scope](scope_loop(d.node), @sc)
|
||||
}
|
||||
case (ast::expr_for_each(?d, _, _, _)) {
|
||||
cons[scope](scope_loop(d), @sc)
|
||||
cons[scope](scope_loop(d.node), @sc)
|
||||
}
|
||||
case (_) { sc }
|
||||
};
|
||||
|
@ -540,14 +540,10 @@ fn lookup_in_scope(&env e, scopes sc, &span sp, &ident id, namespace ns)
|
|||
case (scope_fn(?decl, ?ty_params)) {
|
||||
ret lookup_in_fn(id, decl, ty_params, ns);
|
||||
}
|
||||
case (scope_loop(?d)) {
|
||||
case (scope_loop(?local)) {
|
||||
if (ns == ns_value) {
|
||||
alt (d.node) {
|
||||
case (ast::decl_local(?local)) {
|
||||
if (str::eq(local.ident, id)) {
|
||||
ret some(ast::def_local(local.id));
|
||||
}
|
||||
}
|
||||
if (str::eq(local.ident, id)) {
|
||||
ret some(ast::def_local(local.id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4004,11 +4004,11 @@ fn trans_if(&@block_ctxt cx, &@ast::expr cond,
|
|||
}
|
||||
|
||||
fn trans_for(&@block_ctxt cx,
|
||||
&@ast::decl decl,
|
||||
&@ast::local local,
|
||||
&@ast::expr seq,
|
||||
&ast::block body) -> result {
|
||||
fn inner(&@block_ctxt cx,
|
||||
@ast::local local, ValueRef curr,
|
||||
@ast::local_ local, ValueRef curr,
|
||||
ty::t t, ast::block body,
|
||||
@block_ctxt outer_next_cx) -> result {
|
||||
|
||||
|
@ -4027,19 +4027,11 @@ fn trans_for(&@block_ctxt cx,
|
|||
ret res(next_cx, C_nil());
|
||||
}
|
||||
|
||||
|
||||
let @ast::local local;
|
||||
alt (decl.node) {
|
||||
case (ast::decl_local(?loc)) {
|
||||
local = loc;
|
||||
}
|
||||
}
|
||||
|
||||
auto next_cx = new_sub_block_ctxt(cx, "next");
|
||||
auto seq_ty = ty::expr_ty(cx.fcx.lcx.ccx.tcx, seq);
|
||||
auto seq_res = trans_expr(cx, seq);
|
||||
auto it = iter_sequence(seq_res.bcx, seq_res.val, seq_ty,
|
||||
bind inner(_, local, _, _, body, next_cx));
|
||||
bind inner(_, local.node, _, _, body, next_cx));
|
||||
it.bcx.build.Br(next_cx.llbb);
|
||||
ret res(next_cx, it.val);
|
||||
}
|
||||
|
@ -4074,13 +4066,8 @@ fn collect_upvars(&@block_ctxt cx, &ast::block bloc,
|
|||
}
|
||||
}
|
||||
|
||||
fn walk_decl(env e, &@ast::decl decl) {
|
||||
alt (decl.node) {
|
||||
case (ast::decl_local(?local)) {
|
||||
e.decls.insert(local.id, ());
|
||||
}
|
||||
case (_) {}
|
||||
}
|
||||
fn walk_local(env e, &@ast::local local) {
|
||||
e.decls.insert(local.node.id, ());
|
||||
}
|
||||
|
||||
let vec[ast::def_id] refs = [];
|
||||
|
@ -4090,7 +4077,7 @@ fn collect_upvars(&@block_ctxt cx, &ast::block bloc,
|
|||
decls=decls,
|
||||
def_map=cx.fcx.lcx.ccx.tcx.def_map);
|
||||
|
||||
auto visitor = @rec(visit_decl_pre = bind walk_decl(e, _),
|
||||
auto visitor = @rec(visit_local_pre = bind walk_local(e, _),
|
||||
visit_expr_pre = bind walk_expr(e, _)
|
||||
with walk::default_visitor());
|
||||
walk::walk_block(*visitor, bloc);
|
||||
|
@ -4108,7 +4095,7 @@ fn collect_upvars(&@block_ctxt cx, &ast::block bloc,
|
|||
}
|
||||
|
||||
fn trans_for_each(&@block_ctxt cx,
|
||||
&@ast::decl decl,
|
||||
&@ast::local local,
|
||||
&@ast::expr seq,
|
||||
&ast::block body) -> result {
|
||||
/*
|
||||
|
@ -4139,14 +4126,8 @@ fn trans_for_each(&@block_ctxt cx,
|
|||
|
||||
auto lcx = cx.fcx.lcx;
|
||||
// FIXME: possibly support alias-mode here?
|
||||
auto decl_ty = ty::mk_nil(lcx.ccx.tcx);
|
||||
auto decl_id;
|
||||
alt (decl.node) {
|
||||
case (ast::decl_local(?local)) {
|
||||
decl_ty = node_ann_type(lcx.ccx, local.ann);
|
||||
decl_id = local.id;
|
||||
}
|
||||
}
|
||||
auto decl_ty = node_ann_type(lcx.ccx, local.node.ann);
|
||||
auto decl_id = local.node.id;
|
||||
|
||||
auto upvars = collect_upvars(cx, body, decl_id);
|
||||
auto upvar_count = vec::len[ast::def_id](upvars);
|
||||
|
@ -6901,7 +6882,7 @@ fn trans_anon_obj(@block_ctxt cx, &span sp,
|
|||
ret res(bcx, pair);
|
||||
}
|
||||
|
||||
fn init_local(&@block_ctxt cx, &@ast::local local) -> result {
|
||||
fn init_local(&@block_ctxt cx, &@ast::local_ local) -> result {
|
||||
|
||||
// Make a note to drop this slot on the way out.
|
||||
assert (cx.fcx.lllocals.contains_key(local.id));
|
||||
|
@ -7064,7 +7045,7 @@ fn trans_block_cleanups(&@block_ctxt cx,
|
|||
ret bcx;
|
||||
}
|
||||
|
||||
iter block_locals(&ast::block b) -> @ast::local {
|
||||
iter block_locals(&ast::block b) -> @ast::local_ {
|
||||
// FIXME: putting from inside an iter block doesn't work, so we can't
|
||||
// use the index here.
|
||||
for (@ast::stmt s in b.node.stmts) {
|
||||
|
@ -7117,7 +7098,7 @@ fn alloc_ty(&@block_ctxt cx, &ty::t t) -> result {
|
|||
ret res(cx, val);
|
||||
}
|
||||
|
||||
fn alloc_local(&@block_ctxt cx, &@ast::local local) -> result {
|
||||
fn alloc_local(&@block_ctxt cx, &@ast::local_ local) -> result {
|
||||
auto t = node_ann_type(cx.fcx.lcx.ccx, local.ann);
|
||||
auto r = alloc_ty(cx, t);
|
||||
r.bcx.fcx.lllocals.insert(local.id, r.val);
|
||||
|
@ -7126,7 +7107,7 @@ fn alloc_local(&@block_ctxt cx, &@ast::local local) -> result {
|
|||
|
||||
fn trans_block(&@block_ctxt cx, &ast::block b, &out_method output) -> result {
|
||||
auto bcx = cx;
|
||||
for each (@ast::local local in block_locals(b)) {
|
||||
for each (@ast::local_ local in block_locals(b)) {
|
||||
*bcx = rec(sp=local_rhs_span(local, cx.sp) with *bcx);
|
||||
bcx = alloc_local(bcx, local).bcx;
|
||||
}
|
||||
|
|
|
@ -3,39 +3,7 @@ import std::option;
|
|||
import std::option::some;
|
||||
import std::option::none;
|
||||
|
||||
import front::ast;
|
||||
import front::ast::ident;
|
||||
import front::ast::def_id;
|
||||
import front::ast::ann;
|
||||
import front::ast::item;
|
||||
import front::ast::_fn;
|
||||
import front::ast::_mod;
|
||||
import front::ast::crate;
|
||||
import front::ast::_obj;
|
||||
import front::ast::ty_param;
|
||||
import front::ast::item_fn;
|
||||
import front::ast::item_obj;
|
||||
import front::ast::item_ty;
|
||||
import front::ast::item_tag;
|
||||
import front::ast::item_const;
|
||||
import front::ast::item_mod;
|
||||
import front::ast::item_native_mod;
|
||||
import front::ast::expr;
|
||||
import front::ast::elt;
|
||||
import front::ast::field;
|
||||
import front::ast::decl;
|
||||
import front::ast::decl_local;
|
||||
import front::ast::decl_item;
|
||||
import front::ast::initializer;
|
||||
import front::ast::local;
|
||||
import front::ast::arm;
|
||||
import front::ast::stmt;
|
||||
import front::ast::stmt_decl;
|
||||
import front::ast::stmt_expr;
|
||||
import front::ast::block;
|
||||
import front::ast::block_;
|
||||
import front::ast::method;
|
||||
|
||||
import front::ast::*;
|
||||
import middle::ty::expr_ann;
|
||||
|
||||
import util::common::uistr;
|
||||
|
@ -82,13 +50,8 @@ fn collect_ids_stmt(&@stmt s, @mutable vec[uint] res) -> () {
|
|||
}
|
||||
}
|
||||
|
||||
fn collect_ids_decl(&@decl d, @mutable vec[uint] res) -> () {
|
||||
alt (d.node) {
|
||||
case (decl_local(?l)) {
|
||||
vec::push(*res, l.ann.id);
|
||||
}
|
||||
case (_) {}
|
||||
}
|
||||
fn collect_ids_local(&@local l, @mutable vec[uint] res) -> () {
|
||||
vec::push(*res, l.node.ann.id);
|
||||
}
|
||||
|
||||
fn node_ids_in_fn(&_fn f, &span sp, &ident i, &def_id d, &ann a,
|
||||
|
@ -97,7 +60,7 @@ fn node_ids_in_fn(&_fn f, &span sp, &ident i, &def_id d, &ann a,
|
|||
collect_ids = rec(visit_expr_pre = bind collect_ids_expr(_,res),
|
||||
visit_block_pre = bind collect_ids_block(_,res),
|
||||
visit_stmt_pre = bind collect_ids_stmt(_,res),
|
||||
visit_decl_pre = bind collect_ids_decl(_,res)
|
||||
visit_local_pre = bind collect_ids_local(_,res)
|
||||
with collect_ids);
|
||||
walk::walk_fn(collect_ids, f, sp, i, d, a);
|
||||
}
|
||||
|
|
|
@ -31,15 +31,10 @@ import util::common::respan;
|
|||
type ctxt = rec(@mutable vec[constr] cs,
|
||||
ty::ctxt tcx);
|
||||
|
||||
fn collect_local(&ctxt cx, &@decl d) -> () {
|
||||
alt (d.node) {
|
||||
case (decl_local(?loc)) {
|
||||
log("collect_local: pushing " + loc.ident);
|
||||
vec::push[constr](*cx.cs, respan(d.span,
|
||||
ninit(loc.ident, loc.id)));
|
||||
}
|
||||
case (_) { ret; }
|
||||
}
|
||||
fn collect_local(&ctxt cx, &@local loc) -> () {
|
||||
log("collect_local: pushing " + loc.node.ident);
|
||||
vec::push[constr](*cx.cs, respan(loc.span,
|
||||
ninit(loc.node.ident, loc.node.id)));
|
||||
}
|
||||
|
||||
fn collect_pred(&ctxt cx, &@expr e) -> () {
|
||||
|
@ -77,7 +72,7 @@ fn find_locals(&ty::ctxt tcx, &_fn f, &span sp, &ident i, &def_id d, &ann a)
|
|||
-> ctxt {
|
||||
let ctxt cx = rec(cs=@mutable vec::alloc[constr](0u), tcx=tcx);
|
||||
auto visitor = walk::default_visitor();
|
||||
visitor = rec(visit_decl_pre=bind collect_local(cx,_),
|
||||
visitor = rec(visit_local_pre=bind collect_local(cx,_),
|
||||
visit_expr_pre=bind collect_pred(cx,_)
|
||||
with visitor);
|
||||
walk_fn(visitor, f, sp, i, d, a);
|
||||
|
|
|
@ -170,12 +170,11 @@ fn find_pre_post_exprs(&fn_ctxt fcx, &vec[@expr] args, ann a) {
|
|||
(nv, (vec::map[pre_and_post, postcond](h, pps))));
|
||||
}
|
||||
|
||||
fn find_pre_post_loop(&fn_ctxt fcx, &@decl d, &@expr index,
|
||||
fn find_pre_post_loop(&fn_ctxt fcx, &@local l, &@expr index,
|
||||
&block body, &ann a) -> () {
|
||||
find_pre_post_expr(fcx, index);
|
||||
find_pre_post_block(fcx, body);
|
||||
log("222");
|
||||
auto loop_precond = declare_var(fcx, decl_lhs(d),
|
||||
auto loop_precond = declare_var(fcx, l.node.id,
|
||||
seq_preconds(fcx, [expr_pp(fcx.ccx, index), block_pp(fcx.ccx, body)]));
|
||||
auto loop_postcond = intersect_postconds
|
||||
([expr_postcond(fcx.ccx, index), block_postcond(fcx.ccx, body)]);
|
||||
|
@ -448,11 +447,11 @@ fn find_pre_post_expr(&fn_ctxt fcx, @expr e) -> () {
|
|||
loop_postcond = empty_poststate(num_local_vars);
|
||||
}
|
||||
|
||||
log "777";
|
||||
|
||||
set_pre_and_post(fcx.ccx, a, seq_preconds(fcx,
|
||||
[block_pp(fcx.ccx, body),
|
||||
expr_pp(fcx.ccx, test)]),
|
||||
loop_postcond);
|
||||
[block_pp(fcx.ccx, body),
|
||||
expr_pp(fcx.ccx, test)]),
|
||||
loop_postcond);
|
||||
}
|
||||
case (expr_for(?d, ?index, ?body, ?a)) {
|
||||
find_pre_post_loop(fcx, d, index, body, a);
|
||||
|
|
|
@ -104,11 +104,12 @@ fn find_pre_post_state_exprs(&fn_ctxt fcx, &prestate pres,
|
|||
ret changed;
|
||||
}
|
||||
|
||||
fn find_pre_post_state_loop(&fn_ctxt fcx, prestate pres, &@decl d,
|
||||
fn find_pre_post_state_loop(&fn_ctxt fcx, prestate pres, &@local l,
|
||||
&@expr index, &block body, &ann a) -> bool {
|
||||
auto changed = false;
|
||||
|
||||
/* same issues as while */
|
||||
// FIXME: also want to set l as initialized, no?
|
||||
changed = extend_prestate_ann(fcx.ccx, a, pres) || changed;
|
||||
changed = find_pre_post_state_expr(fcx, pres, index) || changed;
|
||||
/* in general, would need the intersection of
|
||||
|
|
|
@ -1698,15 +1698,8 @@ fn expr_has_ty_params(&ctxt cx, &@ast::expr expr) -> bool {
|
|||
ret ann_has_type_params(cx, expr_ann(expr));
|
||||
}
|
||||
|
||||
fn decl_local_ty(&ctxt cx, &@ast::decl d) -> t {
|
||||
alt (d.node) {
|
||||
case (ast::decl_local(?l)) {
|
||||
ret ann_to_type(cx, l.ann);
|
||||
}
|
||||
case (_) {
|
||||
cx.sess.bug("decl_local_ty called on an item decl");
|
||||
}
|
||||
}
|
||||
fn decl_local_ty(&ctxt cx, &@ast::local_ l) -> t {
|
||||
ret ann_to_type(cx, l.ann);
|
||||
}
|
||||
|
||||
fn stmt_ann(&@ast::stmt s) -> ast::ann {
|
||||
|
|
|
@ -1084,24 +1084,19 @@ mod writeback {
|
|||
resolve_type_vars_for_node(fcx, p.span, ty::pat_ann(p));
|
||||
}
|
||||
|
||||
fn visit_decl_pre(@fn_ctxt fcx, &@ast::decl d) {
|
||||
alt (d.node) {
|
||||
case (ast::decl_local(?l)) {
|
||||
auto var_id = fcx.locals.get(l.id);
|
||||
auto fix_rslt = ty::unify::resolve_type_var(fcx.ccx.tcx,
|
||||
fcx.var_bindings, var_id);
|
||||
alt (fix_rslt) {
|
||||
case (fix_ok(?lty)) {
|
||||
write::ty_only(fcx.ccx.tcx, l.ann.id, lty);
|
||||
}
|
||||
case (fix_err(_)) {
|
||||
fcx.ccx.tcx.sess.span_err(d.span,
|
||||
"cannot determine a type for this local " +
|
||||
"variable");
|
||||
}
|
||||
}
|
||||
fn visit_local_pre(@fn_ctxt fcx, &@ast::local l) {
|
||||
auto var_id = fcx.locals.get(l.node.id);
|
||||
auto fix_rslt = ty::unify::resolve_type_var(fcx.ccx.tcx,
|
||||
fcx.var_bindings, var_id);
|
||||
alt (fix_rslt) {
|
||||
case (fix_ok(?lty)) {
|
||||
write::ty_only(fcx.ccx.tcx, l.node.ann.id, lty);
|
||||
}
|
||||
case (fix_err(_)) {
|
||||
fcx.ccx.tcx.sess.span_err(l.span,
|
||||
"cannot determine a type for this local " +
|
||||
"variable");
|
||||
}
|
||||
case (_) { /* no-op */ }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1123,7 +1118,7 @@ mod writeback {
|
|||
visit_expr_pre=bind visit_expr_pre(fcx, _),
|
||||
visit_block_pre=bind visit_block_pre(fcx, _),
|
||||
visit_pat_pre=bind visit_pat_pre(fcx, _),
|
||||
visit_decl_pre=bind visit_decl_pre(fcx, _)
|
||||
visit_local_pre=bind visit_local_pre(fcx, _)
|
||||
with walk::default_visitor());
|
||||
walk::walk_block(visit, block);
|
||||
}
|
||||
|
@ -1196,29 +1191,24 @@ fn gather_locals(&@crate_ctxt ccx, &ast::fn_decl decl, &ast::block body,
|
|||
}
|
||||
|
||||
// Add explicitly-declared locals.
|
||||
fn visit_decl_pre(@crate_ctxt ccx,
|
||||
fn visit_local_pre(@crate_ctxt ccx,
|
||||
@ty::unify::var_bindings vb,
|
||||
hashmap[ast::def_id,int] locals,
|
||||
hashmap[ast::def_id,ast::ident] local_names,
|
||||
@mutable int nvi,
|
||||
&@ast::decl d) {
|
||||
alt (d.node) {
|
||||
case (ast::decl_local(?local)) {
|
||||
alt (local.ty) {
|
||||
case (none) {
|
||||
// Auto slot.
|
||||
assign(ccx.tcx, vb, locals, local_names, nvi,
|
||||
local.id, local.ident, none[ty::t]);
|
||||
}
|
||||
case (some(?ast_ty)) {
|
||||
// Explicitly typed slot.
|
||||
auto local_ty = ast_ty_to_ty_crate(ccx, ast_ty);
|
||||
assign(ccx.tcx, vb, locals, local_names, nvi,
|
||||
local.id, local.ident, some[ty::t](local_ty));
|
||||
}
|
||||
}
|
||||
&@ast::local local) {
|
||||
alt (local.node.ty) {
|
||||
case (none) {
|
||||
// Auto slot.
|
||||
assign(ccx.tcx, vb, locals, local_names, nvi,
|
||||
local.node.id, local.node.ident, none[ty::t]);
|
||||
}
|
||||
case (some(?ast_ty)) {
|
||||
// Explicitly typed slot.
|
||||
auto local_ty = ast_ty_to_ty_crate(ccx, ast_ty);
|
||||
assign(ccx.tcx, vb, locals, local_names, nvi,
|
||||
local.node.id, local.node.ident, some[ty::t](local_ty));
|
||||
}
|
||||
case (_) { /* no-op */ }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1239,7 +1229,7 @@ fn gather_locals(&@crate_ctxt ccx, &ast::fn_decl decl, &ast::block body,
|
|||
}
|
||||
|
||||
auto visit =
|
||||
rec(visit_decl_pre=bind visit_decl_pre(ccx, vb, locals, local_names,
|
||||
rec(visit_local_pre=bind visit_local_pre(ccx, vb, locals, local_names,
|
||||
nvi, _),
|
||||
visit_pat_pre=bind visit_pat_pre(ccx, vb, locals, local_names,
|
||||
nvi, _)
|
||||
|
@ -1530,15 +1520,15 @@ fn check_expr(&@fn_ctxt fcx, &@ast::expr expr) {
|
|||
}
|
||||
|
||||
// A generic function for checking for or for-each loops
|
||||
fn check_for_or_for_each(&@fn_ctxt fcx, &@ast::decl decl,
|
||||
fn check_for_or_for_each(&@fn_ctxt fcx, &@ast::local local,
|
||||
&ty::t element_ty, &ast::block body,
|
||||
uint node_id) {
|
||||
check_decl_local(fcx, decl);
|
||||
check_decl_local(fcx, local.node);
|
||||
check_block(fcx, body);
|
||||
|
||||
// Unify type of decl with element type of the seq
|
||||
demand::simple(fcx, decl.span, ty::decl_local_ty(fcx.ccx.tcx,
|
||||
decl),
|
||||
demand::simple(fcx, local.span, ty::decl_local_ty(fcx.ccx.tcx,
|
||||
local.node),
|
||||
element_ty);
|
||||
|
||||
auto typ = ty::mk_nil(fcx.ccx.tcx);
|
||||
|
@ -1835,25 +1825,20 @@ fn check_expr(&@fn_ctxt fcx, &@ast::expr expr) {
|
|||
|
||||
case (ast::expr_for(?decl, ?seq, ?body, ?a)) {
|
||||
check_expr(fcx, seq);
|
||||
auto elt_ty;
|
||||
alt (structure_of(fcx, expr.span, expr_ty(fcx.ccx.tcx, seq))) {
|
||||
// FIXME: I include the check_for_or_each call in
|
||||
// each case because of a bug in typestate.
|
||||
// The bug is fixed; once there's a new snapshot,
|
||||
// the call can be moved out of the alt expression
|
||||
case (ty::ty_vec(?vec_elt_ty)) {
|
||||
auto elt_ty = vec_elt_ty.ty;
|
||||
check_for_or_for_each(fcx, decl, elt_ty, body, a.id);
|
||||
elt_ty = vec_elt_ty.ty;
|
||||
}
|
||||
case (ty::ty_str) {
|
||||
auto elt_ty = ty::mk_mach(fcx.ccx.tcx,
|
||||
util::common::ty_u8);
|
||||
check_for_or_for_each(fcx, decl, elt_ty, body, a.id);
|
||||
elt_ty = ty::mk_mach(fcx.ccx.tcx, util::common::ty_u8);
|
||||
}
|
||||
case (_) {
|
||||
fcx.ccx.tcx.sess.span_err(expr.span,
|
||||
"type of for loop iterator is not a vector or string");
|
||||
}
|
||||
}
|
||||
check_for_or_for_each(fcx, decl, elt_ty, body, a.id);
|
||||
}
|
||||
|
||||
case (ast::expr_for_each(?decl, ?seq, ?body, ?a)) {
|
||||
|
@ -2389,11 +2374,15 @@ fn check_decl_initializer(&@fn_ctxt fcx, &ast::def_id lid,
|
|||
}
|
||||
}
|
||||
|
||||
fn check_decl_local(&@fn_ctxt fcx, &@ast::decl decl) -> @ast::decl {
|
||||
alt (decl.node) {
|
||||
case (ast::decl_local(?local)) {
|
||||
auto a_res = local.ann;
|
||||
auto t = ty::mk_var(fcx.ccx.tcx, fcx.locals.get(local.id));
|
||||
fn check_decl_local(&@fn_ctxt fcx, &@ast::local_ local) -> @ast::local_ {
|
||||
auto a_res = local.ann;
|
||||
alt (fcx.locals.find(local.id)) {
|
||||
case (none) {
|
||||
fcx.ccx.tcx.sess.bug("check_decl_local: local id not found "
|
||||
+ local.ident);
|
||||
}
|
||||
case (some(?i)) {
|
||||
auto t = ty::mk_var(fcx.ccx.tcx, i);
|
||||
write::ty_only_fixup(fcx, a_res.id, t);
|
||||
|
||||
auto initopt = local.init;
|
||||
|
@ -2403,8 +2392,7 @@ fn check_decl_local(&@fn_ctxt fcx, &@ast::decl decl) -> @ast::decl {
|
|||
}
|
||||
case (_) { /* fall through */ }
|
||||
}
|
||||
auto local_1 = @rec(init=initopt, ann=a_res with *local);
|
||||
ret @rec(node=ast::decl_local(local_1) with *decl);
|
||||
ret @rec(init=initopt, ann=a_res with *local);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2415,7 +2403,7 @@ fn check_stmt(&@fn_ctxt fcx, &@ast::stmt stmt) {
|
|||
case (ast::stmt_decl(?decl,?a)) {
|
||||
node_id = a.id;
|
||||
alt (decl.node) {
|
||||
case (ast::decl_local(_)) { check_decl_local(fcx, decl); }
|
||||
case (ast::decl_local(?l)) { check_decl_local(fcx, l); }
|
||||
case (ast::decl_item(_)) { /* ignore for now */ }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ import std::option;
|
|||
import std::option::some;
|
||||
import std::option::none;
|
||||
import util::common::span;
|
||||
import util::common::respan;
|
||||
|
||||
// Context-passing AST walker. Each overridden visit method has full control
|
||||
// over what happens with its node, it can do its own traversal of the node's
|
||||
|
@ -23,6 +24,7 @@ type visitor[E] =
|
|||
fn(&@view_item v, &E e, &vt[E] v) visit_view_item,
|
||||
fn(&@native_item i, &E e, &vt[E] v) visit_native_item,
|
||||
fn(&@item i, &E e, &vt[E] v) visit_item,
|
||||
fn(&@local l, &E e, &vt[E] v) visit_local,
|
||||
fn(&block b, &E e, &vt[E] v) visit_block,
|
||||
fn(&@stmt s, &E e, &vt[E] v) visit_stmt,
|
||||
fn(&arm a, &E e, &vt[E] v) visit_arm,
|
||||
|
@ -39,6 +41,7 @@ fn default_visitor[E]() -> visitor[E] {
|
|||
visit_view_item = bind visit_view_item[E](_, _, _),
|
||||
visit_native_item = bind visit_native_item[E](_, _, _),
|
||||
visit_item = bind visit_item[E](_, _, _),
|
||||
visit_local = bind visit_local[E](_, _, _),
|
||||
visit_block = bind visit_block[E](_, _, _),
|
||||
visit_stmt = bind visit_stmt[E](_, _, _),
|
||||
visit_arm = bind visit_arm[E](_, _, _),
|
||||
|
@ -88,6 +91,17 @@ fn visit_mod[E](&_mod m, &span sp, &E e, &vt[E] v) {
|
|||
|
||||
fn visit_view_item[E](&@view_item vi, &E e, &vt[E] v) {}
|
||||
|
||||
fn visit_local[E](&@local loc, &E e, &vt[E] v) {
|
||||
alt (loc.node.ty) {
|
||||
case (none) {}
|
||||
case (some(?t)) { vt(v).visit_ty(t, e, v); }
|
||||
}
|
||||
alt (loc.node.init) {
|
||||
case (none) {}
|
||||
case (some(?i)) { vt(v).visit_expr(i.expr, e, v); }
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_item[E](&@item i, &E e, &vt[E] v) {
|
||||
alt (i.node) {
|
||||
case (item_const(_, ?t, ?ex, _, _)) {
|
||||
|
@ -237,14 +251,7 @@ fn visit_stmt[E](&@stmt s, &E e, &vt[E] v) {
|
|||
fn visit_decl[E](&@decl d, &E e, &vt[E] v) {
|
||||
alt (d.node) {
|
||||
case (decl_local(?loc)) {
|
||||
alt (loc.ty) {
|
||||
case (none) {}
|
||||
case (some(?t)) { vt(v).visit_ty(t, e, v); }
|
||||
}
|
||||
alt (loc.init) {
|
||||
case (none) {}
|
||||
case (some(?i)) { vt(v).visit_expr(i.expr, e, v); }
|
||||
}
|
||||
vt(v).visit_local(@respan(d.span, loc), e, v);
|
||||
}
|
||||
case (decl_item(?it)) { vt(v).visit_item(it, e, v); }
|
||||
}
|
||||
|
@ -309,12 +316,12 @@ fn visit_expr[E](&@expr ex, &E e, &vt[E] v) {
|
|||
vt(v).visit_block(b, e, v);
|
||||
}
|
||||
case (expr_for(?dcl, ?x, ?b, _)) {
|
||||
vt(v).visit_decl(dcl, e, v);
|
||||
vt(v).visit_local(dcl, e, v);
|
||||
vt(v).visit_expr(x, e, v);
|
||||
vt(v).visit_block(b, e, v);
|
||||
}
|
||||
case (expr_for_each(?dcl, ?x, ?b, _)) {
|
||||
vt(v).visit_decl(dcl, e, v);
|
||||
vt(v).visit_local(dcl, e, v);
|
||||
vt(v).visit_expr(x, e, v);
|
||||
vt(v).visit_block(b, e, v);
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import std::option::some;
|
|||
import std::option::none;
|
||||
|
||||
import util::common::span;
|
||||
import util::common::respan;
|
||||
|
||||
// FIXME: Should visit patterns as well.
|
||||
type ast_visitor =
|
||||
|
@ -32,6 +33,8 @@ type ast_visitor =
|
|||
fn (&@ast::pat p) visit_pat_post,
|
||||
fn (&@ast::decl d) visit_decl_pre,
|
||||
fn (&@ast::decl d) visit_decl_post,
|
||||
fn (&@ast::local l) visit_local_pre,
|
||||
fn (&@ast::local l) visit_local_post,
|
||||
fn (&@ast::expr e) visit_expr_pre,
|
||||
fn (&@ast::expr e) visit_expr_post,
|
||||
fn (&@ast::ty t) visit_ty_pre,
|
||||
|
@ -92,6 +95,21 @@ fn walk_view_item(&ast_visitor v, @ast::view_item vi) {
|
|||
v.visit_view_item_post(vi);
|
||||
}
|
||||
|
||||
fn walk_local(&ast_visitor v, @ast::local loc) {
|
||||
v.visit_local_pre(loc);
|
||||
alt (loc.node.ty) {
|
||||
case (none) {}
|
||||
case (some(?t)) { walk_ty(v, t); }
|
||||
}
|
||||
alt (loc.node.init) {
|
||||
case (none) {}
|
||||
case (some(?i)) {
|
||||
walk_expr(v, i.expr);
|
||||
}
|
||||
}
|
||||
v.visit_local_post(loc);
|
||||
}
|
||||
|
||||
fn walk_item(&ast_visitor v, @ast::item i) {
|
||||
if (!v.keep_going()) { ret; }
|
||||
v.visit_item_pre(i);
|
||||
|
@ -291,16 +309,7 @@ fn walk_decl(&ast_visitor v, @ast::decl d) {
|
|||
v.visit_decl_pre(d);
|
||||
alt (d.node) {
|
||||
case (ast::decl_local(?loc)) {
|
||||
alt (loc.ty) {
|
||||
case (none) {}
|
||||
case (some(?t)) { walk_ty(v, t); }
|
||||
}
|
||||
alt (loc.init) {
|
||||
case (none) {}
|
||||
case (some(?i)) {
|
||||
walk_expr(v, i.expr);
|
||||
}
|
||||
}
|
||||
walk_local(v, @respan(d.span, loc));
|
||||
}
|
||||
case (ast::decl_item(?it)) {
|
||||
walk_item(v, it);
|
||||
|
@ -379,12 +388,12 @@ fn walk_expr(&ast_visitor v, @ast::expr e) {
|
|||
walk_block(v, b);
|
||||
}
|
||||
case (ast::expr_for(?dcl, ?x, ?b, _)) {
|
||||
walk_decl(v, dcl);
|
||||
walk_local(v, dcl);
|
||||
walk_expr(v, x);
|
||||
walk_block(v, b);
|
||||
}
|
||||
case (ast::expr_for_each(?dcl, ?x, ?b, _)) {
|
||||
walk_decl(v, dcl);
|
||||
walk_local(v, dcl);
|
||||
walk_expr(v, x);
|
||||
walk_block(v, b);
|
||||
}
|
||||
|
@ -516,6 +525,7 @@ fn def_visit_stmt(&@ast::stmt s) { }
|
|||
fn def_visit_arm(&ast::arm a) { }
|
||||
fn def_visit_pat(&@ast::pat p) { }
|
||||
fn def_visit_decl(&@ast::decl d) { }
|
||||
fn def_visit_local(&@ast::local l) { }
|
||||
fn def_visit_expr(&@ast::expr e) { }
|
||||
fn def_visit_ty(&@ast::ty t) { }
|
||||
fn def_visit_constr(&@ast::constr c) { }
|
||||
|
@ -547,6 +557,8 @@ fn default_visitor() -> ast_visitor {
|
|||
visit_pat_post=def_visit_pat,
|
||||
visit_decl_pre=def_visit_decl,
|
||||
visit_decl_post=def_visit_decl,
|
||||
visit_local_pre=def_visit_local,
|
||||
visit_local_post=def_visit_local,
|
||||
visit_expr_pre=def_visit_expr,
|
||||
visit_expr_post=def_visit_expr,
|
||||
visit_ty_pre=def_visit_ty,
|
||||
|
|
|
@ -889,14 +889,10 @@ fn print_ident(&ps s, &ast::ident ident) {
|
|||
word(s.s, ident);
|
||||
}
|
||||
|
||||
fn print_for_decl(&ps s, @ast::decl decl) {
|
||||
alt (decl.node) {
|
||||
case (ast::decl_local(?loc)) {
|
||||
print_type(s, *option::get[@ast::ty](loc.ty));
|
||||
space(s.s);
|
||||
word(s.s, loc.ident);
|
||||
}
|
||||
}
|
||||
fn print_for_decl(&ps s, @ast::local loc) {
|
||||
print_type(s, *option::get[@ast::ty](loc.node.ty));
|
||||
space(s.s);
|
||||
word(s.s, loc.node.ident);
|
||||
}
|
||||
|
||||
fn print_path(&ps s, &ast::path path) {
|
||||
|
|
|
@ -224,7 +224,7 @@ fn has_nonlocal_exits(&ast::block b) -> bool {
|
|||
ret *has_exits;
|
||||
}
|
||||
|
||||
fn local_rhs_span(&@ast::local l, &span def) -> span {
|
||||
fn local_rhs_span(&@ast::local_ l, &span def) -> span {
|
||||
alt (l.init) {
|
||||
case (some(?i)) { ret i.expr.span; }
|
||||
case (_) { ret def; }
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue