From c28ada0368de78034e0930e01406f5e03a70d610 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 9 Dec 2011 08:16:04 -0800 Subject: [PATCH] first attempt, not happy with it --- Makefile.in | 4 ++ src/comp/middle/fn_usage.rs | 32 +++------- src/comp/middle/freevars.rs | 2 +- src/comp/middle/kind.rs | 9 ++- src/comp/middle/last_use.rs | 3 +- src/comp/middle/trans.rs | 3 +- src/comp/middle/tstate/pre_post_conditions.rs | 2 +- src/comp/middle/tstate/states.rs | 2 +- src/comp/middle/typeck.rs | 6 +- src/comp/syntax/ast.rs | 4 +- src/comp/syntax/fold.rs | 3 +- src/comp/syntax/parse/parser.rs | 58 ++++++++++--------- src/comp/syntax/print/pprust.rs | 2 +- src/comp/syntax/visit.rs | 3 +- 14 files changed, 66 insertions(+), 67 deletions(-) diff --git a/Makefile.in b/Makefile.in index 00c8188f8f6..66e6f3b1741 100644 --- a/Makefile.in +++ b/Makefile.in @@ -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 diff --git a/src/comp/middle/fn_usage.rs b/src/comp/middle/fn_usage.rs index 1bf9533f080..2dc585a6106 100644 --- a/src/comp/middle/fn_usage.rs +++ b/src/comp/middle/fn_usage.rs @@ -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); } diff --git a/src/comp/middle/freevars.rs b/src/comp/middle/freevars.rs index decdc220d16..bf1530e523f 100644 --- a/src/comp/middle/freevars.rs +++ b/src/comp/middle/freevars.rs @@ -33,7 +33,7 @@ fn collect_freevars(def_map: resolve::def_map, walker: fn@(visit::vt)) -> let walk_expr = lambda (expr: @ast::expr, &&depth: int, v: visit::vt) { 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) { diff --git a/src/comp/middle/kind.rs b/src/comp/middle/kind.rs index d771ba65faf..974c6ca5f7f 100644 --- a/src/comp/middle/kind.rs +++ b/src/comp/middle/kind.rs @@ -107,7 +107,14 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt) { 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); diff --git a/src/comp/middle/last_use.rs b/src/comp/middle/last_use.rs index fac179f386f..9c868fcf811 100644 --- a/src/comp/middle/last_use.rs +++ b/src/comp/middle/last_use.rs @@ -134,7 +134,8 @@ fn visit_expr(ex: @expr, cx: ctx, v: visit::vt) { 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); } diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 69f232045f2..0654b6da699 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -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); } diff --git a/src/comp/middle/tstate/pre_post_conditions.rs b/src/comp/middle/tstate/pre_post_conditions.rs index 0663682884c..929dbce308a 100644 --- a/src/comp/middle/tstate/pre_post_conditions.rs +++ b/src/comp/middle/tstate/pre_post_conditions.rs @@ -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) { diff --git a/src/comp/middle/tstate/states.rs b/src/comp/middle/tstate/states.rs index 1ac92efac69..414668f3c40 100644 --- a/src/comp/middle/tstate/states.rs +++ b/src/comp/middle/tstate/states.rs @@ -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) | diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index c8607fab723..efa73ea8f44 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -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; diff --git a/src/comp/syntax/ast.rs b/src/comp/syntax/ast.rs index d9d5260416e..62b24e220d8 100644 --- a/src/comp/syntax/ast.rs +++ b/src/comp/syntax/ast.rs @@ -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], + moves: [spanned] }; type capture = spanned; diff --git a/src/comp/syntax/fold.rs b/src/comp/syntax/fold.rs index fc1a45366fe..564087792ee 100644 --- a/src/comp/syntax/fold.rs +++ b/src/comp/syntax/fold.rs @@ -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)) diff --git a/src/comp/syntax/parse/parser.rs b/src/comp/syntax/parse/parser.rs index e927ffbbeff..063042e3bad 100644 --- a/src/comp/syntax/parse/parser.rs +++ b/src/comp/syntax/parse/parser.rs @@ -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] { 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 { diff --git a/src/comp/syntax/print/pprust.rs b/src/comp/syntax/print/pprust.rs index f58bea2ee74..16b9f89bf63 100644 --- a/src/comp/syntax/print/pprust.rs +++ b/src/comp/syntax/print/pprust.rs @@ -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 diff --git a/src/comp/syntax/visit.rs b/src/comp/syntax/visit.rs index 310d169805b..4f52f15b05d 100644 --- a/src/comp/syntax/visit.rs +++ b/src/comp/syntax/visit.rs @@ -273,7 +273,8 @@ fn visit_expr(ex: @expr, e: E, v: vt) { 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); }