提交 aa5382bb 编写于 作者: N Niko Matsakis

split proto from fn_decl, as not all fn_decls know the proto.

this will address the (crashing) new test added.
上级 d6db9506
......@@ -190,8 +190,7 @@ fn mk_tests(cx: test_ctxt) -> @ast::item {
let ret_ty = mk_test_desc_vec_ty(cx);
let decl: ast::fn_decl =
{proto: ast::proto_bare,
inputs: [],
{inputs: [],
output: ret_ty,
purity: ast::impure_fn,
cf: ast::return_val,
......@@ -322,7 +321,6 @@ fn mk_test_wrapper(cx: test_ctxt,
ast::stmt_expr(@call_expr, cx.sess.next_node_id()));
let wrapper_decl: ast::fn_decl = {
proto: ast::proto_bare,
inputs: [],
output: @nospan(ast::ty_nil),
purity: ast::impure_fn,
......@@ -345,7 +343,8 @@ fn mk_test_wrapper(cx: test_ctxt,
let wrapper_expr: ast::expr = {
id: cx.sess.next_node_id(),
node: ast::expr_fn(wrapper_decl, wrapper_body, wrapper_capture),
node: ast::expr_fn(ast::proto_bare, wrapper_decl,
wrapper_body, wrapper_capture),
span: span
};
......@@ -366,8 +365,7 @@ fn mk_main(cx: test_ctxt) -> @ast::item {
let ret_ty = nospan(ast::ty_nil);
let decl: ast::fn_decl =
{proto: ast::proto_bare,
inputs: [args_arg],
{inputs: [args_arg],
output: @ret_ty,
purity: ast::impure_fn,
cf: ast::return_val,
......
......@@ -61,7 +61,7 @@ fn check_crate(tcx: ty::ctxt, crate: @ast::crate) -> (copy_map, ref_map) {
copy_map: std::map::new_int_hash(),
ref_map: std::map::new_int_hash(),
mutable silent: false};
let v = @{visit_fn: bind visit_fn(cx, _, _, _, _, _, _, _, _),
let v = @{visit_fn: bind visit_fn(cx, _, _, _, _, _, _, _),
visit_expr: bind visit_expr(cx, _, _, _),
visit_block: bind visit_block(cx, _, _, _)
with *visit::default_visitor::<scope>()};
......@@ -71,8 +71,8 @@ fn check_crate(tcx: ty::ctxt, crate: @ast::crate) -> (copy_map, ref_map) {
ret (cx.copy_map, cx.ref_map);
}
fn visit_fn(cx: @ctx, decl: ast::fn_decl, _ts: [ast::ty_param],
body: ast::blk, sp: span, _name: ast::fn_ident,
fn visit_fn(cx: @ctx, _fk: visit::fn_kind, decl: ast::fn_decl,
body: ast::blk, sp: span,
id: ast::node_id, sc: scope, v: vt<scope>) {
visit::visit_fn_decl(decl, sc, v);
let fty = ty::node_id_to_type(cx.tcx, id);
......
......@@ -32,7 +32,7 @@ fn map_crate(c: crate) -> map {
(@{visit_item: bind map_item(cx, _),
visit_native_item: bind map_native_item(cx, _),
visit_expr: bind map_expr(cx, _),
visit_fn: bind map_fn(cx, _, _, _, _, _, _),
visit_fn: bind map_fn(cx, _, _, _, _, _),
visit_local: bind map_local(cx, _),
visit_arm: bind map_arm(cx, _)
with *visit::default_simple_visitor()});
......@@ -40,8 +40,8 @@ fn map_crate(c: crate) -> map {
ret cx.map;
}
fn map_fn(cx: ctx, decl: fn_decl, _tps: [ty_param], _body: blk,
_sp: codemap::span, _n: fn_ident, _id: node_id) {
fn map_fn(cx: ctx, _fk: visit::fn_kind, decl: fn_decl, _body: blk,
_sp: codemap::span, _id: node_id) {
for a in decl.inputs {
cx.map.insert(a.id, node_arg(a, cx.local_id));
cx.local_id += 1u;
......
......@@ -736,7 +736,7 @@ fn create_function(fcx: @fn_ctxt) -> @metadata<subprogram_md> {
}
ast_map::node_expr(expr) {
alt expr.node {
ast::expr_fn(decl, _, _) {
ast::expr_fn(_, decl, _, _) {
(dbg_cx.names.next("fn"), decl.output, expr.id)
}
ast::expr_fn_block(decl, _) {
......
......@@ -38,8 +38,8 @@ fn ignore_item(_i: @ast::item, &&_depth: int, _v: visit::vt<int>) { }
let walk_expr =
lambda (expr: @ast::expr, &&depth: int, v: visit::vt<int>) {
alt expr.node {
ast::expr_fn(decl, _, captures) {
if decl.proto != ast::proto_bare {
ast::expr_fn(proto, decl, _, captures) {
if proto != ast::proto_bare {
visit::visit_expr(expr, depth + 1, v);
}
}
......@@ -82,9 +82,8 @@ fn annotate_freevars(def_map: resolve::def_map, crate: @ast::crate) ->
freevar_map {
let freevars = new_int_hash();
let walk_fn = lambda (_decl: ast::fn_decl, _tps: [ast::ty_param],
blk: ast::blk, _sp: span, _nm: ast::fn_ident,
nid: ast::node_id) {
let walk_fn = lambda (_fk: visit::fn_kind, _decl: ast::fn_decl,
blk: ast::blk, _sp: span, nid: ast::node_id) {
let vars = collect_freevars(def_map, blk);
freevars.insert(nid, vars);
};
......
......@@ -67,8 +67,8 @@ fn with_closure_check_fn(cx: ctx, id: node_id,
// Check that the free variables used in a shared/sendable closure conform
// to the copy/move kind bounds. Then recursively check the function body.
fn check_fn(decl: fn_decl, tps: [ty_param], body: blk, sp: span,
i: fn_ident, id: node_id, cx: ctx, v: visit::vt<ctx>) {
fn check_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, sp: span,
id: node_id, cx: ctx, v: visit::vt<ctx>) {
// n.b.: This could be the body of either a fn decl or a fn expr. In the
// former case, the prototype will be proto_bare and no check occurs. In
......@@ -88,7 +88,7 @@ fn check_fn(decl: fn_decl, tps: [ty_param], body: blk, sp: span,
}
}
visit::visit_fn(decl, tps, body, sp, i, id, cx, v);
visit::visit_fn(fk, decl, body, sp, id, cx, v);
}
fn check_fn_cap_clause(cx: ctx,
......@@ -181,7 +181,7 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) {
}
}
expr_ternary(_, a, b) { maybe_copy(cx, a); maybe_copy(cx, b); }
expr_fn(_, _, cap_clause) {
expr_fn(_, _, _, cap_clause) {
check_fn_cap_clause(cx, e.id, *cap_clause);
}
_ { }
......
......@@ -136,7 +136,7 @@ fn visit_expr(ex: @expr, cx: ctx, v: visit::vt<ctx>) {
for arg in args {
alt arg.node {
//NDM--register captured as uses
expr_fn(_, _, captured) { fns += [arg]; }
expr_fn(_, _, _, captured) { fns += [arg]; }
expr_fn_block(_, _) { fns += [arg]; }
_ {
alt arg_ts[i].mode {
......@@ -153,19 +153,19 @@ fn visit_expr(ex: @expr, cx: ctx, v: visit::vt<ctx>) {
}
}
fn visit_fn(decl: fn_decl, tps: [ty_param], body: blk,
sp: span, nm: fn_ident, id: node_id,
fn visit_fn(fk: visit::fn_kind, decl: fn_decl, body: blk,
sp: span, id: node_id,
cx: ctx, v: visit::vt<ctx>) {
let fty = ty::node_id_to_type(cx.tcx, id);
let proto = ty::ty_fn_proto(cx.tcx, fty);
if proto == proto_block {
visit_block(func, cx, {||
visit::visit_fn(decl, tps, body, sp, nm, id, cx, v);
visit::visit_fn(fk, decl, body, sp, id, cx, v);
});
} else {
let old = nil;
cx.blocks <-> old;
visit::visit_fn(decl, tps, body, sp, nm, id, cx, v);
visit::visit_fn(fk, decl, body, sp, id, cx, v);
cx.blocks <-> old;
leave_fn(cx);
}
......
......@@ -336,7 +336,7 @@ fn resolve_names(e: @env, c: @ast::crate) {
visit_expr: bind walk_expr(e, _, _, _),
visit_ty: bind walk_ty(e, _, _, _),
visit_constr: bind walk_constr(e, _, _, _, _, _),
visit_fn: bind visit_fn_with_scope(e, _, _, _, _, _, _, _, _)
visit_fn: bind visit_fn_with_scope(e, _, _, _, _, _, _, _)
with *visit::default_visitor()};
visit::visit_crate(*c, cons(scope_crate, @nil), visit::mk_vt(v));
e.used_imports.track = false;
......@@ -350,7 +350,7 @@ fn walk_expr(e: @env, exp: @ast::expr, sc: scopes, v: vt<scopes>) {
lookup_path_strict(*e, sc, exp.span, p.node,
ns_value));
}
ast::expr_fn(_, _, cap_clause) {
ast::expr_fn(_, _, _, cap_clause) {
let rci = bind resolve_capture_item(e, sc, _);
vec::iter(cap_clause.copies, rci);
vec::iter(cap_clause.moves, rci);
......@@ -403,8 +403,9 @@ fn visit_item_with_scope(i: @ast::item, sc: scopes, v: vt<scopes>) {
alt ifce { some(ty) { v.visit_ty(ty, sc, v); } _ {} }
v.visit_ty(sty, sc, v);
for m in methods {
v.visit_fn(m.decl, tps + m.tps, m.body, m.span,
some(m.ident), m.id, sc, v);
v.visit_fn(visit::fk_method(m.ident, tps + m.tps),
m.decl, m.body, m.span,
m.id, sc, v);
}
}
_ { visit::visit_item(i, sc, v); }
......@@ -416,30 +417,35 @@ fn visit_native_item_with_scope(ni: @ast::native_item, sc: scopes,
visit::visit_native_item(ni, cons(scope_native_item(ni), @sc), v);
}
fn visit_fn_with_scope(e: @env, decl: ast::fn_decl, tp: [ast::ty_param],
body: ast::blk, sp: span, name: fn_ident,
fn visit_fn_with_scope(e: @env, fk: visit::fn_kind, decl: ast::fn_decl,
body: ast::blk, sp: span,
id: node_id, sc: scopes, v: vt<scopes>) {
// is this a main fn declaration?
alt name {
some(nm) {
alt fk {
visit::fk_item_fn(nm, _) {
if is_main_name([nm]) && !e.sess.building_library() {
// This is a main function -- set it in the session
// as the main ID
e.sess.set_main_id(id);
}
}
_ { }
_ { /* fallthrough */ }
}
// here's where we need to set up the mapping
// for f's constrs in the table.
for c: @ast::constr in decl.constraints { resolve_constr(e, c, sc, v); }
let scope = alt decl.proto {
ast::proto_bare. { scope_bare_fn(decl, id, tp) }
_ { scope_fn_expr(decl, id, tp) }
let scope = alt fk {
visit::fk_item_fn(_, tps) | visit::fk_method(_, tps) |
visit::fk_res(_, tps) {
scope_bare_fn(decl, id, tps)
}
visit::fk_anon(_) | visit::fk_fn_block. {
scope_fn_expr(decl, id, [])
}
};
visit::visit_fn(decl, tp, body, sp, name, id, cons(scope, @sc), v);
visit::visit_fn(fk, decl, body, sp, id, cons(scope, @sc), v);
}
fn visit_block_with_scope(b: ast::blk, sc: scopes, v: vt<scopes>) {
......
......@@ -3551,16 +3551,18 @@ fn trans_expr(bcx: @block_ctxt, e: @ast::expr, dest: dest) -> @block_ctxt {
assert op != ast::deref; // lvals are handled above
ret trans_unary(bcx, op, x, e.id, dest);
}
ast::expr_fn(decl, body, cap_clause) {
ast::expr_fn(proto, decl, body, cap_clause) {
ret trans_closure::trans_expr_fn(
bcx, decl, body, e.span, e.id, *cap_clause, dest);
bcx, proto, decl, body, e.span, e.id, *cap_clause, dest);
}
ast::expr_fn_block(decl, body) {
alt ty::struct(tcx, ty::expr_ty(tcx, e)) {
ty::ty_fn({proto, _}) {
#debug("translating fn_block %s with type %s",
expr_to_str(e), ty_to_str(tcx, ty::expr_ty(tcx, e)));
let cap_clause = { copies: [], moves: [] };
ret trans_closure::trans_expr_fn(
bcx, decl, body, e.span, e.id, cap_clause, dest);
bcx, proto, decl, body, e.span, e.id, cap_clause, dest);
}
_ {
fail "Type of fn block is not a function!";
......
......@@ -372,6 +372,7 @@ fn load_environment(enclosing_cx: @block_ctxt,
}
fn trans_expr_fn(bcx: @block_ctxt,
proto: ast::proto,
decl: ast::fn_decl,
body: ast::blk,
sp: span,
......@@ -390,7 +391,7 @@ fn trans_expr_fn(bcx: @block_ctxt,
let trans_closure_env = lambda(ck: ty::closure_kind) -> ValueRef {
let cap_vars = capture::compute_capture_vars(
ccx.tcx, id, decl.proto, cap_clause);
ccx.tcx, id, proto, cap_clause);
let {llbox, box_ty, bcx} = build_closure(bcx, cap_vars, ck);
trans_closure(sub_cx, sp, decl, body, llfn, no_self, [], id, {|fcx|
load_environment(bcx, fcx, box_ty, cap_vars, ck);
......@@ -398,7 +399,7 @@ fn trans_expr_fn(bcx: @block_ctxt,
llbox
};
let closure = alt decl.proto {
let closure = alt proto {
ast::proto_block. { trans_closure_env(ty::closure_block) }
ast::proto_shared(_) { trans_closure_env(ty::closure_shared) }
ast::proto_send. { trans_closure_env(ty::closure_send) }
......
......@@ -56,8 +56,8 @@ fn visit_fn(ccx: crate_ctxt, num_constraints: uint, body: blk) {
init_vecs(ccx, node_id_vec, num_constraints);
}
fn annotate_in_fn(ccx: crate_ctxt, _decl: fn_decl, _ts: [ty_param], body: blk,
_sp: span, _n: fn_ident, id: node_id) {
fn annotate_in_fn(ccx: crate_ctxt, _fk: visit::fn_kind, _decl: fn_decl,
body: blk, _sp: span, id: node_id) {
let f_info = get_fn_info(ccx, id);
visit_fn(ccx, num_constraints(f_info), body);
}
......@@ -65,7 +65,7 @@ fn annotate_in_fn(ccx: crate_ctxt, _decl: fn_decl, _ts: [ty_param], body: blk,
fn annotate_crate(ccx: crate_ctxt, crate: crate) {
let do_ann =
visit::mk_simple_visitor(
@{visit_fn: bind annotate_in_fn(ccx, _, _, _, _, _, _)
@{visit_fn: bind annotate_in_fn(ccx, _, _, _, _, _)
with *visit::default_simple_visitor()});
visit::visit_crate(crate, (), do_ann);
}
......
......@@ -1008,8 +1008,8 @@ fn op_to_oper_ty(io: init_op) -> oper_type {
}
// default function visitor
fn do_nothing<T>(_decl: fn_decl, _ts: [ty_param], _body: blk,
_sp: span, _i: fn_ident, _id: node_id,
fn do_nothing<T>(_fk: visit::fn_kind, _decl: fn_decl, _body: blk,
_sp: span, _id: node_id,
_t: T, _v: visit::vt<T>) {
}
......
......@@ -151,7 +151,7 @@ fn relax_precond_block(fcx: fn_ctxt, i: node_id, b: blk) {
visit_stmt: relax_precond_stmt,
visit_item:
fn (_i: @item, _cx: relax_ctxt, _vt: visit::vt<relax_ctxt>) { },
visit_fn: bind do_nothing(_, _, _, _, _, _, _, _)
visit_fn: bind do_nothing(_, _, _, _, _, _, _)
with *visitor};
let v1 = visit::mk_vt(visitor);
v1.visit_block(b, cx, v1);
......
......@@ -94,21 +94,20 @@ fn check_states_stmt(s: @stmt, fcx: fn_ctxt, v: visit::vt<fn_ctxt>) {
}
fn check_states_against_conditions(fcx: fn_ctxt,
fk: visit::fn_kind,
f_decl: ast::fn_decl,
f_body: ast::blk,
sp: span,
nm: fn_ident,
id: node_id) {
/* Postorder traversal instead of pre is important
because we want the smallest possible erroneous statement
or expression. */
let visitor = visit::mk_vt(
@{visit_stmt: check_states_stmt,
visit_expr: check_states_expr,
visit_fn: bind do_nothing::<fn_ctxt>(_, _, _, _, _, _, _, _)
visit_fn: bind do_nothing::<fn_ctxt>(_, _, _, _, _, _, _)
with *visit::default_visitor::<fn_ctxt>()});
visit::visit_fn(f_decl, [], f_body, sp, nm, id, fcx, visitor);
visit::visit_fn(fk, f_decl, f_body, sp, id, fcx, visitor);
/* Check that the return value is initialized */
let post = aux::block_poststate(fcx.ccx, f_body);
......@@ -142,10 +141,10 @@ fn check_states_against_conditions(fcx: fn_ctxt,
}
fn check_fn_states(fcx: fn_ctxt,
fk: visit::fn_kind,
f_decl: ast::fn_decl,
f_body: ast::blk,
sp: span,
nm: fn_ident,
id: node_id) {
/* Compute the pre- and post-states for this function */
......@@ -155,20 +154,20 @@ fn check_fn_states(fcx: fn_ctxt,
/* Now compare each expr's pre-state to its precondition
and post-state to its postcondition */
check_states_against_conditions(fcx, f_decl, f_body, sp, nm, id);
check_states_against_conditions(fcx, fk, f_decl, f_body, sp, id);
}
fn fn_states(f_decl: ast::fn_decl, tps: [ast::ty_param], f_body: ast::blk,
sp: span, i: ast::fn_ident, id: node_id,
fn fn_states(fk: visit::fn_kind, f_decl: ast::fn_decl, f_body: ast::blk,
sp: span, id: node_id,
ccx: crate_ctxt, v: visit::vt<crate_ctxt>) {
visit::visit_fn(f_decl, tps, f_body, sp, i, id, ccx, v);
visit::visit_fn(fk, f_decl, f_body, sp, id, ccx, v);
/* Look up the var-to-bit-num map for this function */
assert (ccx.fm.contains_key(id));
let f_info = ccx.fm.get(id);
let name = option::from_maybe("anon", i); // XXXX
let name = visit::name_of_fn(fk);
let fcx = {enclosing: f_info, id: id, name: name, ccx: ccx};
check_fn_states(fcx, f_decl, f_body, sp, i, id)
check_fn_states(fcx, fk, f_decl, f_body, sp, id)
}
fn check_crate(cx: ty::ctxt, crate: @crate) {
......
import syntax::ast::*;
import syntax::ast_util::*;
import util::ppaux::fn_ident_to_string;
import option::*;
import syntax::visit;
import aux::*;
......@@ -45,11 +44,10 @@ fn collect_pred(e: @expr, cx: ctxt, v: visit::vt<ctxt>) {
}
fn find_locals(tcx: ty::ctxt,
fk: visit::fn_kind,
f_decl: fn_decl,
tps: [ty_param],
f_body: blk,
sp: span,
n: fn_ident,
id: node_id) -> ctxt {
let cx: ctxt = {cs: @mutable [], tcx: tcx};
let visitor = visit::default_visitor::<ctxt>();
......@@ -57,10 +55,10 @@ fn find_locals(tcx: ty::ctxt,
visitor =
@{visit_local: collect_local,
visit_expr: collect_pred,
visit_fn: bind do_nothing(_, _, _, _, _, _, _, _)
visit_fn: bind do_nothing(_, _, _, _, _, _, _)
with *visitor};
visit::visit_fn(f_decl, tps, f_body, sp,
n, id, cx, visit::mk_vt(visitor));
visit::visit_fn(fk, f_decl, f_body, sp,
id, cx, visit::mk_vt(visitor));
ret cx;
}
......@@ -98,18 +96,16 @@ fn add_constraint(tcx: ty::ctxt, c: sp_constr, next: uint, tbl: constr_map) ->
/* builds a table mapping each local var defined in f
to a bit number in the precondition/postcondition vectors */
fn mk_fn_info(ccx: crate_ctxt,
fk: visit::fn_kind,
f_decl: fn_decl,
tps: [ty_param],
f_body: blk,
f_sp: span,
f_name: fn_ident,
id: node_id) {
let name = fn_ident_to_string(id, f_name);
let name = visit::name_of_fn(fk);
let res_map = @new_def_hash::<constraint>();
let next: uint = 0u;
let cx: ctxt = find_locals(ccx.tcx, f_decl, tps, f_body, f_sp,
f_name, id);
let cx: ctxt = find_locals(ccx.tcx, fk, f_decl, f_body, f_sp, id);
/* now we have to add bit nums for both the constraints
and the variables... */
......@@ -167,7 +163,7 @@ fn mk_fn_info(ccx: crate_ctxt,
fn mk_f_to_fn_info(ccx: crate_ctxt, c: @crate) {
let visitor =
visit::mk_simple_visitor(@{visit_fn:
bind mk_fn_info(ccx, _, _, _, _, _, _)
bind mk_fn_info(ccx, _, _, _, _, _)
with *visit::default_simple_visitor()});
visit::visit_crate(*c, (), visitor);
}
......
......@@ -14,7 +14,6 @@
import util::common::{new_def_hash, log_expr, field_exprs,
has_nonlocal_exits, log_stmt};
import syntax::codemap::span;
import util::ppaux::fn_ident_to_string;
fn find_pre_post_mod(_m: _mod) -> _mod {
#debug("implement find_pre_post_mod!");
......@@ -346,7 +345,7 @@ fn find_pre_post_expr(fcx: fn_ctxt, e: @expr) {
expr_log(_, lvl, arg) {
find_pre_post_exprs(fcx, [lvl, arg], e.id);
}
expr_fn(_, _, cap_clause) {
expr_fn(_, _, _, cap_clause) {
find_pre_post_expr_fn_upvars(fcx, e);
let use_cap_item = lambda(&&cap_item: @capture_item) {
......@@ -727,15 +726,15 @@ fn find_pre_post_fn(fcx: fn_ctxt, body: blk) {
}
}
fn fn_pre_post(decl: fn_decl, tps: [ty_param], body: blk, sp: span,
i: fn_ident, id: node_id,
fn fn_pre_post(fk: visit::fn_kind, decl: fn_decl, body: blk, sp: span,
id: node_id,
ccx: crate_ctxt, v: visit::vt<crate_ctxt>) {
visit::visit_fn(decl, tps, body, sp, i, id, ccx, v);
visit::visit_fn(fk, decl, body, sp, id, ccx, v);
assert (ccx.fm.contains_key(id));
let fcx =
{enclosing: ccx.fm.get(id),
id: id,
name: fn_ident_to_string(id, i),
name: visit::name_of_fn(fk),
ccx: ccx};
find_pre_post_fn(fcx, body);
}
......
......@@ -371,7 +371,7 @@ fn find_pre_post_state_expr(fcx: fn_ctxt, pres: prestate, e: @expr) -> bool {
}
expr_mac(_) { fcx.ccx.tcx.sess.bug("unexpanded macro"); }
expr_lit(l) { ret pure_exp(fcx.ccx, e.id, pres); }
expr_fn(_, _, cap_clause) {
expr_fn(_, _, _, cap_clause) {
ret find_pre_post_state_cap_clause(fcx, e.id, pres, *cap_clause);
}
expr_fn_block(_, _) { ret pure_exp(fcx.ccx, e.id, pres); }
......
......@@ -333,8 +333,8 @@ fn instantiate(tcx: ty::ctxt, sp: span, mode: mode,
}
typ = ty::mk_rec(tcx, flds);
}
ast::ty_fn(decl) {
typ = ty::mk_fn(tcx, ty_of_fn_decl(tcx, mode, decl));
ast::ty_fn(proto, decl) {
typ = ty::mk_fn(tcx, ty_of_fn_decl(tcx, mode, proto, decl));
}
ast::ty_path(path, id) {
alt tcx.def_map.find(id) {
......@@ -465,7 +465,8 @@ fn ty_of_arg(tcx: ty::ctxt, mode: mode, a: ast::arg) -> ty::arg {
let ty = ast_ty_to_ty(tcx, mode, a.ty);
{mode: default_arg_mode_for_ty(tcx, a.mode, ty), ty: ty}
}
fn ty_of_fn_decl(tcx: ty::ctxt, mode: mode, decl: ast::fn_decl) -> ty::fn_ty {
fn ty_of_fn_decl(tcx: ty::ctxt, mode: mode,
proto: ast::proto, decl: ast::fn_decl) -> ty::fn_ty {
let input_tys = [];
for a: ast::arg in decl.inputs { input_tys += [ty_of_arg(tcx, mode, a)]; }
let output_ty = ast_ty_to_ty(tcx, mode, decl.output);
......@@ -474,19 +475,20 @@ fn ty_of_fn_decl(tcx: ty::ctxt, mode: mode, decl: ast::fn_decl) -> ty::fn_ty {
for constr: @ast::constr in decl.constraints {
out_constrs += [ty::ast_constr_to_constr(tcx, constr)];
}
{proto: decl.proto, inputs: input_tys,
{proto: proto, inputs: input_tys,
output: output_ty, ret_style: decl.cf, constraints: out_constrs}
}
fn ty_of_fn(tcx: ty::ctxt, mode: mode, decl: ast::fn_decl,
ty_params: [ast::ty_param], def_id: ast::def_id)
-> ty::ty_param_bounds_and_ty {
let tpt = @{bounds: ty_param_bounds(tcx, mode, ty_params),
ty: ty::mk_fn(tcx, ty_of_fn_decl(tcx, mode, decl))};
let bounds = ty_param_bounds(tcx, mode, ty_params);
let tofd = ty_of_fn_decl(tcx, mode, ast::proto_bare, decl);
let tpt = @{bounds: bounds, ty: ty::mk_fn(tcx, tofd)};
tcx.tcache.insert(def_id, tpt);
ret tpt;
}
fn ty_of_native_fn_decl(tcx: ty::ctxt, mode: mode, decl: ast::fn_decl,
ty_params: [ast::ty_param], def_id: ast::def_id)
ty_params: [ast::ty_param], def_id: ast::def_id)
-> ty::ty_param_bounds_and_ty {
let input_tys = [], bounds = ty_param_bounds(tcx, mode, ty_params);
for a: ast::arg in decl.inputs { input_tys += [ty_of_arg(tcx, mode, a)]; }
......@@ -524,12 +526,12 @@ fn ty_param_bounds(tcx: ty::ctxt, mode: mode, params: [ast::ty_param])
}
fn ty_of_method(tcx: ty::ctxt, mode: mode, m: @ast::method) -> ty::method {
{ident: m.ident, tps: ty_param_bounds(tcx, mode, m.tps),
fty: ty_of_fn_decl(tcx, mode, m.decl)}
fty: ty_of_fn_decl(tcx, mode, ast::proto_bare, m.decl)}
}
fn ty_of_ty_method(tcx: ty::ctxt, mode: mode, m: ast::ty_method)
-> ty::method {
{ident: m.ident, tps: ty_param_bounds(tcx, mode, m.tps),
fty: ty_of_fn_decl(tcx, mode, m.decl)}
fty: ty_of_fn_decl(tcx, mode, ast::proto_bare, m.decl)}
}
fn ty_of_obj(tcx: ty::ctxt, mode: mode, id: ast::ident, ob: ast::_obj,
ty_params: [ast::ty_param]) -> ty::ty_param_bounds_and_ty {
......@@ -691,8 +693,9 @@ fn convert(cx: @ctxt, it: @ast::item) {
ty_param_bounds(cx.tcx, m_collect, tps);
for m in ms {
let bounds = ty_param_bounds(cx.tcx, m_collect, m.tps);
let ty = ty::mk_fn(cx.tcx, ty_of_fn_decl(cx.tcx, m_collect,
m.decl));
let ty = ty::mk_fn(cx.tcx,
ty_of_fn_decl(cx.tcx, m_collect,
ast::proto_bare, m.decl));
cx.tcx.tcache.insert(local_def(m.id), @{bounds: bounds,
ty: ty});
write::ty_only(cx.tcx, m.id, ty);
......@@ -1005,7 +1008,7 @@ fn visit_expr(e: @ast::expr, wbcx: wb_ctxt, v: wb_vt) {
if !wbcx.success { ret; }
resolve_type_vars_for_node(wbcx, e.span, e.id);
alt e.node {
ast::expr_fn(decl, _, _) |
ast::expr_fn(_, decl, _, _) |
ast::expr_fn_block(decl, _) {
for input in decl.inputs {
resolve_type_vars_for_node(wbcx, e.span, input.id);
......@@ -1154,16 +1157,15 @@ fn gather_locals(ccx: @crate_ctxt,
};
// Don't descend into fns and items
fn visit_fn<T>(_decl: ast::fn_decl, _ts: [ast::ty_param], _body: ast::blk,
_sp: span, _nm: ast::fn_ident, _id: ast::node_id,
_t: T, _v: visit::vt<T>) {
fn visit_fn<T>(_fk: visit::fn_kind, _decl: ast::fn_decl, _body: ast::blk,
_sp: span, _id: ast::node_id, _t: T, _v: visit::vt<T>) {
}
fn visit_item<E>(_i: @ast::item, _e: E, _v: visit::vt<E>) { }
let visit =
@{visit_local: visit_local,
visit_pat: visit_pat,
visit_fn: bind visit_fn(_, _, _, _, _, _, _, _),
visit_fn: bind visit_fn(_, _, _, _, _, _, _),
visit_item: bind visit_item(_, _, _)
with *visit::default_visitor()};
......@@ -1510,13 +1512,15 @@ fn lookup_method(fcx: @fn_ctxt, isc: resolve::iscopes,
fn check_expr_fn_with_unifier(fcx: @fn_ctxt,
expr: @ast::expr,
proto: ast::proto,
decl: ast::fn_decl,
body: ast::blk,
unify: unifier,
expected: ty::t) {
let tcx = fcx.ccx.tcx;
let fty = ty::mk_fn(tcx, ty_of_fn_decl(tcx, m_check_tyvar(fcx), decl));
let fty = ty::mk_fn(tcx, ty_of_fn_decl(tcx, m_check_tyvar(fcx),
proto, decl));
#debug("check_expr_fn_with_unifier %s fty=%s",
expr_to_str(expr),
......@@ -1530,7 +1534,7 @@ fn check_expr_fn_with_unifier(fcx: @fn_ctxt,
// record projection work on type inferred arguments.
unify(fcx, expr.span, expected, fty);
check_fn(fcx.ccx, decl, body, expr.id, some(fcx));
check_fn(fcx.ccx, proto, decl, body, expr.id, some(fcx));
}
fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
......@@ -1964,10 +1968,10 @@ fn check_binop_type_compat(fcx: @fn_ctxt, span: span, ty: ty::t,
if !arm_non_bot { result_ty = ty::mk_bot(tcx); }
write::ty_only_fixup(fcx, id, result_ty);
}
ast::expr_fn(decl, body, captures) {
check_expr_fn_with_unifier(fcx, expr, decl, body,
ast::expr_fn(proto, decl, body, captures) {
check_expr_fn_with_unifier(fcx, expr, proto, decl, body,
unify, expected);
capture::check_capture_clause(tcx, expr.id, decl.proto, *captures);
capture::check_capture_clause(tcx, expr.id, proto, *captures);
}
ast::expr_fn_block(decl, body) {
// Take the prototype from the expected type, but default to block:
......@@ -1983,7 +1987,7 @@ fn check_binop_type_compat(fcx: @fn_ctxt, span: span, ty: ty::t,
#debug("checking expr_fn_block %s expected=%s",
expr_to_str(expr),
ty_to_str(tcx, expected));
check_expr_fn_with_unifier(fcx, expr, {proto: proto with decl}, body,
check_expr_fn_with_unifier(fcx, expr, proto, decl, body,
unify, expected);
write::ty_only_fixup(fcx, id, expected);
}
......@@ -2602,10 +2606,11 @@ fn check_constraints(fcx: @fn_ctxt, cs: [@ast::constr], args: [ast::arg]) {
}
fn check_fn(ccx: @crate_ctxt,
decl: ast::fn_decl,
body: ast::blk,
id: ast::node_id,
old_fcx: option::t<@fn_ctxt>) {
proto: ast::proto,
decl: ast::fn_decl,
body: ast::blk,
id: ast::node_id,
old_fcx: option::t<@fn_ctxt>) {
// If old_fcx is some(...), this is a block fn { |x| ... }.
// In that case, the purity is inherited from the context.
let purity = alt old_fcx {
......@@ -2618,7 +2623,7 @@ fn check_fn(ccx: @crate_ctxt,
let fcx: @fn_ctxt =
@{ret_ty: ty::ty_fn_ret(ccx.tcx, ty::node_id_to_type(ccx.tcx, id)),
purity: purity,
proto: decl.proto,
proto: proto,
var_bindings: gather_result.var_bindings,
locals: gather_result.locals,
next_var_id: gather_result.next_var_id,
......@@ -2655,15 +2660,17 @@ fn check_fn(ccx: @crate_ctxt,
}
fn check_method(ccx: @crate_ctxt, method: @ast::method) {
check_fn(ccx, method.decl, method.body, method.id, none);
check_fn(ccx, ast::proto_bare, method.decl, method.body, method.id, none);
}
fn check_item(ccx: @crate_ctxt, it: @ast::item) {
alt it.node {
ast::item_const(_, e) { check_const(ccx, it.span, e, it.id); }
ast::item_fn(decl, _, body) { check_fn(ccx, decl, body, it.id, none); }
ast::item_fn(decl, _, body) {
check_fn(ccx, ast::proto_bare, decl, body, it.id, none);
}
ast::item_res(decl, _, body, dtor_id, _) {
check_fn(ccx, decl, body, dtor_id, none);
check_fn(ccx, ast::proto_bare, decl, body, dtor_id, none);
}
ast::item_obj(ob, _, _) {
// We're entering an object, so gather up the info we need.
......
......@@ -202,7 +202,7 @@
expr_for(@local, @expr, blk);
expr_do_while(blk, @expr);
expr_alt(@expr, [arm]);
expr_fn(fn_decl, blk, @capture_clause);
expr_fn(proto, fn_decl, blk, @capture_clause);
expr_fn_block(fn_decl, blk);
expr_block(blk);
......@@ -317,7 +317,7 @@
ty_port(@ty);
ty_chan(@ty);
ty_rec([ty_field]);
ty_fn(fn_decl);
ty_fn(proto, fn_decl);
ty_obj([ty_method]);
ty_tup([@ty]);
ty_path(@path, node_id);
......@@ -368,8 +368,7 @@
type arg = {mode: mode, ty: @ty, ident: ident, id: node_id};
type fn_decl =
{proto: proto,
inputs: [arg],
{inputs: [arg],
output: @ty,
purity: purity,
cf: ret_style,
......
......@@ -143,8 +143,7 @@ fn fold_mac_(m: mac, fld: ast_fold) -> mac {
}
fn fold_fn_decl(decl: ast::fn_decl, fld: ast_fold) -> ast::fn_decl {
ret {proto: decl.proto,
inputs: vec::map(decl.inputs, bind fold_arg_(_, fld)),
ret {inputs: vec::map(decl.inputs, bind fold_arg_(_, fld)),
output: fld.fold_ty(decl.output),
purity: decl.purity,
cf: decl.cf,
......@@ -192,8 +191,7 @@ fn noop_fold_native_item(&&ni: @native_item, fld: ast_fold) -> @native_item {
alt ni.node {
native_item_ty. { native_item_ty }
native_item_fn(fdec, typms) {
native_item_fn({proto: fdec.proto,
inputs: vec::map(fdec.inputs, fold_arg),
native_item_fn({inputs: vec::map(fdec.inputs, fold_arg),
output: fld.fold_ty(fdec.output),
purity: fdec.purity,
cf: fdec.cf,
......@@ -398,8 +396,9 @@ fn fold_anon_obj_field_(aof: anon_obj_field, fld: ast_fold) ->
expr_alt(expr, arms) {
expr_alt(fld.fold_expr(expr), vec::map(arms, fld.fold_arm))
}
expr_fn(decl, body, captures) {
expr_fn(fold_fn_decl(decl, fld), fld.fold_block(body), captures)
expr_fn(proto, decl, body, captures) {
expr_fn(proto, fold_fn_decl(decl, fld),
fld.fold_block(body), captures)
}
expr_fn_block(decl, body) {
expr_fn_block(fold_fn_decl(decl, fld), fld.fold_block(body))
......
......@@ -280,21 +280,21 @@ fn parse_fn_input_ty(p: parser) -> ast::arg {
// auto constrs = parse_constrs(~[], p);
let constrs: [@ast::constr] = [];
let (ret_style, ret_ty) = parse_ret_ty(p);
ret ast::ty_fn({proto: proto, inputs: inputs.node, output: ret_ty,
purity: ast::impure_fn, cf: ret_style,
constraints: constrs});
ret ast::ty_fn(proto, {inputs: inputs.node, output: ret_ty,
purity: ast::impure_fn, cf: ret_style,
constraints: constrs});
}
fn parse_ty_methods(p: parser, allow_tps: bool) -> [ast::ty_method] {
parse_seq(token::LBRACE, token::RBRACE, seq_sep_none(), {|p|
let flo = p.get_lo_pos();
let proto: ast::proto = parse_method_proto(p);
expect_word(p, "fn");
let ident = parse_value_ident(p);
let tps = allow_tps ? parse_ty_params(p) : [];
let f = parse_ty_fn(proto, p), fhi = p.get_last_hi_pos();
let f = parse_ty_fn(ast::proto_bare, p), fhi = p.get_last_hi_pos();
expect(p, token::SEMI);
alt f {
ast::ty_fn(d) {
ast::ty_fn(_, d) {
{ident: ident, decl: d, tps: tps,
span: ast_util::mk_sp(flo, fhi)}
}
......@@ -1284,10 +1284,10 @@ fn eat_ident_list(p: parser) -> [@ast::capture_item] {
fn parse_fn_expr(p: parser, proto: ast::proto) -> @ast::expr {
let lo = p.get_last_lo_pos();
let capture_clause = parse_capture_clause(p);
let decl = parse_fn_decl(p, proto, ast::impure_fn);
let decl = parse_fn_decl(p, ast::impure_fn);
let body = parse_block(p);
ret mk_expr(p, lo, body.span.hi,
ast::expr_fn(decl, body, capture_clause));
ast::expr_fn(proto, decl, body, capture_clause));
}
fn parse_fn_block_expr(p: parser) -> @ast::expr {
......@@ -1738,7 +1738,7 @@ fn parse_ty_params(p: parser) -> [ast::ty_param] {
} else { [] }
}
fn parse_fn_decl(p: parser, proto: ast::proto, purity: ast::purity)
fn parse_fn_decl(p: parser, purity: ast::purity)
-> ast::fn_decl {
let inputs: ast::spanned<[ast::arg]> =
parse_seq(token::LPAREN, token::RPAREN, seq_sep(token::COMMA),
......@@ -1752,8 +1752,7 @@ fn parse_fn_decl(p: parser, proto: ast::proto, purity: ast::purity)
constrs = parse_constrs({|x| parse_ty_constr(inputs.node, x) }, p);
}
let (ret_style, ret_ty) = parse_ret_ty(p);
ret {proto: proto,
inputs: inputs.node,
ret {inputs: inputs.node,
output: ret_ty,
purity: purity,
cf: ret_style,
......@@ -1766,8 +1765,7 @@ fn parse_fn_block_decl(p: parser) -> ast::fn_decl {
seq_sep(token::COMMA), parse_fn_block_arg, p).node;
let output = eat(p, token::RARROW) ? parse_ty(p, false) :
@spanned(p.get_lo_pos(), p.get_hi_pos(), ast::ty_infer);
ret {proto: ast::proto_block,
inputs: inputs,
ret {inputs: inputs,
output: output,
purity: ast::impure_fn,
cf: ast::return_val,
......@@ -1789,11 +1787,11 @@ fn mk_item(p: parser, lo: uint, hi: uint, ident: ast::ident, node: ast::item_,
span: ast_util::mk_sp(lo, hi)};
}
fn parse_item_fn(p: parser, purity: ast::purity, proto: ast::proto,
fn parse_item_fn(p: parser, purity: ast::purity,
attrs: [ast::attribute]) -> @ast::item {
let lo = p.get_last_lo_pos();
let t = parse_fn_header(p);
let decl = parse_fn_decl(p, proto, purity);
let decl = parse_fn_decl(p, purity);
let body = parse_block(p);
ret mk_item(p, lo, body.span.hi, t.ident,
ast::item_fn(decl, t.tps, body), attrs);
......@@ -1819,10 +1817,10 @@ fn parse_anon_obj_field(p: parser) -> ast::anon_obj_field {
fn parse_method(p: parser, allow_tps: bool) -> @ast::method {
let lo = p.get_lo_pos();
let proto = parse_method_proto(p);
expect_word(p, "fn");
let ident = parse_value_ident(p);
let tps = allow_tps ? parse_ty_params(p) : [];
let decl = parse_fn_decl(p, proto, ast::impure_fn);
let decl = parse_fn_decl(p, ast::impure_fn);
let body = parse_block(p);
@{ident: ident, tps: tps, decl: decl, body: body,
id: p.get_id(), span: ast_util::mk_sp(lo, body.span.hi)}
......@@ -1900,8 +1898,7 @@ fn parse_item_res(p: parser, attrs: [ast::attribute]) -> @ast::item {
expect(p, token::RPAREN);
let dtor = parse_block_no_value(p);
let decl =
{proto: ast::proto_bare,
inputs:
{inputs:
[{mode: ast::by_ref, ty: t, ident: arg_ident,
id: p.get_id()}],
output: @spanned(lo, lo, ast::ty_nil),
......@@ -1974,7 +1971,7 @@ fn parse_item_native_fn(p: parser, attrs: [ast::attribute],
purity: ast::purity) -> @ast::native_item {
let lo = p.get_last_lo_pos();
let t = parse_fn_header(p);
let decl = parse_fn_decl(p, ast::proto_bare, purity);
let decl = parse_fn_decl(p, purity);
let hi = p.get_hi_pos();
expect(p, token::SEMI);
ret @{ident: t.ident,
......@@ -2107,10 +2104,6 @@ fn parse_item_tag(p: parser, attrs: [ast::attribute]) -> @ast::item {
ret mk_item(p, lo, hi, id, ast::item_tag(variants, ty_params), attrs);
}
fn parse_fn_item_proto(_p: parser) -> ast::proto {
ast::proto_bare
}
fn parse_fn_ty_proto(p: parser) -> ast::proto {
if p.peek() == token::AT {
p.bump();
......@@ -2120,32 +2113,22 @@ fn parse_fn_ty_proto(p: parser) -> ast::proto {
}
}
fn parse_method_proto(p: parser) -> ast::proto {
if eat_word(p, "fn") {
ret ast::proto_bare;
} else { unexpected(p, p.peek()); }
}
fn parse_item(p: parser, attrs: [ast::attribute]) -> option::t<@ast::item> {
if eat_word(p, "const") {
ret some(parse_item_const(p, attrs));
} else if eat_word(p, "inline") {
expect_word(p, "fn");
let proto = parse_fn_item_proto(p);
ret some(parse_item_fn(p, ast::impure_fn, proto, attrs));
ret some(parse_item_fn(p, ast::impure_fn, attrs));
} else if is_word(p, "fn") && p.look_ahead(1u) != token::LPAREN {
p.bump();
let proto = parse_fn_item_proto(p);
ret some(parse_item_fn(p, ast::impure_fn, proto, attrs));
ret some(parse_item_fn(p, ast::impure_fn, attrs));
} else if eat_word(p, "pure") {
expect_word(p, "fn");
let proto = parse_fn_item_proto(p);
ret some(parse_item_fn(p, ast::pure_fn, proto, attrs));
ret some(parse_item_fn(p, ast::pure_fn, attrs));
} else if is_word(p, "unsafe") && p.look_ahead(1u) != token::LBRACE {
p.bump();
expect_word(p, "fn");
let proto = parse_fn_item_proto(p);
ret some(parse_item_fn(p, ast::unsafe_fn, proto, attrs));
ret some(parse_item_fn(p, ast::unsafe_fn, attrs));
} else if eat_word(p, "mod") {
ret some(parse_item_mod(p, attrs));
} else if eat_word(p, "native") {
......
......@@ -305,8 +305,8 @@ fn print_field(s: ps, f: ast::ty_field) {
commasep(s, inconsistent, elts, print_type);
pclose(s);
}
ast::ty_fn(d) {
print_ty_fn(s, d, none::<str>);
ast::ty_fn(proto, d) {
print_ty_fn(s, proto, d, none::<str>);
}
ast::ty_obj(methods) {
head(s, "obj");
......@@ -519,7 +519,7 @@ fn print_ty_method(s: ps, m: ast::ty_method) {
hardbreak_if_not_bol(s);
cbox(s, indent_unit);
maybe_print_comment(s, m.span.lo);
print_ty_fn(s, m.decl, some(m.ident));
print_ty_fn(s, ast::proto_bare, m.decl, some(m.ident));
word(s.s, ";");
end(s);
}
......@@ -840,8 +840,8 @@ fn print_opt(s: ps, expr: option::t<@ast::expr>) {
}
bclose_(s, expr.span, alt_indent_unit);
}
ast::expr_fn(decl, body, captures) { // NDM captures
head(s, proto_to_str(decl.proto));
ast::expr_fn(proto, decl, body, captures) { // NDM captures
head(s, proto_to_str(proto));
print_fn_args_and_ret(s, decl);
space(s.s);
print_block(s, body);
......@@ -1147,8 +1147,9 @@ fn print_field(s: ps, f: ast::field_pat) {
fn print_fn(s: ps, decl: ast::fn_decl, name: ast::ident,
typarams: [ast::ty_param]) {
alt decl.purity {
ast::impure_fn. { head(s, proto_to_str(decl.proto)); }
_ { head(s, "pure fn"); }
ast::impure_fn. { head(s, "fn"); }
ast::unsafe_fn. { head(s, "unsafe fn"); }
ast::pure_fn. { head(s, "pure fn"); }
}
word(s.s, name);
print_type_params(s, typarams);
......@@ -1360,9 +1361,10 @@ fn print_mt(s: ps, mt: ast::mt) {
print_type(s, mt.ty);
}
fn print_ty_fn(s: ps, decl: ast::fn_decl, id: option::t<ast::ident>) {
fn print_ty_fn(s: ps, proto: ast::proto,
decl: ast::fn_decl, id: option::t<ast::ident>) {
ibox(s, indent_unit);
word(s.s, proto_to_str(decl.proto));
word(s.s, proto_to_str(proto));
alt id { some(id) { word(s.s, " "); word(s.s, id); } _ { } }
zerobreak(s.s);
popen(s);
......
......@@ -15,6 +15,28 @@
// hold functions that take visitors. A vt tag is used to break the cycle.
tag vt<E> { mk_vt(visitor<E>); }
tag fn_kind {
fk_item_fn(ident, [ty_param]); //< an item declared with fn()
fk_method(ident, [ty_param]);
fk_res(ident, [ty_param]);
fk_anon(proto); //< an anonymous function like lambda(...)
fk_fn_block; //< a block {||...}
}
fn name_of_fn(fk: fn_kind) -> ident {
alt fk {
fk_item_fn(name, _) | fk_method(name, _) | fk_res(name, _) { name }
fk_anon(_) | fk_fn_block. { "anon" }
}
}
fn tps_of_fn(fk: fn_kind) -> [ty_param] {
alt fk {
fk_item_fn(_, tps) | fk_method(_, tps) | fk_res(_, tps) { tps }
fk_anon(_) | fk_fn_block. { [] }
}
}
type visitor<E> =
// takes the components so that one function can be
// generic over constr and ty_constr
......@@ -31,8 +53,7 @@
visit_expr: fn@(@expr, E, vt<E>),
visit_ty: fn@(@ty, E, vt<E>),
visit_constr: fn@(@path, span, node_id, E, vt<E>),
visit_fn: fn@(fn_decl, [ty_param], blk, span, fn_ident, node_id,
E, vt<E>)};
visit_fn: fn@(fn_kind, fn_decl, blk, span, node_id, E, vt<E>)};
fn default_visitor<E>() -> visitor<E> {
ret @{visit_mod: bind visit_mod::<E>(_, _, _, _),
......@@ -48,7 +69,7 @@ fn default_visitor<E>() -> visitor<E> {
visit_expr: bind visit_expr::<E>(_, _, _),
visit_ty: bind skip_ty::<E>(_, _, _),
visit_constr: bind visit_constr::<E>(_, _, _, _, _),
visit_fn: bind visit_fn::<E>(_, _, _, _, _, _, _, _)};
visit_fn: bind visit_fn::<E>(_, _, _, _, _, _, _)};
}
fn visit_crate<E>(c: crate, e: E, v: vt<E>) {
......@@ -85,7 +106,7 @@ fn visit_item<E>(i: @item, e: E, v: vt<E>) {
alt i.node {
item_const(t, ex) { v.visit_ty(t, e, v); v.visit_expr(ex, e, v); }
item_fn(decl, tp, body) {
v.visit_fn(decl, tp, body, i.span, some(i.ident), i.id, e, v);
v.visit_fn(fk_item_fn(i.ident, tp), decl, body, i.span, i.id, e, v);
}
item_mod(m) { v.visit_mod(m, i.span, e, v); }
item_native_mod(nm) {
......@@ -94,8 +115,8 @@ fn visit_item<E>(i: @item, e: E, v: vt<E>) {
}
item_ty(t, tps) { v.visit_ty(t, e, v); visit_ty_params(tps, e, v); }
item_res(decl, tps, body, dtor_id, _) {
v.visit_fn(decl, tps, body, i.span, some(i.ident), dtor_id,
e, v);
v.visit_fn(fk_res(i.ident, tps), decl, body, i.span,
dtor_id, e, v);
}
item_tag(variants, tps) {
visit_ty_params(tps, e, v);
......@@ -107,8 +128,8 @@ fn visit_item<E>(i: @item, e: E, v: vt<E>) {
visit_ty_params(tps, e, v);
for f: obj_field in ob.fields { v.visit_ty(f.ty, e, v); }
for m: @method in ob.methods {
v.visit_fn(m.decl, m.tps, m.body, m.span,
some(m.ident), m.id, e, v);
v.visit_fn(fk_method(m.ident, m.tps), m.decl, m.body, m.span,
m.id, e, v);
}
}
item_impl(tps, ifce, ty, methods) {
......@@ -116,8 +137,8 @@ fn visit_item<E>(i: @item, e: E, v: vt<E>) {
alt ifce { some(ty) { v.visit_ty(ty, e, v); } _ {} }
v.visit_ty(ty, e, v);
for m in methods {
v.visit_fn(m.decl, m.tps, m.body, m.span,
some(m.ident), m.id, e, v);
v.visit_fn(fk_method(m.ident, m.tps), m.decl, m.body, m.span,
m.id, e, v);
}
}
item_iface(tps, methods) {
......@@ -142,7 +163,7 @@ fn visit_ty<E>(t: @ty, e: E, v: vt<E>) {
for f: ty_field in flds { v.visit_ty(f.node.mt.ty, e, v); }
}
ty_tup(ts) { for tt in ts { v.visit_ty(tt, e, v); } }
ty_fn(decl) {
ty_fn(_, decl) {
for a in decl.inputs { v.visit_ty(a.ty, e, v); }
for c: @constr in decl.constraints {
v.visit_constr(c.node.path, c.span, c.node.id, e, v);
......@@ -222,10 +243,10 @@ fn visit_fn_decl<E>(fd: fn_decl, e: E, v: vt<E>) {
v.visit_ty(fd.output, e, v);
}
fn visit_fn<E>(decl: fn_decl, tp: [ty_param], body: blk, _sp: span,
_i: fn_ident, _id: node_id, e: E, v: vt<E>) {
fn visit_fn<E>(fk: fn_kind, decl: fn_decl, body: blk, _sp: span,
_id: node_id, e: E, v: vt<E>) {
visit_fn_decl(decl, e, v);
visit_ty_params(tp, e, v);
visit_ty_params(tps_of_fn(fk), e, v);
v.visit_block(body, e, v);
}
......@@ -314,11 +335,11 @@ fn visit_expr<E>(ex: @expr, e: E, v: vt<E>) {
v.visit_expr(x, e, v);
for a: arm in arms { v.visit_arm(a, e, v); }
}
expr_fn(decl, body, _) {
v.visit_fn(decl, [], body, ex.span, none, ex.id, e, v);
expr_fn(proto, decl, body, _) {
v.visit_fn(fk_anon(proto), decl, body, ex.span, ex.id, e, v);
}
expr_fn_block(decl, body) {
v.visit_fn(decl, [], body, ex.span, none, ex.id, e, v);
v.visit_fn(fk_fn_block, decl, body, ex.span, ex.id, e, v);
}
expr_block(b) { v.visit_block(b, e, v); }
expr_assign(a, b) { v.visit_expr(b, e, v); v.visit_expr(a, e, v); }
......@@ -361,8 +382,8 @@ fn visit_expr<E>(ex: @expr, e: E, v: vt<E>) {
some(ex) { v.visit_expr(ex, e, v); }
}
for m: @method in anon_obj.methods {
v.visit_fn(m.decl, m.tps, m.body, m.span,
some(m.ident), m.id, e, v);
v.visit_fn(fk_method(m.ident, m.tps), m.decl, m.body, m.span,
m.id, e, v);
}
}
expr_mac(mac) { visit_mac(mac, e, v); }
......@@ -394,7 +415,7 @@ fn visit_arm<E>(a: arm, e: E, v: vt<E>) {
visit_expr: fn@(@expr),
visit_ty: fn@(@ty),
visit_constr: fn@(@path, span, node_id),
visit_fn: fn@(fn_decl, [ty_param], blk, span, fn_ident, node_id)};
visit_fn: fn@(fn_kind, fn_decl, blk, span, node_id)};
fn simple_ignore_ty(_t: @ty) {}
......@@ -412,8 +433,8 @@ fn default_simple_visitor() -> simple_visitor {
visit_expr: fn(_e: @expr) { },
visit_ty: simple_ignore_ty,
visit_constr: fn(_p: @path, _sp: span, _id: node_id) { },
visit_fn: fn(_d: fn_decl, _tps: [ty_param], _b: blk, _sp: span,
_ident: fn_ident, _id: node_id) { }
visit_fn: fn(_fk: fn_kind, _d: fn_decl, _b: blk, _sp: span,
_id: node_id) { }
};
}
......@@ -472,11 +493,11 @@ fn v_constr(f: fn@(@path, span, node_id), pt: @path, sp: span,
f(pt, sp, id);
visit_constr(pt, sp, id, e, v);
}
fn v_fn(f: fn@(fn_decl, [ty_param], blk, span, fn_ident, node_id),
decl: fn_decl, tps: [ty_param], body: blk, sp: span,
ident: fn_ident, id: node_id, &&e: (), v: vt<()>) {
f(decl, tps, body, sp, ident, id);
visit_fn(decl, tps, body, sp, ident, id, e, v);
fn v_fn(f: fn@(fn_kind, fn_decl, blk, span, node_id),
fk: fn_kind, decl: fn_decl, body: blk, sp: span,
id: node_id, &&e: (), v: vt<()>) {
f(fk, decl, body, sp, id);
visit_fn(fk, decl, body, sp, id, e, v);
}
let visit_ty = if v.visit_ty == simple_ignore_ty {
bind skip_ty(_, _, _)
......@@ -497,7 +518,7 @@ fn v_fn(f: fn@(fn_decl, [ty_param], blk, span, fn_ident, node_id),
visit_expr: bind v_expr(v.visit_expr, _, _, _),
visit_ty: visit_ty,
visit_constr: bind v_constr(v.visit_constr, _, _, _, _, _),
visit_fn: bind v_fn(v.visit_fn, _, _, _, _, _, _, _, _)
visit_fn: bind v_fn(v.visit_fn, _, _, _, _, _, _, _)
});
}
......
......@@ -23,10 +23,6 @@ fn mode_str_1(m: ty::mode) -> str {
alt m { ast::by_ref. { "ref" } _ { mode_str(m) } }
}
fn fn_ident_to_string(id: ast::node_id, i: ast::fn_ident) -> str {
ret alt i { none. { "anon" + int::str(id) } some(s) { s } };
}
fn ty_to_str(cx: ctxt, typ: t) -> str {
fn fn_input_to_str(cx: ctxt, input: {mode: middle::ty::mode, ty: t}) ->
str {
......
use std;
fn asSendfn( f : sendfn()->uint ) -> uint {
ret f();
}
fn asLambda( f : lambda()->uint ) -> uint {
ret f();
}
fn asBlock( f : block()->uint ) -> uint {
ret f();
}
fn main() {
let x = asSendfn({|| 22u});
assert(x == 22u);
let x = asLambda({|| 22u});
assert(x == 22u);
let x = asBlock({|| 22u});
assert(x == 22u);
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册