first attempt, not happy with it

This commit is contained in:
Niko Matsakis 2011-12-09 08:16:04 -08:00
parent 941101a9cd
commit c28ada0368
14 changed files with 66 additions and 67 deletions

View File

@ -372,6 +372,10 @@ $(foreach host,$(CFG_TARGET_TRIPLES), \
$(eval $(foreach stage,1 2 3, \
$(eval $(call DEF_RUSTC_STAGE_TARGET,$(host),$(stage))))))
rustc-stage1: rustc-stage1-H-$(CFG_HOST_TRIPLE)
rustc-stage2: rustc-stage2-H-$(CFG_HOST_TRIPLE)
rustc-stage3: rustc-stage3-H-$(CFG_HOST_TRIPLE)
define DEF_RUSTC_TARGET
# $(1) == architecture

View File

@ -7,8 +7,7 @@ export check_crate_fn_usage;
type fn_usage_ctx = {
tcx: ty::ctxt,
unsafe_fn_legal: bool,
generic_bare_fn_legal: bool
unsafe_fn_legal: bool
};
fn fn_usage_expr(expr: @ast::expr,
@ -29,44 +28,28 @@ fn fn_usage_expr(expr: @ast::expr,
_ {}
}
}
if !ctx.generic_bare_fn_legal
&& ty::expr_has_ty_params(ctx.tcx, expr) {
alt ty::struct(ctx.tcx, ty::expr_ty(ctx.tcx, expr)) {
ty::ty_fn(ast::proto_bare., _, _, _, _) {
ctx.tcx.sess.span_fatal(
expr.span,
"generic bare functions can only be called or bound");
}
_ { }
}
}
}
ast::expr_call(f, args, _) {
let f_ctx = {unsafe_fn_legal: true,
generic_bare_fn_legal: true with ctx};
let f_ctx = {unsafe_fn_legal: true with ctx};
v.visit_expr(f, f_ctx, v);
let args_ctx = {unsafe_fn_legal: false,
generic_bare_fn_legal: false with ctx};
let args_ctx = {unsafe_fn_legal: false with ctx};
visit::visit_exprs(args, args_ctx, v);
}
ast::expr_bind(f, args) {
let f_ctx = {unsafe_fn_legal: false,
generic_bare_fn_legal: true with ctx};
let f_ctx = {unsafe_fn_legal: false with ctx};
v.visit_expr(f, f_ctx, v);
let args_ctx = {unsafe_fn_legal: false,
generic_bare_fn_legal: false with ctx};
let args_ctx = {unsafe_fn_legal: false with ctx};
for arg in args {
visit::visit_expr_opt(arg, args_ctx, v);
}
}
_ {
let subctx = {unsafe_fn_legal: false,
generic_bare_fn_legal: false with ctx};
let subctx = {unsafe_fn_legal: false with ctx};
visit::visit_expr(expr, subctx, v);
}
}
@ -79,8 +62,7 @@ fn check_crate_fn_usage(tcx: ty::ctxt, crate: @ast::crate) {
with *visit::default_visitor()});
let ctx = {
tcx: tcx,
unsafe_fn_legal: false,
generic_bare_fn_legal: false
unsafe_fn_legal: false
};
visit::visit_crate(*crate, ctx, visit);
}

View File

@ -33,7 +33,7 @@ fn collect_freevars(def_map: resolve::def_map, walker: fn@(visit::vt<int>)) ->
let walk_expr =
lambda (expr: @ast::expr, &&depth: int, v: visit::vt<int>) {
alt expr.node {
ast::expr_fn(f) {
ast::expr_fn(f, captures) {
if f.proto == ast::proto_block ||
f.proto == ast::proto_shared(ast::sugar_normal) ||
f.proto == ast::proto_shared(ast::sugar_sexy) {

View File

@ -107,7 +107,14 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) {
none. {}
}
}
expr_fn({proto: proto_shared(_), _}) {
expr_fn({proto: proto_send, _}, captures) {
for free in *freevars::get_freevars(cx.tcx, e.id) {
let id = ast_util::def_id_of_def(free).node;
let ty = ty::node_id_to_type(cx.tcx, id);
check_copy(cx, ty, e.span);
}
}
expr_fn({proto: proto_shared(_), _}, captures) {
for free in *freevars::get_freevars(cx.tcx, e.id) {
let id = ast_util::def_id_of_def(free).node;
let ty = ty::node_id_to_type(cx.tcx, id);

View File

@ -134,7 +134,8 @@ fn visit_expr(ex: @expr, cx: ctx, v: visit::vt<ctx>) {
let arg_ts = ty::ty_fn_args(cx.tcx, ty::expr_ty(cx.tcx, f));
for arg in args {
alt arg.node {
expr_fn(_) { fns += [arg]; }
//NDM--register captured as uses
expr_fn(_, captured) { fns += [arg]; }
_ {
alt arg_ts[i].mode {
by_mut_ref. { clear_if_path(cx, arg, v, false); }

View File

@ -4047,7 +4047,8 @@ 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(f) { ret trans_expr_fn(bcx, f, e.span, e.id, dest); }
// NDM captures
ast::expr_fn(f, cap) { ret trans_expr_fn(bcx, f, e.span, e.id, dest); }
ast::expr_bind(f, args) { ret trans_bind(bcx, f, args, e.id, dest); }
ast::expr_copy(a) {
if !ty::expr_is_lval(tcx, a) { ret trans_expr(bcx, a, dest); }

View File

@ -341,7 +341,7 @@ fn find_pre_post_expr(fcx: fn_ctxt, e: @expr) {
find_pre_post_expr(fcx, arg);
copy_pre_post(fcx.ccx, e.id, arg);
}
expr_fn(f) {
expr_fn(f, _) { // NDM captures
let rslt = expr_pp(fcx.ccx, e);
clear_pp(rslt);
for def in *freevars::get_freevars(fcx.ccx.tcx, e.id) {

View File

@ -358,7 +358,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(f) { ret pure_exp(fcx.ccx, e.id, pres); }
expr_fn(f, _) { ret pure_exp(fcx.ccx, e.id, pres); } // NDM Captures
expr_block(b) {
ret find_pre_post_state_block(fcx, pres, b) |
set_prestate_ann(fcx.ccx, e.id, pres) |

View File

@ -1001,7 +1001,7 @@ mod writeback {
if !wbcx.success { ret; }
resolve_type_vars_for_node(wbcx, e.span, e.id);
alt e.node {
ast::expr_fn(f) {
ast::expr_fn(f, _) { // NDM captures?
for input in f.decl.inputs {
resolve_type_vars_for_node(wbcx, e.span, input.id);
}
@ -1526,7 +1526,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
some(a) {
let is_block =
alt a.node {
ast::expr_fn(_) { true }
ast::expr_fn(_, _) { true }
_ { false }
};
if is_block == check_blocks {
@ -1902,7 +1902,7 @@ 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(f) {
ast::expr_fn(f, captures) { // NDM captures
let cx = @{tcx: tcx};
let fty = ty_of_fn_decl(cx.tcx, m_check_tyvar(fcx), f.decl,
f.proto, [], none).ty;

View File

@ -237,8 +237,8 @@ tag expr_ {
// At the moment, one can only capture local variables.
type capture_ = {
is_send: bool,
copies: [ident],
moves: [ident]
copies: [spanned<ident>],
moves: [spanned<ident>]
};
type capture = spanned<capture_>;

View File

@ -381,7 +381,8 @@ fn noop_fold_expr(e: expr_, fld: ast_fold) -> expr_ {
expr_alt(expr, arms) {
expr_alt(fld.fold_expr(expr), vec::map(fld.fold_arm, arms))
}
expr_fn(f) { expr_fn(fld.fold_fn(f)) }
// NDM fold_captures
expr_fn(f, captures) { expr_fn(fld.fold_fn(f), captures) }
expr_block(blk) { expr_block(fld.fold_block(blk)) }
expr_move(el, er) {
expr_move(fld.fold_expr(el), fld.fold_expr(er))

View File

@ -18,7 +18,7 @@ tag fn_kw {
fn_kw_fn;
fn_kw_lambda;
fn_kw_block;
};
}
type parse_sess = @{cm: codemap::codemap, mutable next_id: node_id};
@ -1292,7 +1292,7 @@ fn parse_if_expr(p: parser) -> @ast::expr {
// CC := [send; copy ID*; move ID*]
//
// where any part is optional and trailing ; is permitted.
fn parse_capture_clause(p: parser) -> (bool, @ast::capture) {
fn parse_capture_clause(p: parser) -> @ast::capture {
fn expect_opt_trailing_semi(p: parser) {
if !eat(p, token::SEMI) {
if p.peek() != token::RBRACE {
@ -1301,12 +1301,13 @@ fn parse_capture_clause(p: parser) -> (bool, @ast::capture) {
}
}
fn eat_ident_list(p: parser) -> [ast::ident] {
fn eat_ident_list(p: parser) -> [ast::spanned<ast::ident>] {
let res = [];
while true {
alt p.peek() {
token::IDENT(_, _) {
res += parse_ident(p);
let i = spanned(p.get_lo_pos(), p.get_hi_pos(), parse_ident(p));
res += [i];
if !eat(p, token::COMMA) {
ret res;
}
@ -1321,52 +1322,53 @@ fn parse_capture_clause(p: parser) -> (bool, @ast::capture) {
let copies = [];
let moves = [];
if p.peek() != token::LBRACE {
ret (is_send, captures);
}
expect(p, token::LBRACE);
while p.peek() != token::RBRACE {
if eat_word(p, "send") {
is_send = true;
expect_opt_trailing_semi(p);
} else if eat_word(p, "copy") {
copies += eat_ident_list();
expect_opt_trailing_semi(p);
} else if eat_word(p, "move") {
moves += eat_ident_list();
expect_opt_trailing_semi(p);
} else {
let s: str = "expecting send, copy, or move clause";
p.fatal(s);
let lo = p.get_lo_pos();
if eat(p, token::LBRACE) {
while !eat(p, token::RBRACE) {
if eat_word(p, "send") {
is_send = true;
expect_opt_trailing_semi(p);
} else if eat_word(p, "copy") {
copies += eat_ident_list(p);
expect_opt_trailing_semi(p);
} else if eat_word(p, "move") {
moves += eat_ident_list(p);
expect_opt_trailing_semi(p);
} else {
let s: str = "expecting send, copy, or move clause";
p.fatal(s);
}
}
}
let hi = p.get_last_hi_pos();
ret @{is_send: is_send, copies: copies, moves: moves};
ret @spanned(lo, hi, {is_send: is_send, copies: copies, moves: moves});
}
fn parse_fn_expr(p: parser, kw: fn_kw) -> @ast::expr {
let lo = p.get_last_lo_pos();
let cap = parse_capture_clause(p);
let captures = parse_capture_clause(p);
let decl = parse_fn_decl(p, ast::impure_fn, ast::il_normal);
let body = parse_block(p);
let proto = alt (kw, cap.is_send) {
let proto = alt (kw, captures.node.is_send) {
(fn_kw_fn., true) { ast::proto_bare }
(fn_kw_lambda., true) { ast::proto_send }
(fn_kw_lambda., false) { ast::proto_shared(ast::sugar_sexy) }
(fn_kw_block., false) { ast::proto_block }
(_, true) { p.fatal("only lambda can be declared sendable"); }
}
};
let _fn = {decl: decl, proto: proto, body: body};
ret mk_expr(p, lo, body.span.hi, ast::expr_fn(_fn, cap));
ret mk_expr(p, lo, body.span.hi, ast::expr_fn(_fn, captures));
}
fn parse_fn_block_expr(p: parser) -> @ast::expr {
let lo = p.get_last_lo_pos();
let decl = parse_fn_block_decl(p);
let mid = p.get_last_hi_pos();
let body = parse_block_tail(p, lo, ast::default_blk);
let _fn = {decl: decl, proto: ast::proto_block, body: body};
ret mk_expr(p, lo, body.span.hi, ast::expr_fn(_fn));
let captures = @spanned(lo, mid, {is_send: false, copies: [], moves: []});
ret mk_expr(p, lo, body.span.hi, ast::expr_fn(_fn, captures));
}
fn parse_else_expr(p: parser) -> @ast::expr {

View File

@ -818,7 +818,7 @@ fn print_expr(s: ps, &&expr: @ast::expr) {
}
bclose_(s, expr.span, alt_indent_unit);
}
ast::expr_fn(f) {
ast::expr_fn(f, captures) { // NDM captures
// If the return type is the magic ty_infer, then we need to
// pretty print as a lambda-block

View File

@ -273,7 +273,8 @@ 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(f) { v.visit_fn(f, [], ex.span, none, ex.id, e, v); }
// NDM add visit routine?
expr_fn(f, captures) { v.visit_fn(f, [], ex.span, none, 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); }
expr_copy(a) { v.visit_expr(a, e, v); }