split proto from fn_decl, as not all fn_decls know the proto.
this will address the (crashing) new test added.
This commit is contained in:
parent
d6db9506f4
commit
aa5382bb13
@ -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 collect_freevars(def_map: resolve::def_map, blk: ast::blk)
|
||||
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 resolve_names(e: @env, c: @ast::crate) {
|
||||
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) {
|
||||
|
@ -1,6 +1,5 @@
|
||||
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 syntax::visit;
|
||||
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 ast_ty_to_ty(tcx: ty::ctxt, mode: mode, &&ast_ty: @ast::ty) -> ty::t {
|
||||
}
|
||||
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 @@ mod collect {
|
||||
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 @@ mod writeback {
|
||||
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_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
|
||||
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_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
|
||||
#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 @@ tag expr_ {
|
||||
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 @@ tag ty_ {
|
||||
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 ty_constr = spanned<ty_constr_>;
|
||||
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 noop_fold_expr(e: expr_, fld: ast_fold) -> expr_ {
|
||||
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_ty_fn(proto: ast::proto, p: parser) -> ast::ty_ {
|
||||
// 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 parse_capture_clause(p: parser) -> @ast::capture_clause {
|
||||
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_type(s: ps, &&ty: @ast::ty) {
|
||||
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_expr(s: ps, &&expr: @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_pat(s: ps, &&pat: @ast::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 @@ import codemap::span;
|
||||
// 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 @@ type visitor<E> =
|
||||
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 @@ type simple_visitor =
|
||||
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 mk_simple_visitor(v: simple_visitor) -> vt<()> {
|
||||
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 mk_simple_visitor(v: simple_visitor) -> vt<()> {
|
||||
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 {
|
||||
|
22
src/test/run-pass/block-arg-call-as.rs
Normal file
22
src/test/run-pass/block-arg-call-as.rs
Normal file
@ -0,0 +1,22 @@
|
||||
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);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user