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 $(foreach stage,1 2 3, \
$(eval $(call DEF_RUSTC_STAGE_TARGET,$(host),$(stage)))))) $(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 define DEF_RUSTC_TARGET
# $(1) == architecture # $(1) == architecture

View File

@ -7,8 +7,7 @@ export check_crate_fn_usage;
type fn_usage_ctx = { type fn_usage_ctx = {
tcx: ty::ctxt, tcx: ty::ctxt,
unsafe_fn_legal: bool, unsafe_fn_legal: bool
generic_bare_fn_legal: bool
}; };
fn fn_usage_expr(expr: @ast::expr, 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, _) { ast::expr_call(f, args, _) {
let f_ctx = {unsafe_fn_legal: true, let f_ctx = {unsafe_fn_legal: true with ctx};
generic_bare_fn_legal: true with ctx};
v.visit_expr(f, f_ctx, v); v.visit_expr(f, f_ctx, v);
let args_ctx = {unsafe_fn_legal: false, let args_ctx = {unsafe_fn_legal: false with ctx};
generic_bare_fn_legal: false with ctx};
visit::visit_exprs(args, args_ctx, v); visit::visit_exprs(args, args_ctx, v);
} }
ast::expr_bind(f, args) { ast::expr_bind(f, args) {
let f_ctx = {unsafe_fn_legal: false, let f_ctx = {unsafe_fn_legal: false with ctx};
generic_bare_fn_legal: true with ctx};
v.visit_expr(f, f_ctx, v); v.visit_expr(f, f_ctx, v);
let args_ctx = {unsafe_fn_legal: false, let args_ctx = {unsafe_fn_legal: false with ctx};
generic_bare_fn_legal: false with ctx};
for arg in args { for arg in args {
visit::visit_expr_opt(arg, args_ctx, v); visit::visit_expr_opt(arg, args_ctx, v);
} }
} }
_ { _ {
let subctx = {unsafe_fn_legal: false, let subctx = {unsafe_fn_legal: false with ctx};
generic_bare_fn_legal: false with ctx};
visit::visit_expr(expr, subctx, v); 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()}); with *visit::default_visitor()});
let ctx = { let ctx = {
tcx: tcx, tcx: tcx,
unsafe_fn_legal: false, unsafe_fn_legal: false
generic_bare_fn_legal: false
}; };
visit::visit_crate(*crate, ctx, visit); 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 = let walk_expr =
lambda (expr: @ast::expr, &&depth: int, v: visit::vt<int>) { lambda (expr: @ast::expr, &&depth: int, v: visit::vt<int>) {
alt expr.node { alt expr.node {
ast::expr_fn(f) { ast::expr_fn(f, captures) {
if f.proto == ast::proto_block || if f.proto == ast::proto_block ||
f.proto == ast::proto_shared(ast::sugar_normal) || f.proto == ast::proto_shared(ast::sugar_normal) ||
f.proto == ast::proto_shared(ast::sugar_sexy) { 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. {} 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) { for free in *freevars::get_freevars(cx.tcx, e.id) {
let id = ast_util::def_id_of_def(free).node; let id = ast_util::def_id_of_def(free).node;
let ty = ty::node_id_to_type(cx.tcx, id); 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)); let arg_ts = ty::ty_fn_args(cx.tcx, ty::expr_ty(cx.tcx, f));
for arg in args { for arg in args {
alt arg.node { alt arg.node {
expr_fn(_) { fns += [arg]; } //NDM--register captured as uses
expr_fn(_, captured) { fns += [arg]; }
_ { _ {
alt arg_ts[i].mode { alt arg_ts[i].mode {
by_mut_ref. { clear_if_path(cx, arg, v, false); } 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 assert op != ast::deref; // lvals are handled above
ret trans_unary(bcx, op, x, e.id, dest); 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_bind(f, args) { ret trans_bind(bcx, f, args, e.id, dest); }
ast::expr_copy(a) { ast::expr_copy(a) {
if !ty::expr_is_lval(tcx, a) { ret trans_expr(bcx, a, dest); } 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); find_pre_post_expr(fcx, arg);
copy_pre_post(fcx.ccx, e.id, arg); copy_pre_post(fcx.ccx, e.id, arg);
} }
expr_fn(f) { expr_fn(f, _) { // NDM captures
let rslt = expr_pp(fcx.ccx, e); let rslt = expr_pp(fcx.ccx, e);
clear_pp(rslt); clear_pp(rslt);
for def in *freevars::get_freevars(fcx.ccx.tcx, e.id) { 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_mac(_) { fcx.ccx.tcx.sess.bug("unexpanded macro"); }
expr_lit(l) { ret pure_exp(fcx.ccx, e.id, pres); } 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) { expr_block(b) {
ret find_pre_post_state_block(fcx, pres, b) | ret find_pre_post_state_block(fcx, pres, b) |
set_prestate_ann(fcx.ccx, e.id, pres) | set_prestate_ann(fcx.ccx, e.id, pres) |

View File

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

View File

@ -237,8 +237,8 @@ tag expr_ {
// At the moment, one can only capture local variables. // At the moment, one can only capture local variables.
type capture_ = { type capture_ = {
is_send: bool, is_send: bool,
copies: [ident], copies: [spanned<ident>],
moves: [ident] moves: [spanned<ident>]
}; };
type capture = spanned<capture_>; 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(expr, arms) {
expr_alt(fld.fold_expr(expr), vec::map(fld.fold_arm, 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_block(blk) { expr_block(fld.fold_block(blk)) }
expr_move(el, er) { expr_move(el, er) {
expr_move(fld.fold_expr(el), fld.fold_expr(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_fn;
fn_kw_lambda; fn_kw_lambda;
fn_kw_block; fn_kw_block;
}; }
type parse_sess = @{cm: codemap::codemap, mutable next_id: node_id}; 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*] // CC := [send; copy ID*; move ID*]
// //
// where any part is optional and trailing ; is permitted. // 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) { fn expect_opt_trailing_semi(p: parser) {
if !eat(p, token::SEMI) { if !eat(p, token::SEMI) {
if p.peek() != token::RBRACE { 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 = []; let res = [];
while true { while true {
alt p.peek() { alt p.peek() {
token::IDENT(_, _) { 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) { if !eat(p, token::COMMA) {
ret res; ret res;
} }
@ -1321,52 +1322,53 @@ fn parse_capture_clause(p: parser) -> (bool, @ast::capture) {
let copies = []; let copies = [];
let moves = []; let moves = [];
if p.peek() != token::LBRACE { let lo = p.get_lo_pos();
ret (is_send, captures); if eat(p, token::LBRACE) {
} while !eat(p, token::RBRACE) {
if eat_word(p, "send") {
expect(p, token::LBRACE); is_send = true;
while p.peek() != token::RBRACE { expect_opt_trailing_semi(p);
if eat_word(p, "send") { } else if eat_word(p, "copy") {
is_send = true; copies += eat_ident_list(p);
expect_opt_trailing_semi(p); expect_opt_trailing_semi(p);
} else if eat_word(p, "copy") { } else if eat_word(p, "move") {
copies += eat_ident_list(); moves += eat_ident_list(p);
expect_opt_trailing_semi(p); expect_opt_trailing_semi(p);
} else if eat_word(p, "move") { } else {
moves += eat_ident_list(); let s: str = "expecting send, copy, or move clause";
expect_opt_trailing_semi(p); p.fatal(s);
} 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 { fn parse_fn_expr(p: parser, kw: fn_kw) -> @ast::expr {
let lo = p.get_last_lo_pos(); 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 decl = parse_fn_decl(p, ast::impure_fn, ast::il_normal);
let body = parse_block(p); 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_fn., true) { ast::proto_bare }
(fn_kw_lambda., true) { ast::proto_send } (fn_kw_lambda., true) { ast::proto_send }
(fn_kw_lambda., false) { ast::proto_shared(ast::sugar_sexy) } (fn_kw_lambda., false) { ast::proto_shared(ast::sugar_sexy) }
(fn_kw_block., false) { ast::proto_block } (fn_kw_block., false) { ast::proto_block }
(_, true) { p.fatal("only lambda can be declared sendable"); } (_, true) { p.fatal("only lambda can be declared sendable"); }
} };
let _fn = {decl: decl, proto: proto, body: body}; 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 { fn parse_fn_block_expr(p: parser) -> @ast::expr {
let lo = p.get_last_lo_pos(); let lo = p.get_last_lo_pos();
let decl = parse_fn_block_decl(p); 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 body = parse_block_tail(p, lo, ast::default_blk);
let _fn = {decl: decl, proto: ast::proto_block, body: body}; 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 { 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); 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 // If the return type is the magic ty_infer, then we need to
// pretty print as a lambda-block // 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); v.visit_expr(x, e, v);
for a: arm in arms { v.visit_arm(a, 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_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_assign(a, b) { v.visit_expr(b, e, v); v.visit_expr(a, e, v); }
expr_copy(a) { v.visit_expr(a, e, v); } expr_copy(a) { v.visit_expr(a, e, v); }