Extend the unchecked block stuff to allow unsafe blocks as well.
This commit is contained in:
parent
58b8e88356
commit
29584cc5ac
12 changed files with 114 additions and 35 deletions
|
@ -184,7 +184,7 @@ fn mk_tests(cx: test_ctxt) -> @ast::item {
|
|||
let test_descs = mk_test_desc_vec(cx);
|
||||
|
||||
let body_: ast::blk_ =
|
||||
checked_blk([], option::some(test_descs), cx.next_node_id());
|
||||
checked_block([], option::some(test_descs), cx.next_node_id());
|
||||
let body = nospan(body_);
|
||||
|
||||
let fn_ = {decl: decl, proto: proto, body: body};
|
||||
|
@ -303,7 +303,8 @@ fn mk_main(cx: test_ctxt) -> @ast::item {
|
|||
let test_main_call_expr = mk_test_main_call(cx);
|
||||
|
||||
let body_: ast::blk_ =
|
||||
checked_blk([], option::some(test_main_call_expr), cx.next_node_id());
|
||||
checked_block([], option::some(test_main_call_expr),
|
||||
cx.next_node_id());
|
||||
let body = {node: body_, span: dummy_sp()};
|
||||
|
||||
let fn_ = {decl: decl, proto: proto, body: body};
|
||||
|
|
|
@ -175,6 +175,7 @@ fn lookup_def(cnum: ast::crate_num, data: @[u8], did_: ast::def_id) ->
|
|||
let def =
|
||||
alt fam_ch as char {
|
||||
'c' { ast::def_const(did) }
|
||||
'u' { ast::def_fn(did, ast::unsafe_fn) }
|
||||
'f' { ast::def_fn(did, ast::impure_fn) }
|
||||
'p' { ast::def_fn(did, ast::pure_fn) }
|
||||
'F' { ast::def_native_fn(did) }
|
||||
|
|
|
@ -252,6 +252,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
|
|||
encode_def_id(ebml_w, local_def(item.id));
|
||||
encode_family(ebml_w,
|
||||
alt fd.decl.purity {
|
||||
unsafe_fn. { 'u' }
|
||||
pure_fn. { 'p' }
|
||||
impure_fn. { 'f' }
|
||||
} as u8);
|
||||
|
|
|
@ -4380,11 +4380,11 @@ fn trans_expr(bcx: @block_ctxt, e: @ast::expr, dest: dest) -> @block_ctxt {
|
|||
assert dest == ignore;
|
||||
ret trans_check_expr(bcx, a, "Assertion");
|
||||
}
|
||||
ast::expr_check(ast::checked., a) {
|
||||
ast::expr_check(ast::checked_expr., a) {
|
||||
assert dest == ignore;
|
||||
ret trans_check_expr(bcx, a, "Predicate");
|
||||
}
|
||||
ast::expr_check(ast::unchecked., a) {
|
||||
ast::expr_check(ast::claimed_expr., a) {
|
||||
assert dest == ignore;
|
||||
/* Claims are turned on and off by a global variable
|
||||
that the RTS sets. This case generates code to
|
||||
|
|
|
@ -1523,6 +1523,15 @@ fn check_pat(fcx: @fn_ctxt, map: ast_util::pat_id_map, pat: @ast::pat,
|
|||
}
|
||||
}
|
||||
|
||||
fn require_unsafe(sess: session::session, f_purity: ast::purity, sp: span) {
|
||||
alt f_purity {
|
||||
ast::unsafe_fn. { ret; }
|
||||
_ {
|
||||
sess.span_fatal(sp, "Found unsafe expression in safe function decl");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn require_impure(sess: session::session, f_purity: ast::purity, sp: span) {
|
||||
alt f_purity {
|
||||
ast::unsafe_fn. { ret; }
|
||||
|
@ -1536,7 +1545,22 @@ fn require_impure(sess: session::session, f_purity: ast::purity, sp: span) {
|
|||
fn require_pure_call(ccx: @crate_ctxt, caller_purity: ast::purity,
|
||||
callee: @ast::expr, sp: span) {
|
||||
alt caller_purity {
|
||||
ast::impure_fn. { ret; }
|
||||
ast::unsafe_fn. { ret; }
|
||||
ast::impure_fn. {
|
||||
alt ccx.tcx.def_map.find(callee.id) {
|
||||
some(ast::def_fn(_, ast::unsafe_fn.)) {
|
||||
ccx.tcx.sess.span_fatal
|
||||
(sp, "safe function calls function marked unsafe");
|
||||
}
|
||||
//some(ast::def_native_fn(_)) {
|
||||
// ccx.tcx.sess.span_fatal
|
||||
// (sp, "native functions can only be invoked from unsafe code");
|
||||
//}
|
||||
_ {
|
||||
}
|
||||
}
|
||||
ret;
|
||||
}
|
||||
ast::pure_fn. {
|
||||
alt ccx.tcx.def_map.find(callee.id) {
|
||||
some(ast::def_fn(_, ast::pure_fn.)) { ret; }
|
||||
|
@ -2066,8 +2090,9 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
|
|||
// If this is an unchecked block, turn off purity-checking
|
||||
let fcx_for_block =
|
||||
alt b.node.rules {
|
||||
ast::unchecked. { @{purity: ast::impure_fn with *fcx} }
|
||||
_ { fcx }
|
||||
ast::unchecked_blk. { @{purity: ast::impure_fn with *fcx} }
|
||||
ast::unsafe_blk. { @{purity: ast::unsafe_fn with *fcx} }
|
||||
ast::checked_blk. { fcx }
|
||||
};
|
||||
bot = check_block(fcx_for_block, b);
|
||||
let typ =
|
||||
|
|
|
@ -78,7 +78,8 @@ tag meta_item_ {
|
|||
type blk = spanned<blk_>;
|
||||
|
||||
type blk_ =
|
||||
{stmts: [@stmt], expr: option::t<@expr>, id: node_id, rules: check_mode};
|
||||
{stmts: [@stmt], expr: option::t<@expr>, id: node_id,
|
||||
rules: blk_check_mode};
|
||||
|
||||
type pat = {id: node_id, node: pat_, span: span};
|
||||
|
||||
|
@ -173,7 +174,9 @@ type field_ = {mut: mutability, ident: ident, expr: @expr};
|
|||
|
||||
type field = spanned<field_>;
|
||||
|
||||
tag check_mode { checked; unchecked; }
|
||||
tag blk_check_mode { checked_blk; unchecked_blk; unsafe_blk; }
|
||||
|
||||
tag expr_check_mode { claimed_expr; checked_expr; }
|
||||
|
||||
type expr = {id: node_id, node: expr_, span: span};
|
||||
|
||||
|
@ -222,7 +225,7 @@ tag expr_ {
|
|||
expr_assert(@expr);
|
||||
|
||||
/* preds that typestate is aware of */
|
||||
expr_check(check_mode, @expr);
|
||||
expr_check(expr_check_mode, @expr);
|
||||
|
||||
/* FIXME Would be nice if expr_check desugared
|
||||
to expr_if_check. */
|
||||
|
|
|
@ -185,13 +185,13 @@ fn eq_ty(&&a: @ty, &&b: @ty) -> bool { ret std::box::ptr_eq(a, b); }
|
|||
fn hash_ty(&&t: @ty) -> uint { ret t.span.lo << 16u + t.span.hi; }
|
||||
|
||||
fn block_from_expr(e: @expr) -> blk {
|
||||
let blk_ = checked_blk([], option::some::<@expr>(e), e.id);
|
||||
let blk_ = checked_block([], option::some::<@expr>(e), e.id);
|
||||
ret {node: blk_, span: e.span};
|
||||
}
|
||||
|
||||
fn checked_blk(stmts1: [@stmt], expr1: option::t<@expr>, id1: node_id) ->
|
||||
fn checked_block(stmts1: [@stmt], expr1: option::t<@expr>, id1: node_id) ->
|
||||
blk_ {
|
||||
ret {stmts: stmts1, expr: expr1, id: id1, rules: checked};
|
||||
ret {stmts: stmts1, expr: expr1, id: id1, rules: checked_blk};
|
||||
}
|
||||
|
||||
fn obj_field_from_anon_obj_field(f: anon_obj_field) -> obj_field {
|
||||
|
|
|
@ -828,7 +828,7 @@ fn parse_bottom_expr(p: parser) -> @ast::expr {
|
|||
p.peek() == token::OROR {
|
||||
ret parse_fn_block_expr(p);
|
||||
} else {
|
||||
let blk = parse_block_tail(p, lo, ast::checked);
|
||||
let blk = parse_block_tail(p, lo, ast::checked_blk);
|
||||
ret mk_expr(p, blk.span.lo, blk.span.hi, ast::expr_block(blk));
|
||||
}
|
||||
} else if eat_word(p, "if") {
|
||||
|
@ -853,9 +853,9 @@ fn parse_bottom_expr(p: parser) -> @ast::expr {
|
|||
} else if eat_word(p, "lambda") {
|
||||
ret parse_fn_expr(p, ast::proto_closure);
|
||||
} else if eat_word(p, "unchecked") {
|
||||
expect(p, token::LBRACE);
|
||||
let blk = parse_block_tail(p, lo, ast::unchecked);
|
||||
ret mk_expr(p, blk.span.lo, blk.span.hi, ast::expr_block(blk));
|
||||
ret parse_block_expr(p, lo, ast::unchecked_blk);
|
||||
} else if eat_word(p, "unsafe") {
|
||||
ret parse_block_expr(p, lo, ast::unsafe_blk);
|
||||
} else if p.peek() == token::LBRACKET {
|
||||
p.bump();
|
||||
let mut = parse_mutability(p);
|
||||
|
@ -872,7 +872,8 @@ fn parse_bottom_expr(p: parser) -> @ast::expr {
|
|||
ret mk_mac_expr(p, lo, p.get_hi_pos(), ast::mac_embed_type(ty));
|
||||
} else if p.peek() == token::POUND_LBRACE {
|
||||
p.bump();
|
||||
let blk = ast::mac_embed_block(parse_block_tail(p, lo, ast::checked));
|
||||
let blk = ast::mac_embed_block(
|
||||
parse_block_tail(p, lo, ast::checked_blk));
|
||||
ret mk_mac_expr(p, lo, p.get_hi_pos(), blk);
|
||||
} else if p.peek() == token::ELLIPSIS {
|
||||
p.bump();
|
||||
|
@ -948,7 +949,7 @@ fn parse_bottom_expr(p: parser) -> @ast::expr {
|
|||
|
||||
let e = parse_expr(p);
|
||||
hi = e.span.hi;
|
||||
ex = ast::expr_check(ast::checked, e);
|
||||
ex = ast::expr_check(ast::checked_expr, e);
|
||||
} else if eat_word(p, "claim") {
|
||||
/* Same rules as check, except that if check-claims
|
||||
is enabled (a command-line flag), then the parser turns
|
||||
|
@ -956,7 +957,7 @@ fn parse_bottom_expr(p: parser) -> @ast::expr {
|
|||
|
||||
let e = parse_expr(p);
|
||||
hi = e.span.hi;
|
||||
ex = ast::expr_check(ast::unchecked, e);
|
||||
ex = ast::expr_check(ast::claimed_expr, e);
|
||||
} else if eat_word(p, "ret") {
|
||||
if can_begin_expr(p.peek()) {
|
||||
let e = parse_expr(p);
|
||||
|
@ -1014,6 +1015,14 @@ fn parse_bottom_expr(p: parser) -> @ast::expr {
|
|||
ret mk_expr(p, lo, hi, ex);
|
||||
}
|
||||
|
||||
fn parse_block_expr(p: parser,
|
||||
lo: uint,
|
||||
blk_mode: ast::blk_check_mode) -> @ast::expr {
|
||||
expect(p, token::LBRACE);
|
||||
let blk = parse_block_tail(p, lo, blk_mode);
|
||||
ret mk_expr(p, blk.span.lo, blk.span.hi, ast::expr_block(blk));
|
||||
}
|
||||
|
||||
fn parse_syntax_ext(p: parser) -> @ast::expr {
|
||||
let lo = p.get_lo_pos();
|
||||
expect(p, token::POUND);
|
||||
|
@ -1311,7 +1320,7 @@ fn parse_fn_expr(p: parser, proto: ast::proto) -> @ast::expr {
|
|||
fn parse_fn_block_expr(p: parser) -> @ast::expr {
|
||||
let lo = p.get_last_lo_pos();
|
||||
let decl = parse_fn_block_decl(p);
|
||||
let body = parse_block_tail(p, lo, ast::checked);
|
||||
let body = parse_block_tail(p, lo, ast::checked_blk);
|
||||
let _fn = {decl: decl, proto: ast::proto_block, body: body};
|
||||
ret mk_expr(p, lo, body.span.hi, ast::expr_fn(_fn));
|
||||
}
|
||||
|
@ -1675,10 +1684,12 @@ fn stmt_ends_with_semi(stmt: ast::stmt) -> bool {
|
|||
fn parse_block(p: parser) -> ast::blk {
|
||||
let lo = p.get_lo_pos();
|
||||
if eat_word(p, "unchecked") {
|
||||
be parse_block_tail(p, lo, ast::unchecked);
|
||||
be parse_block_tail(p, lo, ast::unchecked_blk);
|
||||
} else if eat_word(p, "unsafe") {
|
||||
be parse_block_tail(p, lo, ast::unsafe_blk);
|
||||
} else {
|
||||
expect(p, token::LBRACE);
|
||||
be parse_block_tail(p, lo, ast::checked);
|
||||
be parse_block_tail(p, lo, ast::checked_blk);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1695,7 +1706,7 @@ fn parse_block_no_value(p: parser) -> ast::blk {
|
|||
// I guess that also means "already parsed the 'impure'" if
|
||||
// necessary, and this should take a qualifier.
|
||||
// some blocks start with "#{"...
|
||||
fn parse_block_tail(p: parser, lo: uint, s: ast::check_mode) -> ast::blk {
|
||||
fn parse_block_tail(p: parser, lo: uint, s: ast::blk_check_mode) -> ast::blk {
|
||||
let stmts: [@ast::stmt] = [];
|
||||
let expr: option::t<@ast::expr> = none;
|
||||
while p.peek() != token::RBRACE {
|
||||
|
|
|
@ -572,7 +572,11 @@ tag embed_type { block_macro; block_block_fn; block_normal; }
|
|||
|
||||
fn print_possibly_embedded_block(s: ps, blk: ast::blk, embedded: embed_type,
|
||||
indented: uint) {
|
||||
alt blk.node.rules { ast::unchecked. { word(s.s, "unchecked"); } _ { } }
|
||||
alt blk.node.rules {
|
||||
ast::unchecked_blk. { word(s.s, "unchecked"); }
|
||||
ast::unsafe_blk. { word(s.s, "unsafe"); }
|
||||
ast::checked_blk. { }
|
||||
}
|
||||
|
||||
maybe_print_comment(s, blk.span.lo);
|
||||
let ann_node = node_block(s, blk);
|
||||
|
@ -934,8 +938,8 @@ fn print_expr(s: ps, &&expr: @ast::expr) {
|
|||
}
|
||||
ast::expr_check(m, expr) {
|
||||
alt m {
|
||||
ast::unchecked. { word_nbsp(s, "claim"); }
|
||||
ast::checked. { word_nbsp(s, "check"); }
|
||||
ast::claimed_expr. { word_nbsp(s, "claim"); }
|
||||
ast::checked_expr. { word_nbsp(s, "check"); }
|
||||
}
|
||||
popen(s);
|
||||
print_expr(s, expr);
|
||||
|
|
|
@ -263,7 +263,7 @@ obj fd_buf_writer(fd: int, res: option::t<@fd_res>) {
|
|||
let nout = os::libc::write(fd, vbuf, len);
|
||||
if nout < 0 {
|
||||
log_err "error dumping buffer";
|
||||
log_err sys::rustrt::last_os_error();
|
||||
log_err sys::last_os_error();
|
||||
fail;
|
||||
}
|
||||
count += nout as uint;
|
||||
|
@ -299,7 +299,7 @@ fn file_buf_writer(path: str, flags: [fileflag]) -> buf_writer {
|
|||
});
|
||||
if fd < 0 {
|
||||
log_err "error opening file for writing";
|
||||
log_err sys::rustrt::last_os_error();
|
||||
log_err sys::last_os_error();
|
||||
fail;
|
||||
}
|
||||
ret fd_buf_writer(fd, option::some(@fd_res(fd)));
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
|
||||
import rustrt::size_of;
|
||||
|
||||
export rustrt;
|
||||
export size_of;
|
||||
//export rustrt;
|
||||
//export size_of;
|
||||
|
||||
native "rust" mod rustrt {
|
||||
|
||||
// Explicitly re-export native stuff we want to be made
|
||||
// available outside this crate. Otherwise it's
|
||||
// visible-in-crate, but not re-exported.
|
||||
|
@ -17,6 +14,42 @@ native "rust" mod rustrt {
|
|||
fn unsupervise();
|
||||
}
|
||||
|
||||
fn last_os_error() -> str {
|
||||
//unsafe {
|
||||
ret rustrt::last_os_error();
|
||||
//}
|
||||
}
|
||||
|
||||
fn size_of<T>() -> uint {
|
||||
//unsafe {
|
||||
ret rustrt::size_of::<T>();
|
||||
//}
|
||||
}
|
||||
|
||||
fn align_of<T>() -> uint {
|
||||
//unsafe {
|
||||
ret rustrt::align_of::<T>();
|
||||
//}
|
||||
}
|
||||
|
||||
fn refcount<T>(t: @T) -> uint {
|
||||
//unsafe {
|
||||
ret rustrt::refcount::<T>(t);
|
||||
//}
|
||||
}
|
||||
|
||||
fn do_gc() -> () {
|
||||
//unsafe {
|
||||
ret rustrt::do_gc();
|
||||
//}
|
||||
}
|
||||
|
||||
fn unsupervise() -> () {
|
||||
//unsafe {
|
||||
ret rustrt::unsupervise();
|
||||
//}
|
||||
}
|
||||
|
||||
// Local Variables:
|
||||
// mode: rust;
|
||||
// fill-column: 78;
|
||||
|
|
|
@ -32,7 +32,7 @@ iter range(lo: uint, hi: uint) -> uint {
|
|||
}
|
||||
|
||||
fn next_power_of_two(n: uint) -> uint {
|
||||
let halfbits: uint = sys::rustrt::size_of::<uint>() * 4u;
|
||||
let halfbits: uint = sys::size_of::<uint>() * 4u;
|
||||
let tmp: uint = n - 1u;
|
||||
let shift: uint = 1u;
|
||||
while shift <= halfbits { tmp |= tmp >> shift; shift <<= 1u; }
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue