first attempt, not happy with it
This commit is contained in:
parent
941101a9cd
commit
c28ada0368
14 changed files with 66 additions and 67 deletions
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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); }
|
||||
|
|
|
@ -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); }
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) |
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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_>;
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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); }
|
||||
|
|
Loading…
Add table
Reference in a new issue