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:
Tim Chevalier 2011-06-13 17:04:15 -07:00
parent ff8af3c2db
commit d65ad8c31c
15 changed files with 149 additions and 222 deletions

View file

@ -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);

View file

@ -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);
}

View file

@ -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)) {

View file

@ -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));
}
}
}

View file

@ -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;
}

View file

@ -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);
}

View file

@ -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);

View file

@ -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);

View file

@ -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

View file

@ -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 {

View file

@ -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 */ }
}
}

View file

@ -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);
}

View file

@ -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,

View file

@ -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) {

View file

@ -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; }