From 1b76bac41de9f52295a99db21abdd1ad5b0fc231 Mon Sep 17 00:00:00 2001 From: Philipp Brüschweiler Date: Fri, 21 Jun 2013 13:01:15 +0200 Subject: syntax: Remove unused tokens TyDesc, TyVisitor and intrinsic are not used anymore. --- src/libsyntax/parse/token.rs | 204 +++++++++++++++++++++---------------------- 1 file changed, 99 insertions(+), 105 deletions(-) (limited to 'src/libsyntax') diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 273a59f0a3d..d40b96f077b 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -331,21 +331,18 @@ pub mod special_idents { pub static str : ident = ident { name: 19, ctxt: 0}; // for the type /* outside of libsyntax */ - pub static ty_visitor : ident = ident { name: 20, ctxt: 0}; - pub static arg : ident = ident { name: 21, ctxt: 0}; - pub static descrim : ident = ident { name: 22, ctxt: 0}; - pub static clownshoe_abi : ident = ident { name: 23, ctxt: 0}; - pub static clownshoe_stack_shim : ident = ident { name: 24, ctxt: 0}; - pub static tydesc : ident = ident { name: 25, ctxt: 0}; - pub static main : ident = ident { name: 26, ctxt: 0}; - pub static opaque : ident = ident { name: 27, ctxt: 0}; - pub static blk : ident = ident { name: 28, ctxt: 0}; - pub static statik : ident = ident { name: 29, ctxt: 0}; - pub static intrinsic : ident = ident { name: 30, ctxt: 0}; - pub static clownshoes_foreign_mod: ident = ident { name: 31, ctxt: 0}; - pub static unnamed_field: ident = ident { name: 32, ctxt: 0}; - pub static c_abi: ident = ident { name: 33, ctxt: 0}; - pub static type_self: ident = ident { name: 34, ctxt: 0}; // `Self` + pub static arg : ident = ident { name: 20, ctxt: 0}; + pub static descrim : ident = ident { name: 21, ctxt: 0}; + pub static clownshoe_abi : ident = ident { name: 22, ctxt: 0}; + pub static clownshoe_stack_shim : ident = ident { name: 23, ctxt: 0}; + pub static main : ident = ident { name: 24, ctxt: 0}; + pub static opaque : ident = ident { name: 25, ctxt: 0}; + pub static blk : ident = ident { name: 26, ctxt: 0}; + pub static statik : ident = ident { name: 27, ctxt: 0}; + pub static clownshoes_foreign_mod: ident = ident { name: 28, ctxt: 0}; + pub static unnamed_field: ident = ident { name: 29, ctxt: 0}; + pub static c_abi: ident = ident { name: 30, ctxt: 0}; + pub static type_self: ident = ident { name: 31, ctxt: 0}; // `Self` } /** @@ -426,59 +423,56 @@ fn mk_fresh_ident_interner() -> @ident_interner { "tt", // 17 "matchers", // 18 "str", // 19 - "TyVisitor", // 20 - "arg", // 21 - "descrim", // 22 - "__rust_abi", // 23 - "__rust_stack_shim", // 24 - "TyDesc", // 25 - "main", // 26 - "", // 27 - "blk", // 28 - "static", // 29 - "intrinsic", // 30 - "__foreign_mod__", // 31 - "__field__", // 32 - "C", // 33 - "Self", // 34 - - "as", // 35 - "break", // 36 - "const", // 37 - "copy", // 38 - "do", // 39 - "else", // 40 - "enum", // 41 - "extern", // 42 - "false", // 43 - "fn", // 44 - "for", // 45 - "if", // 46 - "impl", // 47 - "let", // 48 - "__log", // 49 - "loop", // 50 - "match", // 51 - "mod", // 52 - "mut", // 53 - "once", // 54 - "priv", // 55 - "pub", // 56 - "pure", // 57 - "ref", // 58 - "return", // 59 - "static", // 29 -- also a special ident + "arg", // 20 + "descrim", // 21 + "__rust_abi", // 22 + "__rust_stack_shim", // 23 + "main", // 24 + "", // 25 + "blk", // 26 + "static", // 27 + "__foreign_mod__", // 28 + "__field__", // 29 + "C", // 30 + "Self", // 31 + + "as", // 32 + "break", // 33 + "const", // 34 + "copy", // 35 + "do", // 36 + "else", // 37 + "enum", // 38 + "extern", // 39 + "false", // 40 + "fn", // 41 + "for", // 42 + "if", // 43 + "impl", // 44 + "let", // 45 + "__log", // 46 + "loop", // 47 + "match", // 48 + "mod", // 49 + "mut", // 50 + "once", // 51 + "priv", // 52 + "pub", // 53 + "pure", // 54 + "ref", // 55 + "return", // 56 + "static", // 27 -- also a special ident "self", // 8 -- also a special ident - "struct", // 60 - "super", // 61 - "true", // 62 - "trait", // 63 - "type", // 64 - "unsafe", // 65 - "use", // 66 - "while", // 67 - - "be", // 68 + "struct", // 57 + "super", // 58 + "true", // 59 + "trait", // 60 + "type", // 61 + "unsafe", // 62 + "use", // 63 + "while", // 64 + + "be", // 65 ]; @ident_interner { @@ -612,42 +606,42 @@ pub mod keywords { impl Keyword { pub fn to_ident(&self) -> ident { match *self { - As => ident { name: 35, ctxt: 0 }, - Break => ident { name: 36, ctxt: 0 }, - Const => ident { name: 37, ctxt: 0 }, - Copy => ident { name: 38, ctxt: 0 }, - Do => ident { name: 39, ctxt: 0 }, - Else => ident { name: 40, ctxt: 0 }, - Enum => ident { name: 41, ctxt: 0 }, - Extern => ident { name: 42, ctxt: 0 }, - False => ident { name: 43, ctxt: 0 }, - Fn => ident { name: 44, ctxt: 0 }, - For => ident { name: 45, ctxt: 0 }, - If => ident { name: 46, ctxt: 0 }, - Impl => ident { name: 47, ctxt: 0 }, - Let => ident { name: 48, ctxt: 0 }, - __Log => ident { name: 49, ctxt: 0 }, - Loop => ident { name: 50, ctxt: 0 }, - Match => ident { name: 51, ctxt: 0 }, - Mod => ident { name: 52, ctxt: 0 }, - Mut => ident { name: 53, ctxt: 0 }, - Once => ident { name: 54, ctxt: 0 }, - Priv => ident { name: 55, ctxt: 0 }, - Pub => ident { name: 56, ctxt: 0 }, - Pure => ident { name: 57, ctxt: 0 }, - Ref => ident { name: 58, ctxt: 0 }, - Return => ident { name: 59, ctxt: 0 }, - Static => ident { name: 29, ctxt: 0 }, + As => ident { name: 32, ctxt: 0 }, + Break => ident { name: 33, ctxt: 0 }, + Const => ident { name: 34, ctxt: 0 }, + Copy => ident { name: 35, ctxt: 0 }, + Do => ident { name: 36, ctxt: 0 }, + Else => ident { name: 37, ctxt: 0 }, + Enum => ident { name: 38, ctxt: 0 }, + Extern => ident { name: 39, ctxt: 0 }, + False => ident { name: 40, ctxt: 0 }, + Fn => ident { name: 41, ctxt: 0 }, + For => ident { name: 42, ctxt: 0 }, + If => ident { name: 43, ctxt: 0 }, + Impl => ident { name: 44, ctxt: 0 }, + Let => ident { name: 45, ctxt: 0 }, + __Log => ident { name: 46, ctxt: 0 }, + Loop => ident { name: 47, ctxt: 0 }, + Match => ident { name: 48, ctxt: 0 }, + Mod => ident { name: 49, ctxt: 0 }, + Mut => ident { name: 50, ctxt: 0 }, + Once => ident { name: 51, ctxt: 0 }, + Priv => ident { name: 52, ctxt: 0 }, + Pub => ident { name: 53, ctxt: 0 }, + Pure => ident { name: 54, ctxt: 0 }, + Ref => ident { name: 55, ctxt: 0 }, + Return => ident { name: 56, ctxt: 0 }, + Static => ident { name: 27, ctxt: 0 }, Self => ident { name: 8, ctxt: 0 }, - Struct => ident { name: 60, ctxt: 0 }, - Super => ident { name: 61, ctxt: 0 }, - True => ident { name: 62, ctxt: 0 }, - Trait => ident { name: 63, ctxt: 0 }, - Type => ident { name: 64, ctxt: 0 }, - Unsafe => ident { name: 65, ctxt: 0 }, - Use => ident { name: 66, ctxt: 0 }, - While => ident { name: 67, ctxt: 0 }, - Be => ident { name: 68, ctxt: 0 }, + Struct => ident { name: 57, ctxt: 0 }, + Super => ident { name: 58, ctxt: 0 }, + True => ident { name: 59, ctxt: 0 }, + Trait => ident { name: 60, ctxt: 0 }, + Type => ident { name: 61, ctxt: 0 }, + Unsafe => ident { name: 62, ctxt: 0 }, + Use => ident { name: 63, ctxt: 0 }, + While => ident { name: 64, ctxt: 0 }, + Be => ident { name: 65, ctxt: 0 }, } } } @@ -663,7 +657,7 @@ pub fn is_keyword(kw: keywords::Keyword, tok: &Token) -> bool { pub fn is_any_keyword(tok: &Token) -> bool { match *tok { token::IDENT(sid, false) => match sid.name { - 8 | 29 | 35 .. 68 => true, + 8 | 27 | 32 .. 65 => true, _ => false, }, _ => false @@ -673,7 +667,7 @@ pub fn is_any_keyword(tok: &Token) -> bool { pub fn is_strict_keyword(tok: &Token) -> bool { match *tok { token::IDENT(sid, false) => match sid.name { - 8 | 29 | 35 .. 67 => true, + 8 | 27 | 32 .. 64 => true, _ => false, }, _ => false, @@ -683,7 +677,7 @@ pub fn is_strict_keyword(tok: &Token) -> bool { pub fn is_reserved_keyword(tok: &Token) -> bool { match *tok { token::IDENT(sid, false) => match sid.name { - 68 => true, + 65 => true, _ => false, }, _ => false, -- cgit 1.4.1-3-g733a5 From 1841b31c61c2cca9c54264edd2a78b994b9638e9 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 21 Jun 2013 18:46:34 -0700 Subject: Add 'static mut' items to the language --- src/librustc/metadata/decoder.rs | 16 +++++--- src/librustc/metadata/encoder.rs | 10 +++-- src/librustc/middle/astencode.rs | 2 +- src/librustc/middle/check_const.rs | 6 +-- src/librustc/middle/check_match.rs | 10 ++--- src/librustc/middle/const_eval.rs | 6 +-- src/librustc/middle/effect.rs | 10 ++++- src/librustc/middle/mem_categorization.rs | 28 ++++++++----- src/librustc/middle/pat_util.rs | 2 +- src/librustc/middle/resolve.rs | 17 ++++---- src/librustc/middle/trans/_match.rs | 9 +++-- src/librustc/middle/trans/base.rs | 12 ++++-- src/librustc/middle/trans/callee.rs | 2 +- src/librustc/middle/trans/consts.rs | 12 +++--- src/librustc/middle/trans/expr.rs | 2 +- src/librustc/middle/trans/reachable.rs | 2 +- src/librustc/middle/ty.rs | 2 +- src/librustc/middle/typeck/check/mod.rs | 4 +- src/librustc/middle/typeck/collect.rs | 2 +- src/librustdoc/extract.rs | 2 +- src/librustdoc/tystr_pass.rs | 2 +- src/libsyntax/ast.rs | 4 +- src/libsyntax/ast_map.rs | 2 +- src/libsyntax/ast_util.rs | 2 +- src/libsyntax/fold.rs | 2 +- src/libsyntax/parse/parser.rs | 5 ++- src/libsyntax/print/pprust.rs | 5 ++- src/libsyntax/visit.rs | 2 +- src/test/auxiliary/static_mut_xc.rs | 1 + src/test/compile-fail/static-mut-bad-types.rs | 17 ++++++++ src/test/compile-fail/static-mut-not-constant.rs | 13 ++++++ src/test/compile-fail/static-mut-not-pat.rs | 26 ++++++++++++ .../compile-fail/static-mut-requires-unsafe.rs | 17 ++++++++ src/test/run-pass/static-mut-xc.rs | 46 ++++++++++++++++++++++ 34 files changed, 230 insertions(+), 70 deletions(-) create mode 100644 src/test/auxiliary/static_mut_xc.rs create mode 100644 src/test/compile-fail/static-mut-bad-types.rs create mode 100644 src/test/compile-fail/static-mut-not-constant.rs create mode 100644 src/test/compile-fail/static-mut-not-pat.rs create mode 100644 src/test/compile-fail/static-mut-requires-unsafe.rs create mode 100644 src/test/run-pass/static-mut-xc.rs (limited to 'src/libsyntax') diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 9ace8677dab..83e59d98085 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -97,7 +97,8 @@ fn lookup_item(item_id: int, data: @~[u8]) -> ebml::Doc { #[deriving(Eq)] enum Family { - Const, // c + ImmStatic, // c + MutStatic, // b Fn, // f UnsafeFn, // u PureFn, // p @@ -122,7 +123,8 @@ enum Family { fn item_family(item: ebml::Doc) -> Family { let fam = reader::get_doc(item, tag_items_data_item_family); match reader::doc_as_u8(fam) as char { - 'c' => Const, + 'c' => ImmStatic, + 'b' => MutStatic, 'f' => Fn, 'u' => UnsafeFn, 'p' => PureFn, @@ -321,7 +323,8 @@ fn item_to_def_like(item: ebml::Doc, did: ast::def_id, cnum: ast::crate_num) -> def_like { let fam = item_family(item); match fam { - Const => dl_def(ast::def_const(did)), + ImmStatic => dl_def(ast::def_static(did, false)), + MutStatic => dl_def(ast::def_static(did, true)), Struct => dl_def(ast::def_struct(did)), UnsafeFn => dl_def(ast::def_fn(did, ast::unsafe_fn)), Fn => dl_def(ast::def_fn(did, ast::impure_fn)), @@ -900,8 +903,8 @@ pub fn get_item_visibility(cdata: cmd, id: ast::node_id) fn family_has_type_params(fam: Family) -> bool { match fam { - Const | ForeignType | Mod | ForeignMod | PublicField | PrivateField - | ForeignFn => false, + ImmStatic | ForeignType | Mod | ForeignMod | PublicField | PrivateField + | ForeignFn | MutStatic => false, _ => true } } @@ -931,7 +934,8 @@ fn describe_def(items: ebml::Doc, id: ast::def_id) -> ~str { fn item_family_to_str(fam: Family) -> ~str { match fam { - Const => ~"const", + ImmStatic => ~"static", + MutStatic => ~"static mut", Fn => ~"fn", UnsafeFn => ~"unsafe fn", PureFn => ~"pure fn", diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 94cad18ece2..96cf7284169 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -785,7 +785,7 @@ fn encode_info_for_item(ecx: &EncodeContext, let must_write = match item.node { item_enum(_, _) | item_impl(*) | item_trait(*) | item_struct(*) | - item_mod(*) | item_foreign_mod(*) | item_const(*) => true, + item_mod(*) | item_foreign_mod(*) | item_static(*) => true, _ => false }; if !must_write && !reachable(ecx, item.id) { return; } @@ -800,11 +800,15 @@ fn encode_info_for_item(ecx: &EncodeContext, ecx.tcx.sess.codemap.span_to_str(item.span)); match item.node { - item_const(_, _) => { + item_static(_, m, _) => { add_to_index(); ebml_w.start_tag(tag_items_data_item); encode_def_id(ebml_w, local_def(item.id)); - encode_family(ebml_w, 'c'); + if m == ast::m_mutbl { + encode_family(ebml_w, 'b'); + } else { + encode_family(ebml_w, 'c'); + } encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id)); encode_symbol(ecx, ebml_w, item.id); encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident)); diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index 925b1f506d7..5aad0d894da 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -384,7 +384,7 @@ impl tr for ast::def { ast::def_self(nid, i) => { ast::def_self(xcx.tr_id(nid), i) } ast::def_mod(did) => { ast::def_mod(did.tr(xcx)) } ast::def_foreign_mod(did) => { ast::def_foreign_mod(did.tr(xcx)) } - ast::def_const(did) => { ast::def_const(did.tr(xcx)) } + ast::def_static(did, m) => { ast::def_static(did.tr(xcx), m) } ast::def_arg(nid, b) => { ast::def_arg(xcx.tr_id(nid), b) } ast::def_local(nid, b) => { ast::def_local(xcx.tr_id(nid), b) } ast::def_variant(e_did, v_did) => { diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs index 126d2db6879..c1906820883 100644 --- a/src/librustc/middle/check_const.rs +++ b/src/librustc/middle/check_const.rs @@ -43,7 +43,7 @@ pub fn check_item(sess: Session, (_is_const, v): (bool, visit::vt)) { match it.node { - item_const(_, ex) => { + item_static(_, _, ex) => { (v.visit_expr)(ex, (true, v)); check_item_recursion(sess, ast_map, def_map, it); } @@ -124,7 +124,7 @@ pub fn check_expr(sess: Session, items without type parameters"); } match def_map.find(&e.id) { - Some(&def_const(_)) | + Some(&def_static(*)) | Some(&def_fn(_, _)) | Some(&def_variant(_, _)) | Some(&def_struct(_)) => { } @@ -237,7 +237,7 @@ pub fn check_item_recursion(sess: Session, match e.node { expr_path(*) => { match env.def_map.find(&e.id) { - Some(&def_const(def_id)) => { + Some(&def_static(def_id, _)) => { if ast_util::is_local(def_id) { match env.ast_map.get_copy(&def_id.node) { ast_map::node_item(it, _) => { diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs index a2532405870..b4c8a6b19c2 100644 --- a/src/librustc/middle/check_match.rs +++ b/src/librustc/middle/check_match.rs @@ -304,7 +304,7 @@ pub fn pat_ctor_id(cx: @MatchCheckCtxt, p: @pat) -> Option { pat_ident(_, _, _) | pat_enum(_, _) => { match cx.tcx.def_map.find(&pat.id) { Some(&def_variant(_, id)) => Some(variant(id)), - Some(&def_const(did)) => { + Some(&def_static(did, false)) => { let const_expr = lookup_const_by_id(cx.tcx, did).get(); Some(val(eval_const_expr(cx.tcx, const_expr))) } @@ -339,7 +339,7 @@ pub fn is_wild(cx: @MatchCheckCtxt, p: @pat) -> bool { pat_wild => { true } pat_ident(_, _, _) => { match cx.tcx.def_map.find(&pat.id) { - Some(&def_variant(_, _)) | Some(&def_const(*)) => { false } + Some(&def_variant(_, _)) | Some(&def_static(*)) => { false } _ => { true } } } @@ -499,7 +499,7 @@ pub fn specialize(cx: @MatchCheckCtxt, None } } - Some(&def_const(did)) => { + Some(&def_static(did, _)) => { let const_expr = lookup_const_by_id(cx.tcx, did).get(); let e_v = eval_const_expr(cx.tcx, const_expr); @@ -549,7 +549,7 @@ pub fn specialize(cx: @MatchCheckCtxt, } pat_enum(_, args) => { match cx.tcx.def_map.get_copy(&pat_id) { - def_const(did) => { + def_static(did, _) => { let const_expr = lookup_const_by_id(cx.tcx, did).get(); let e_v = eval_const_expr(cx.tcx, const_expr); @@ -790,7 +790,7 @@ pub fn is_refutable(cx: @MatchCheckCtxt, pat: &pat) -> bool { return true; } } - Some(&def_const(*)) => return true, + Some(&def_static(*)) => return true, _ => () } diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index 988ad519f42..1a7cd856bed 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -166,7 +166,7 @@ pub fn classify(e: @expr, pub fn lookup_const(tcx: ty::ctxt, e: @expr) -> Option<@expr> { match tcx.def_map.find(&e.id) { - Some(&ast::def_const(def_id)) => lookup_const_by_id(tcx, def_id), + Some(&ast::def_static(def_id, false)) => lookup_const_by_id(tcx, def_id), _ => None } } @@ -178,7 +178,7 @@ pub fn lookup_const_by_id(tcx: ty::ctxt, match tcx.items.find(&def_id.node) { None => None, Some(&ast_map::node_item(it, _)) => match it.node { - item_const(_, const_expr) => Some(const_expr), + item_static(_, ast::m_imm, const_expr) => Some(const_expr), _ => None }, Some(_) => None @@ -195,7 +195,7 @@ pub fn lookup_const_by_id(tcx: ty::ctxt, match csearch::maybe_get_item_ast(tcx, def_id, |a, b, c, d| astencode::decode_inlined_item(a, b, maps, /*bar*/ copy c, d)) { csearch::found(ast::ii_item(item)) => match item.node { - item_const(_, const_expr) => Some(const_expr), + item_static(_, ast::m_imm, const_expr) => Some(const_expr), _ => None }, _ => None diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs index d9481c26dad..513b2015a83 100644 --- a/src/librustc/middle/effect.rs +++ b/src/librustc/middle/effect.rs @@ -17,7 +17,7 @@ use middle::typeck::method_map; use util::ppaux; use syntax::ast::{deref, expr_call, expr_inline_asm, expr_method_call}; -use syntax::ast::{expr_unary, node_id, unsafe_blk, unsafe_fn}; +use syntax::ast::{expr_unary, node_id, unsafe_blk, unsafe_fn, expr_path}; use syntax::ast; use syntax::codemap::span; use syntax::visit::{fk_item_fn, fk_method}; @@ -143,6 +143,14 @@ pub fn check_crate(tcx: ty::ctxt, expr_inline_asm(*) => { require_unsafe(expr.span, "use of inline assembly") } + expr_path(*) => { + match ty::resolve_expr(tcx, expr) { + ast::def_static(_, true) => { + require_unsafe(expr.span, "use of mutable static") + } + _ => {} + } + } _ => {} } diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 2ced57dc885..f93cb265d78 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -447,19 +447,29 @@ impl mem_categorization_ctxt { -> cmt { match def { ast::def_fn(*) | ast::def_static_method(*) | ast::def_mod(_) | - ast::def_foreign_mod(_) | ast::def_const(_) | + ast::def_foreign_mod(_) | ast::def_static(_, false) | ast::def_use(_) | ast::def_variant(*) | ast::def_trait(_) | ast::def_ty(_) | ast::def_prim_ty(_) | ast::def_ty_param(*) | ast::def_struct(*) | ast::def_typaram_binder(*) | ast::def_region(_) | ast::def_label(_) | ast::def_self_ty(*) => { - @cmt_ { - id:id, - span:span, - cat:cat_static_item, - mutbl: McImmutable, - ty:expr_ty - } + @cmt_ { + id:id, + span:span, + cat:cat_static_item, + mutbl: McImmutable, + ty:expr_ty + } + } + + ast::def_static(_, true) => { + @cmt_ { + id:id, + span:span, + cat:cat_static_item, + mutbl: McDeclared, + ty:expr_ty + } } ast::def_arg(vid, mutbl) => { @@ -894,7 +904,7 @@ impl mem_categorization_ctxt { self.cat_pattern(cmt_field, subpat, op); } } - Some(&ast::def_const(*)) => { + Some(&ast::def_static(*)) => { for subpats.iter().advance |&subpat| { self.cat_pattern(cmt, subpat, op); } diff --git a/src/librustc/middle/pat_util.rs b/src/librustc/middle/pat_util.rs index 1237e9fb4a2..5bd39e85863 100644 --- a/src/librustc/middle/pat_util.rs +++ b/src/librustc/middle/pat_util.rs @@ -45,7 +45,7 @@ pub fn pat_is_const(dm: resolve::DefMap, pat: &pat) -> bool { match pat.node { pat_ident(_, _, None) | pat_enum(*) => { match dm.find(&pat.id) { - Some(&def_const(*)) => true, + Some(&def_static(_, false)) => true, _ => false } } diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index eed0b12b9e1..7f9086be81d 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -1146,12 +1146,13 @@ impl Resolver { } // These items live in the value namespace. - item_const(*) => { + item_static(_, m, _) => { let (name_bindings, _) = self.add_child(ident, parent, ForbidDuplicateValues, sp); + let mutbl = m == ast::m_mutbl; name_bindings.define_value - (privacy, def_const(local_def(item.id)), sp); + (privacy, def_static(local_def(item.id), mutbl), sp); } item_fn(_, purity, _, _, _) => { let (name_bindings, new_parent) = @@ -1566,7 +1567,7 @@ impl Resolver { } } foreign_item_const(*) => { - let def = def_const(local_def(foreign_item.id)); + let def = def_static(local_def(foreign_item.id), false); name_bindings.define_value(Public, def, foreign_item.span); visit_foreign_item(foreign_item, (new_parent, visitor)); @@ -1673,7 +1674,7 @@ impl Resolver { let privacy = variant_visibility_to_privacy(visibility, true); child_name_bindings.define_value(privacy, def, dummy_sp()); } - def_fn(*) | def_static_method(*) | def_const(*) => { + def_fn(*) | def_static_method(*) | def_static(*) => { debug!("(building reduced graph for external \ crate) building value %s", final_ident); child_name_bindings.define_value(privacy, def, dummy_sp()); @@ -3686,7 +3687,7 @@ impl Resolver { visitor); } - item_const(*) => { + item_static(*) => { self.with_constant_rib(|| { visit_item(item, ((), visitor)); }); @@ -4344,7 +4345,7 @@ impl Resolver { Some(def @ def_struct(*)) => { self.record_def(pattern.id, def); } - Some(def @ def_const(*)) => { + Some(def @ def_static(*)) => { self.enforce_default_binding_mode( pattern, binding_mode, @@ -4376,7 +4377,7 @@ impl Resolver { Some(def @ def_fn(*)) | Some(def @ def_variant(*)) | Some(def @ def_struct(*)) | - Some(def @ def_const(*)) => { + Some(def @ def_static(*)) => { self.record_def(pattern.id, def); } Some(_) => { @@ -4459,7 +4460,7 @@ impl Resolver { def @ def_variant(*) | def @ def_struct(*) => { return FoundStructOrEnumVariant(def); } - def @ def_const(*) => { + def @ def_static(_, false) => { return FoundConst(def); } _ => { diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs index ab2f0c84d02..71b416ffe85 100644 --- a/src/librustc/middle/trans/_match.rs +++ b/src/librustc/middle/trans/_match.rs @@ -820,7 +820,7 @@ pub fn get_options(bcx: block, m: &[@Match], col: uint) -> ~[Opt] { add_to_set(ccx.tcx, &mut found, lit(UnitLikeStructLit(cur.id))); } - Some(&ast::def_const(const_did)) => { + Some(&ast::def_static(const_did, false)) => { add_to_set(ccx.tcx, &mut found, lit(ConstLit(const_did))); } @@ -836,7 +836,7 @@ pub fn get_options(bcx: block, m: &[@Match], col: uint) -> ~[Opt] { add_to_set(ccx.tcx, &mut found, variant_opt(bcx, cur.id)); } - Some(&ast::def_const(const_did)) => { + Some(&ast::def_static(const_did, false)) => { add_to_set(ccx.tcx, &mut found, lit(ConstLit(const_did))); } @@ -1831,8 +1831,9 @@ pub fn bind_irrefutable_pat(bcx: block, } } } - Some(&ast::def_const(*)) => { - bcx = bind_irrefutable_pat(bcx, pat, val, make_copy, binding_mode); + Some(&ast::def_static(_, false)) => { + bcx = bind_irrefutable_pat(bcx, pat, val, make_copy, + binding_mode); } _ => { // Nothing to do here. diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index ec77fe359b5..0f6c7dbe754 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -2122,14 +2122,19 @@ pub fn trans_item(ccx: @mut CrateContext, item: &ast::item) { trans_enum_def(ccx, enum_definition, item.id, vi, &mut i); } } - ast::item_const(_, expr) => { - consts::trans_const(ccx, expr, item.id); + ast::item_static(_, m, expr) => { + consts::trans_const(ccx, m, item.id); // Do static_assert checking. It can't really be done much earlier because we need to get // the value of the bool out of LLVM for item.attrs.iter().advance |attr| { match attr.node.value.node { ast::meta_word(x) => { if x.slice(0, x.len()) == "static_assert" { + if m == ast::m_mutbl { + ccx.sess.span_fatal(expr.span, + "cannot have static_assert \ + on a mutable static"); + } let v = ccx.const_values.get_copy(&item.id); unsafe { if !(llvm::LLVMConstIntGetZExtValue(v) as bool) { @@ -2398,13 +2403,14 @@ pub fn get_item_val(ccx: @mut CrateContext, id: ast::node_id) -> ValueRef { let my_path = vec::append(/*bad*/copy *pth, [path_name(i.ident)]); match i.node { - ast::item_const(_, expr) => { + ast::item_static(_, m, expr) => { let typ = ty::node_id_to_type(ccx.tcx, i.id); let s = mangle_exported_name(ccx, my_path, typ); // We need the translated value here, because for enums the // LLVM type is not fully determined by the Rust type. let v = consts::const_expr(ccx, expr); ccx.const_values.insert(id, v); + exprt = m == ast::m_mutbl; unsafe { let llty = llvm::LLVMTypeOf(v); let g = str::as_c_str(s, |buf| { diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs index 6120e1e6581..593d0beb88c 100644 --- a/src/librustc/middle/trans/callee.rs +++ b/src/librustc/middle/trans/callee.rs @@ -143,7 +143,7 @@ pub fn trans(bcx: block, expr: @ast::expr) -> Callee { datum_callee(bcx, ref_expr) } ast::def_mod(*) | ast::def_foreign_mod(*) | ast::def_trait(*) | - ast::def_const(*) | ast::def_ty(*) | ast::def_prim_ty(*) | + ast::def_static(*) | ast::def_ty(*) | ast::def_prim_ty(*) | ast::def_use(*) | ast::def_typaram_binder(*) | ast::def_region(*) | ast::def_label(*) | ast::def_ty_param(*) | ast::def_self_ty(*) => { diff --git a/src/librustc/middle/trans/consts.rs b/src/librustc/middle/trans/consts.rs index e40534773c2..98eb858be55 100644 --- a/src/librustc/middle/trans/consts.rs +++ b/src/librustc/middle/trans/consts.rs @@ -164,9 +164,9 @@ pub fn get_const_val(cx: @mut CrateContext, mut def_id: ast::def_id) -> ValueRef } match cx.tcx.items.get_copy(&def_id.node) { ast_map::node_item(@ast::item { - node: ast::item_const(_, subexpr), _ + node: ast::item_static(_, ast::m_imm, _), _ }, _) => { - trans_const(cx, subexpr, def_id.node); + trans_const(cx, ast::m_imm, def_id.node); } _ => cx.tcx.sess.bug("expected a const to be an item") } @@ -538,7 +538,7 @@ fn const_expr_unadjusted(cx: @mut CrateContext, e: @ast::expr) -> ValueRef { base::get_item_val(cx, def_id.node) } } - Some(&ast::def_const(def_id)) => { + Some(&ast::def_static(def_id, false)) => { get_const_val(cx, def_id) } Some(&ast::def_variant(enum_did, variant_did)) => { @@ -587,7 +587,7 @@ fn const_expr_unadjusted(cx: @mut CrateContext, e: @ast::expr) -> ValueRef { } } -pub fn trans_const(ccx: @mut CrateContext, _e: @ast::expr, id: ast::node_id) { +pub fn trans_const(ccx: @mut CrateContext, m: ast::mutability, id: ast::node_id) { unsafe { let _icx = push_ctxt("trans_const"); let g = base::get_item_val(ccx, id); @@ -595,6 +595,8 @@ pub fn trans_const(ccx: @mut CrateContext, _e: @ast::expr, id: ast::node_id) { // constant's initializer to determine its LLVM type. let v = ccx.const_values.get_copy(&id); llvm::LLVMSetInitializer(g, v); - llvm::LLVMSetGlobalConstant(g, True); + if m != ast::m_mutbl { + llvm::LLVMSetGlobalConstant(g, True); + } } } diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index 7d86f743a8e..1aebf73b81a 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -945,7 +945,7 @@ fn trans_lvalue_unadjusted(bcx: block, expr: @ast::expr) -> DatumBlock { let _icx = push_ctxt("trans_def_lvalue"); let ccx = bcx.ccx(); match def { - ast::def_const(did) => { + ast::def_static(did, _) => { let const_ty = expr_ty(bcx, ref_expr); fn get_did(ccx: @mut CrateContext, did: ast::def_id) diff --git a/src/librustc/middle/trans/reachable.rs b/src/librustc/middle/trans/reachable.rs index 6a40c1f75e9..e950c24c49e 100644 --- a/src/librustc/middle/trans/reachable.rs +++ b/src/librustc/middle/trans/reachable.rs @@ -146,7 +146,7 @@ fn traverse_public_item(cx: @mut ctx, item: @item) { visit::mk_vt(@visit::Visitor {visit_ty: traverse_ty, ..*visit::default_visitor()}))) } - item_const(*) | + item_static(*) | item_enum(*) | item_trait(*) => (), item_mac(*) => fail!("item macros unimplemented") } diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 90cd8a8665e..f3c0d4bd8f4 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -3269,7 +3269,7 @@ pub fn expr_kind(tcx: ctxt, // Note: there is actually a good case to be made that // def_args, particularly those of immediate type, ought to // considered rvalues. - ast::def_const(*) | + ast::def_static(*) | ast::def_binding(*) | ast::def_upvar(*) | ast::def_arg(*) | diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index fa7959c7872..1acf806f21e 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -585,7 +585,7 @@ pub fn check_item(ccx: @mut CrateCtxt, it: @ast::item) { let _indenter = indenter(); match it.node { - ast::item_const(_, e) => check_const(ccx, it.span, e, it.id), + ast::item_static(_, _, e) => check_const(ccx, it.span, e, it.id), ast::item_enum(ref enum_definition, _) => { check_enum_variants(ccx, it.span, @@ -3216,7 +3216,7 @@ pub fn ty_param_bounds_and_ty_for_def(fcx: @mut FnCtxt, } ast::def_fn(id, _) | ast::def_static_method(id, _, _) | - ast::def_const(id) | ast::def_variant(_, id) | + ast::def_static(id, _) | ast::def_variant(_, id) | ast::def_struct(id) => { return ty::lookup_item_type(fcx.ccx.tcx, id); } diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index 7f820d11ac6..aef148830a9 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -1060,7 +1060,7 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: @ast::item) } let rp = tcx.region_paramd_items.find(&it.id).map_consume(|x| *x); match it.node { - ast::item_const(t, _) => { + ast::item_static(t, _, _) => { let typ = ccx.to_ty(&empty_rscope, t); let tpt = no_params(typ); tcx.tcache.insert(local_def(it.id), tpt); diff --git a/src/librustdoc/extract.rs b/src/librustdoc/extract.rs index b6131dce9c8..f12f612b036 100644 --- a/src/librustdoc/extract.rs +++ b/src/librustdoc/extract.rs @@ -102,7 +102,7 @@ fn moddoc_from_mod( fndoc_from_fn(ItemDoc) )) } - ast::item_const(_, _) => { + ast::item_static(*) => { Some(doc::ConstTag( constdoc_from_const(ItemDoc) )) diff --git a/src/librustdoc/tystr_pass.rs b/src/librustdoc/tystr_pass.rs index e3abe6e926a..459daaa468f 100644 --- a/src/librustdoc/tystr_pass.rs +++ b/src/librustdoc/tystr_pass.rs @@ -96,7 +96,7 @@ fn fold_const( do astsrv::exec(srv) |ctxt| { match ctxt.ast_map.get_copy(&doc.id()) { ast_map::node_item(@ast::item { - node: ast::item_const(ty, _), _ + node: ast::item_static(ty, _, _), _ }, _) => { pprust::ty_to_str(ty, extract::interner()) } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 2e3d557daa9..012a1e76228 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -190,7 +190,7 @@ pub enum def { def_self_ty(/* trait id */ node_id), def_mod(def_id), def_foreign_mod(def_id), - def_const(def_id), + def_static(def_id, bool /* is_mutbl */), def_arg(node_id, bool /* is_mutbl */), def_local(node_id, bool /* is_mutbl */), def_variant(def_id /* enum */, def_id /* variant */), @@ -1095,7 +1095,7 @@ pub struct item { #[deriving(Eq, Encodable, Decodable)] pub enum item_ { - item_const(@Ty, @expr), + item_static(@Ty, mutability, @expr), item_fn(fn_decl, purity, AbiSet, Generics, blk), item_mod(_mod), item_foreign_mod(foreign_mod), diff --git a/src/libsyntax/ast_map.rs b/src/libsyntax/ast_map.rs index a0e1ec69350..421c4c566b5 100644 --- a/src/libsyntax/ast_map.rs +++ b/src/libsyntax/ast_map.rs @@ -339,7 +339,7 @@ pub fn node_id_to_str(map: map, id: node_id, itr: @ident_interner) -> ~str { Some(&node_item(item, path)) => { let path_str = path_ident_to_str(path, item.ident, itr); let item_str = match item.node { - item_const(*) => ~"const", + item_static(*) => ~"static", item_fn(*) => ~"fn", item_mod(*) => ~"mod", item_foreign_mod(*) => ~"foreign mod", diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 24cf5662a36..227d700452b 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -59,7 +59,7 @@ pub fn variant_def_ids(d: def) -> Option<(def_id, def_id)> { pub fn def_id_of_def(d: def) -> def_id { match d { def_fn(id, _) | def_static_method(id, _, _) | def_mod(id) | - def_foreign_mod(id) | def_const(id) | + def_foreign_mod(id) | def_static(id, _) | def_variant(_, id) | def_ty(id) | def_ty_param(id, _) | def_use(id) | def_struct(id) | def_trait(id) => { id diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 4bd2c0a3de1..8a22dbe9178 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -270,7 +270,7 @@ fn noop_fold_struct_field(sf: @struct_field, fld: @ast_fold) pub fn noop_fold_item_underscore(i: &item_, fld: @ast_fold) -> item_ { match *i { - item_const(t, e) => item_const(fld.fold_ty(t), fld.fold_expr(e)), + item_static(t, m, e) => item_static(fld.fold_ty(t), m, fld.fold_expr(e)), item_fn(ref decl, purity, abi, ref generics, ref body) => { item_fn( fold_fn_decl(decl, fld), diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index f2443f9e533..a726b3b27d2 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -34,7 +34,7 @@ use ast::{expr_vstore_slice, expr_vstore_box}; use ast::{expr_vstore_mut_slice, expr_while, extern_fn, field, fn_decl}; use ast::{expr_vstore_uniq, Onceness, Once, Many}; use ast::{foreign_item, foreign_item_const, foreign_item_fn, foreign_mod}; -use ast::{ident, impure_fn, inherited, item, item_, item_const}; +use ast::{ident, impure_fn, inherited, item, item_, item_static}; use ast::{item_enum, item_fn, item_foreign_mod, item_impl}; use ast::{item_mac, item_mod, item_struct, item_trait, item_ty, lit, lit_}; use ast::{lit_bool, lit_float, lit_float_unsuffixed, lit_int}; @@ -3556,13 +3556,14 @@ impl Parser { } fn parse_item_const(&self) -> item_info { + let m = if self.eat_keyword(keywords::Mut) {m_mutbl} else {m_imm}; let id = self.parse_ident(); self.expect(&token::COLON); let ty = self.parse_ty(false); self.expect(&token::EQ); let e = self.parse_expr(); self.expect(&token::SEMI); - (id, item_const(ty, e), None) + (id, item_static(ty, m, e), None) } // parse a mod { ...} item diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index fa22b7ceb71..c21c0a0afee 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -477,8 +477,11 @@ pub fn print_item(s: @ps, item: @ast::item) { let ann_node = node_item(s, item); (s.ann.pre)(ann_node); match item.node { - ast::item_const(ty, expr) => { + ast::item_static(ty, m, expr) => { head(s, visibility_qualified(item.vis, "static")); + if m == ast::m_mutbl { + word_space(s, "mut"); + } print_ident(s, item.ident); word_space(s, ":"); print_type(s, ty); diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 5aa38c0348c..fd9350e0005 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -148,7 +148,7 @@ fn visit_trait_ref(tref: @ast::trait_ref, (e, v): (E, vt)) { pub fn visit_item(i: @item, (e, v): (E, vt)) { match i.node { - item_const(t, ex) => { + item_static(t, _, ex) => { (v.visit_ty)(t, (copy e, v)); (v.visit_expr)(ex, (copy e, v)); } diff --git a/src/test/auxiliary/static_mut_xc.rs b/src/test/auxiliary/static_mut_xc.rs new file mode 100644 index 00000000000..8dc45c681bf --- /dev/null +++ b/src/test/auxiliary/static_mut_xc.rs @@ -0,0 +1 @@ +pub static mut a: int = 3; diff --git a/src/test/compile-fail/static-mut-bad-types.rs b/src/test/compile-fail/static-mut-bad-types.rs new file mode 100644 index 00000000000..7aed3ce30bc --- /dev/null +++ b/src/test/compile-fail/static-mut-bad-types.rs @@ -0,0 +1,17 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +static mut a: int = 3; + +fn main() { + unsafe { + a = true; //~ ERROR: mismatched types + } +} diff --git a/src/test/compile-fail/static-mut-not-constant.rs b/src/test/compile-fail/static-mut-not-constant.rs new file mode 100644 index 00000000000..61d3ed7fd18 --- /dev/null +++ b/src/test/compile-fail/static-mut-not-constant.rs @@ -0,0 +1,13 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +static mut a: ~int = ~3; //~ ERROR: disallowed operator in constant + +fn main() {} diff --git a/src/test/compile-fail/static-mut-not-pat.rs b/src/test/compile-fail/static-mut-not-pat.rs new file mode 100644 index 00000000000..997003a28d4 --- /dev/null +++ b/src/test/compile-fail/static-mut-not-pat.rs @@ -0,0 +1,26 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Constants (static variables) can be used to match in patterns, but mutable +// statics cannot. This ensures that there's some form of error if this is +// attempted. + +static mut a: int = 3; + +fn main() { + // If they can't be matched against, then it's possible to capture the same + // name as a variable, hence this should be an unreachable pattern situation + // instead of spitting out a custom error about some identifier collisions + // (we should allow shadowing) + match 4 { + a => {} + _ => {} //~ ERROR: unreachable pattern + } +} diff --git a/src/test/compile-fail/static-mut-requires-unsafe.rs b/src/test/compile-fail/static-mut-requires-unsafe.rs new file mode 100644 index 00000000000..7337920cce6 --- /dev/null +++ b/src/test/compile-fail/static-mut-requires-unsafe.rs @@ -0,0 +1,17 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +static mut a: int = 3; + +fn main() { + a += 3; //~ ERROR: requires unsafe + a = 4; //~ ERROR: requires unsafe + let _b = a; //~ ERROR: requires unsafe +} diff --git a/src/test/run-pass/static-mut-xc.rs b/src/test/run-pass/static-mut-xc.rs new file mode 100644 index 00000000000..72f44fcd501 --- /dev/null +++ b/src/test/run-pass/static-mut-xc.rs @@ -0,0 +1,46 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Constants (static variables) can be used to match in patterns, but mutable +// statics cannot. This ensures that there's some form of error if this is +// attempted. + +// xfail-fast +// aux-build:static_mut_xc.rs + +extern mod static_mut_xc; + +unsafe fn static_bound(_: &'static int) {} + +fn static_bound_set(a: &'static mut int) { + *a = 3; +} + +unsafe fn run() { + assert!(static_mut_xc::a == 3); + static_mut_xc::a = 4; + assert!(static_mut_xc::a == 4); + static_mut_xc::a += 1; + assert!(static_mut_xc::a == 5); + static_mut_xc::a *= 3; + assert!(static_mut_xc::a == 15); + static_mut_xc::a = -3; + assert!(static_mut_xc::a == -3); + static_bound(&static_mut_xc::a); + static_bound_set(&mut static_mut_xc::a); +} + +fn main() { + unsafe { run() } +} + +pub mod inner { + pub static mut a: int = 4; +} -- cgit 1.4.1-3-g733a5 From 8fdc8f392c3f5d1bdf601756bfe442b7698e6315 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 21 Jun 2013 22:46:27 -0700 Subject: Support foreign 'static mut' variables as well --- src/librustc/metadata/encoder.rs | 8 +++- src/librustc/middle/lint.rs | 48 +++++++++++----------- src/librustc/middle/resolve.rs | 6 +-- src/librustc/middle/trans/base.rs | 2 +- src/librustc/middle/trans/foreign.rs | 2 +- src/librustc/middle/typeck/collect.rs | 2 +- src/librustdoc/extract.rs | 2 +- src/libsyntax/ast.rs | 2 +- src/libsyntax/fold.rs | 4 +- src/libsyntax/parse/parser.rs | 5 ++- src/libsyntax/print/pprust.rs | 5 ++- src/libsyntax/visit.rs | 2 +- src/rt/rust_builtin.cpp | 10 +++++ src/rt/rustrt.def.in | 4 +- .../static-mut-foreign-requires-unsafe.rs | 21 ++++++++++ src/test/run-pass/static-mut-foreign.rs | 46 +++++++++++++++++++++ 16 files changed, 129 insertions(+), 40 deletions(-) create mode 100644 src/test/compile-fail/static-mut-foreign-requires-unsafe.rs create mode 100644 src/test/run-pass/static-mut-foreign.rs (limited to 'src/libsyntax') diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 96cf7284169..7d18bdb77ef 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -1111,9 +1111,13 @@ fn encode_info_for_foreign_item(ecx: &EncodeContext, } encode_path(ecx, ebml_w, path, ast_map::path_name(nitem.ident)); } - foreign_item_const(*) => { + foreign_item_static(_, mutbl) => { encode_def_id(ebml_w, local_def(nitem.id)); - encode_family(ebml_w, 'c'); + if mutbl { + encode_family(ebml_w, 'b'); + } else { + encode_family(ebml_w, 'c'); + } encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, nitem.id)); encode_symbol(ecx, ebml_w, nitem.id); encode_path(ecx, ebml_w, path, ast_map::path_name(nitem.ident)); diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs index 821aed731c2..17ff5930078 100644 --- a/src/librustc/middle/lint.rs +++ b/src/librustc/middle/lint.rs @@ -709,28 +709,31 @@ fn check_item_default_methods(cx: &Context, item: @ast::item) { } fn check_item_ctypes(cx: &Context, it: @ast::item) { + fn check_ty(cx: &Context, ty: @ast::Ty) { + match ty.node { + ast::ty_path(_, _, id) => { + match cx.tcx.def_map.get_copy(&id) { + ast::def_prim_ty(ast::ty_int(ast::ty_i)) => { + cx.span_lint(ctypes, ty.span, + "found rust type `int` in foreign module, while \ + libc::c_int or libc::c_long should be used"); + } + ast::def_prim_ty(ast::ty_uint(ast::ty_u)) => { + cx.span_lint(ctypes, ty.span, + "found rust type `uint` in foreign module, while \ + libc::c_uint or libc::c_ulong should be used"); + } + _ => () + } + } + _ => () + } + } fn check_foreign_fn(cx: &Context, decl: &ast::fn_decl) { let tys = vec::map(decl.inputs, |a| a.ty ); for vec::each(vec::append_one(tys, decl.output)) |ty| { - match ty.node { - ast::ty_path(_, _, id) => { - match cx.tcx.def_map.get_copy(&id) { - ast::def_prim_ty(ast::ty_int(ast::ty_i)) => { - cx.span_lint(ctypes, ty.span, - "found rust type `int` in foreign module, while \ - libc::c_int or libc::c_long should be used"); - } - ast::def_prim_ty(ast::ty_uint(ast::ty_u)) => { - cx.span_lint(ctypes, ty.span, - "found rust type `uint` in foreign module, while \ - libc::c_uint or libc::c_ulong should be used"); - } - _ => () - } - } - _ => () - } + check_ty(cx, *ty); } } @@ -738,11 +741,10 @@ fn check_item_ctypes(cx: &Context, it: @ast::item) { ast::item_foreign_mod(ref nmod) if !nmod.abis.is_intrinsic() => { for nmod.items.iter().advance |ni| { match ni.node { - ast::foreign_item_fn(ref decl, _, _) => { - check_foreign_fn(cx, decl); - } - // FIXME #4622: Not implemented. - ast::foreign_item_const(*) => {} + ast::foreign_item_fn(ref decl, _, _) => { + check_foreign_fn(cx, decl); + } + ast::foreign_item_static(t, _) => { check_ty(cx, t); } } } } diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index 7f9086be81d..ed385ae5421 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -1566,8 +1566,8 @@ impl Resolver { visit_foreign_item(foreign_item, (new_parent, visitor)); } } - foreign_item_const(*) => { - let def = def_static(local_def(foreign_item.id), false); + foreign_item_static(_, m) => { + let def = def_static(local_def(foreign_item.id), m); name_bindings.define_value(Public, def, foreign_item.span); visit_foreign_item(foreign_item, (new_parent, visitor)); @@ -3665,7 +3665,7 @@ impl Resolver { || visit_foreign_item(*foreign_item, ((), visitor))); } - foreign_item_const(_) => { + foreign_item_static(*) => { visit_foreign_item(*foreign_item, ((), visitor)); } diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 0f6c7dbe754..0e322c187af 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -2463,7 +2463,7 @@ pub fn get_item_val(ccx: @mut CrateContext, id: ast::node_id) -> ValueRef { ni.id, ni.attrs) } - ast::foreign_item_const(*) => { + ast::foreign_item_static(*) => { let typ = ty::node_id_to_type(ccx.tcx, ni.id); let ident = token::ident_to_str(&ni.ident); let g = do str::as_c_str(ident) |buf| { diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs index 10e63e6af77..54bfc25244f 100644 --- a/src/librustc/middle/trans/foreign.rs +++ b/src/librustc/middle/trans/foreign.rs @@ -332,7 +332,7 @@ pub fn trans_foreign_mod(ccx: @mut CrateContext, } } } - ast::foreign_item_const(*) => { + ast::foreign_item_static(*) => { let ident = token::ident_to_str(&foreign_item.ident); ccx.item_symbols.insert(foreign_item.id, /* bad */ident.to_owned()); } diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index aef148830a9..33e483e552a 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -1153,7 +1153,7 @@ pub fn ty_of_foreign_item(ccx: &CrateCtxt, generics, abis) } - ast::foreign_item_const(t) => { + ast::foreign_item_static(t, _) => { ty::ty_param_bounds_and_ty { generics: ty::Generics { type_param_defs: @~[], diff --git a/src/librustdoc/extract.rs b/src/librustdoc/extract.rs index f12f612b036..b7b2b70769b 100644 --- a/src/librustdoc/extract.rs +++ b/src/librustdoc/extract.rs @@ -150,7 +150,7 @@ fn nmoddoc_from_mod( ast::foreign_item_fn(*) => { fns.push(fndoc_from_fn(ItemDoc)); } - ast::foreign_item_const(*) => {} // XXX: Not implemented. + ast::foreign_item_static(*) => {} // XXX: Not implemented. } } doc::NmodDoc { diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 012a1e76228..c7f3b41475f 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1124,7 +1124,7 @@ pub struct foreign_item { #[deriving(Eq, Encodable, Decodable)] pub enum foreign_item_ { foreign_item_fn(fn_decl, purity, Generics), - foreign_item_const(@Ty) + foreign_item_static(@Ty, /* is_mutbl */ bool), } // The data we save and restore about an inlined item or method. This is not diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 8a22dbe9178..25839fb4633 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -236,8 +236,8 @@ fn noop_fold_foreign_item(ni: @foreign_item, fld: @ast_fold) purity, fold_generics(generics, fld)) } - foreign_item_const(t) => { - foreign_item_const(fld.fold_ty(t)) + foreign_item_static(t, m) => { + foreign_item_static(fld.fold_ty(t), m) } }, id: fld.new_id(ni.id), diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index a726b3b27d2..cc4a1f45722 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -33,7 +33,7 @@ use ast::{expr_vec, expr_vstore, expr_vstore_mut_box}; use ast::{expr_vstore_slice, expr_vstore_box}; use ast::{expr_vstore_mut_slice, expr_while, extern_fn, field, fn_decl}; use ast::{expr_vstore_uniq, Onceness, Once, Many}; -use ast::{foreign_item, foreign_item_const, foreign_item_fn, foreign_mod}; +use ast::{foreign_item, foreign_item_static, foreign_item_fn, foreign_mod}; use ast::{ident, impure_fn, inherited, item, item_, item_static}; use ast::{item_enum, item_fn, item_foreign_mod, item_impl}; use ast::{item_mac, item_mod, item_struct, item_trait, item_ty, lit, lit_}; @@ -3684,6 +3684,7 @@ impl Parser { } else { self.expect_keyword(keywords::Static); } + let mutbl = self.eat_keyword(keywords::Mut); let ident = self.parse_ident(); self.expect(&token::COLON); @@ -3692,7 +3693,7 @@ impl Parser { self.expect(&token::SEMI); @ast::foreign_item { ident: ident, attrs: attrs, - node: foreign_item_const(ty), + node: foreign_item_static(ty, mutbl), id: self.get_id(), span: mk_sp(lo, hi), vis: vis } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index c21c0a0afee..1a3155337a5 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -458,8 +458,11 @@ pub fn print_foreign_item(s: @ps, item: @ast::foreign_item) { word(s.s, ";"); end(s); // end the outer fn box } - ast::foreign_item_const(t) => { + ast::foreign_item_static(t, m) => { head(s, "static"); + if m { + word_space(s, "mut"); + } print_ident(s, item.ident); word_space(s, ":"); print_type(s, t); diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index fd9350e0005..d7914832835 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -326,7 +326,7 @@ pub fn visit_foreign_item(ni: @foreign_item, (e, v): (E, vt)) { visit_fn_decl(fd, (copy e, v)); (v.visit_generics)(generics, (e, v)); } - foreign_item_const(t) => { + foreign_item_static(t, _) => { (v.visit_ty)(t, (e, v)); } } diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp index e476fa0ad5e..6ae5e978106 100644 --- a/src/rt/rust_builtin.cpp +++ b/src/rt/rust_builtin.cpp @@ -154,6 +154,16 @@ debug_abi_2(floats f) { return ff; } +extern "C" int +debug_static_mut; + +int debug_static_mut = 3; + +extern "C" void +debug_static_mut_check_four() { + assert(debug_static_mut == 4); +} + /* Debug builtins for std::dbg. */ static void diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in index ba7ada04a27..505de6e20b7 100644 --- a/src/rt/rustrt.def.in +++ b/src/rt/rustrt.def.in @@ -7,6 +7,8 @@ debug_tydesc debug_get_stk_seg debug_abi_1 debug_abi_2 +debug_static_mut +debug_static_mut_check_four get_task_id get_time rust_tzset @@ -239,4 +241,4 @@ rust_valgrind_stack_deregister rust_take_env_lock rust_drop_env_lock rust_update_log_settings -rust_running_on_valgrind \ No newline at end of file +rust_running_on_valgrind diff --git a/src/test/compile-fail/static-mut-foreign-requires-unsafe.rs b/src/test/compile-fail/static-mut-foreign-requires-unsafe.rs new file mode 100644 index 00000000000..7b371cf708d --- /dev/null +++ b/src/test/compile-fail/static-mut-foreign-requires-unsafe.rs @@ -0,0 +1,21 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::libc; + +extern { + static mut a: libc::c_int; +} + +fn main() { + a += 3; //~ ERROR: requires unsafe + a = 4; //~ ERROR: requires unsafe + let _b = a; //~ ERROR: requires unsafe +} diff --git a/src/test/run-pass/static-mut-foreign.rs b/src/test/run-pass/static-mut-foreign.rs new file mode 100644 index 00000000000..66d34c7e454 --- /dev/null +++ b/src/test/run-pass/static-mut-foreign.rs @@ -0,0 +1,46 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Constants (static variables) can be used to match in patterns, but mutable +// statics cannot. This ensures that there's some form of error if this is +// attempted. + +use std::libc; + +#[nolink] +extern { + static mut debug_static_mut: libc::c_int; + pub fn debug_static_mut_check_four(); +} + +unsafe fn static_bound(_: &'static libc::c_int) {} + +fn static_bound_set(a: &'static mut libc::c_int) { + *a = 3; +} + +unsafe fn run() { + assert!(debug_static_mut == 3); + debug_static_mut = 4; + assert!(debug_static_mut == 4); + debug_static_mut_check_four(); + debug_static_mut += 1; + assert!(debug_static_mut == 5); + debug_static_mut *= 3; + assert!(debug_static_mut == 15); + debug_static_mut = -3; + assert!(debug_static_mut == -3); + static_bound(&debug_static_mut); + static_bound_set(&mut debug_static_mut); +} + +fn main() { + unsafe { run() } +} -- cgit 1.4.1-3-g733a5 From 6ad31ffb53f9620f9063cb441de9c7338dfbb4de Mon Sep 17 00:00:00 2001 From: James Miller Date: Tue, 25 Jun 2013 17:13:22 +1200 Subject: Warning police --- src/librustc/metadata/decoder.rs | 1 - src/librustc/middle/ty.rs | 2 +- src/librustc/middle/typeck/check/mod.rs | 2 +- src/librustc/middle/typeck/coherence.rs | 4 +--- src/librustc/util/ppaux.rs | 1 - src/libstd/to_str.rs | 2 -- src/libsyntax/parse/parser.rs | 2 +- 7 files changed, 4 insertions(+), 10 deletions(-) (limited to 'src/libsyntax') diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 9ace8677dab..db44ac5e442 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -35,7 +35,6 @@ use extra::ebml; use extra::serialize::Decodable; use syntax::ast_map; use syntax::attr; -use syntax::diagnostic::span_handler; use syntax::parse::token::{ident_interner, special_idents}; use syntax::print::pprust; use syntax::{ast, ast_util}; diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 90cd8a8665e..632874025e7 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -21,7 +21,7 @@ use middle::ty; use middle::subst::Subst; use middle::typeck; use middle; -use util::ppaux::{note_and_explain_region, bound_region_to_str, bound_region_ptr_to_str}; +use util::ppaux::{note_and_explain_region, bound_region_ptr_to_str}; use util::ppaux::{trait_store_to_str, ty_to_str, vstore_to_str}; use util::ppaux::{Repr, UserString}; use util::common::{indenter}; diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index fa7959c7872..76b7e651ff1 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -107,7 +107,7 @@ use middle::typeck::{isr_alist, lookup_def_ccx}; use middle::typeck::no_params; use middle::typeck::{require_same_types, method_map, vtable_map}; use util::common::{block_query, indenter, loop_query}; -use util::ppaux::{bound_region_to_str,bound_region_ptr_to_str}; +use util::ppaux::{bound_region_ptr_to_str}; use util::ppaux; diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs index 7ad27077cd8..ae62e768ea2 100644 --- a/src/librustc/middle/typeck/coherence.rs +++ b/src/librustc/middle/typeck/coherence.rs @@ -16,10 +16,8 @@ use core::prelude::*; -use driver; use metadata::csearch::{each_path, get_impl_trait}; use metadata::csearch::{get_impls_for_mod}; -use metadata::csearch; use metadata::cstore::{CStore, iter_crate_data}; use metadata::decoder::{dl_def, dl_field, dl_impl}; use middle::resolve::{Impl, MethodInfo}; @@ -39,7 +37,7 @@ use middle::typeck::infer::combine::Combine; use middle::typeck::infer::InferCtxt; use middle::typeck::infer::{new_infer_ctxt, resolve_ivar}; use middle::typeck::infer::{resolve_nested_tvar, resolve_type}; -use syntax::ast::{crate, def_id, def_mod, def_struct, def_trait, def_ty}; +use syntax::ast::{crate, def_id, def_mod, def_struct, def_ty}; use syntax::ast::{item, item_enum, item_impl, item_mod, item_struct}; use syntax::ast::{local_crate, method, trait_ref, ty_path}; use syntax::ast; diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index e25267f4441..3194df269c0 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -32,7 +32,6 @@ use syntax::parse::token; use syntax::print::pprust; use syntax::{ast, ast_util}; -use core::str; use core::vec; /// Produces a string suitable for debugging output. diff --git a/src/libstd/to_str.rs b/src/libstd/to_str.rs index 9f812288621..2e5c3c01adf 100644 --- a/src/libstd/to_str.rs +++ b/src/libstd/to_str.rs @@ -18,11 +18,9 @@ use str::OwnedStr; use hashmap::HashMap; use hashmap::HashSet; use iterator::IteratorUtil; -use container::Map; use hash::Hash; use cmp::Eq; use vec::ImmutableVector; -use iterator::IteratorUtil; /// A generic trait for converting a value to a string pub trait ToStr { diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index f2443f9e533..c9ef1a7a33c 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -60,7 +60,7 @@ use ast::{view_item_, view_item_extern_mod, view_item_use}; use ast::{view_path, view_path_glob, view_path_list, view_path_simple}; use ast::visibility; use ast; -use ast_util::{as_prec, ident_to_path, operator_prec}; +use ast_util::{as_prec, operator_prec}; use ast_util; use codemap::{span, BytePos, spanned, mk_sp}; use codemap; -- cgit 1.4.1-3-g733a5 From 42b44b21b11ded0a7dbbe196b1c9d338ef33b614 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 10 Jun 2013 13:00:38 -0700 Subject: Rename all files with the 'rc' extension --- Makefile.in | 16 +- mk/tools.mk | 14 +- src/compiletest/compiletest.rc | 267 ----------------- src/compiletest/compiletest.rs | 267 +++++++++++++++++ src/libextra/extra.rs | 155 ++++++++++ src/libextra/std.rc | 155 ---------- src/librust/rust.rc | 255 ---------------- src/librust/rust.rs | 255 ++++++++++++++++ src/librustc/rustc.rc | 369 ----------------------- src/librustc/rustc.rs | 369 +++++++++++++++++++++++ src/librustdoc/rustdoc.rc | 162 ---------- src/librustdoc/rustdoc.rs | 162 ++++++++++ src/librusti/rusti.rc | 665 ----------------------------------------- src/librusti/rusti.rs | 665 +++++++++++++++++++++++++++++++++++++++++ src/librustpkg/rustpkg.rc | 474 ----------------------------- src/librustpkg/rustpkg.rs | 474 +++++++++++++++++++++++++++++ src/libstd/core.rc | 230 -------------- src/libstd/std.rs | 230 ++++++++++++++ src/libsyntax/syntax.rc | 99 ------ src/libsyntax/syntax.rs | 99 ++++++ 20 files changed, 2691 insertions(+), 2691 deletions(-) delete mode 100644 src/compiletest/compiletest.rc create mode 100644 src/compiletest/compiletest.rs create mode 100644 src/libextra/extra.rs delete mode 100644 src/libextra/std.rc delete mode 100644 src/librust/rust.rc create mode 100644 src/librust/rust.rs delete mode 100644 src/librustc/rustc.rc create mode 100644 src/librustc/rustc.rs delete mode 100644 src/librustdoc/rustdoc.rc create mode 100644 src/librustdoc/rustdoc.rs delete mode 100644 src/librusti/rusti.rc create mode 100644 src/librusti/rusti.rs delete mode 100644 src/librustpkg/rustpkg.rc create mode 100644 src/librustpkg/rustpkg.rs delete mode 100644 src/libstd/core.rc create mode 100644 src/libstd/std.rs delete mode 100644 src/libsyntax/syntax.rc create mode 100644 src/libsyntax/syntax.rs (limited to 'src/libsyntax') diff --git a/Makefile.in b/Makefile.in index baae56c4f40..fa6c7806581 100644 --- a/Makefile.in +++ b/Makefile.in @@ -239,29 +239,29 @@ $(foreach target,$(CFG_TARGET_TRIPLES),\ # Standard library variables ###################################################################### -STDLIB_CRATE := $(S)src/libstd/core.rc +STDLIB_CRATE := $(S)src/libstd/std.rs STDLIB_INPUTS := $(wildcard $(addprefix $(S)src/libstd/, \ - core.rc *.rs */*.rs */*/*rs */*/*/*rs)) + *.rs */*.rs */*/*rs */*/*/*rs)) ###################################################################### # Extra library variables ###################################################################### -EXTRALIB_CRATE := $(S)src/libextra/std.rc +EXTRALIB_CRATE := $(S)src/libextra/extra.rs EXTRALIB_INPUTS := $(wildcard $(addprefix $(S)src/libextra/, \ - std.rc *.rs */*.rs)) + *.rs */*.rs)) ###################################################################### # rustc crate variables ###################################################################### -COMPILER_CRATE := $(S)src/librustc/rustc.rc +COMPILER_CRATE := $(S)src/librustc/rustc.rs COMPILER_INPUTS := $(wildcard $(addprefix $(S)src/librustc/, \ - rustc.rc *.rs */*.rs */*/*.rs */*/*/*.rs)) + *.rs */*.rs */*/*.rs */*/*/*.rs)) -LIBSYNTAX_CRATE := $(S)src/libsyntax/syntax.rc +LIBSYNTAX_CRATE := $(S)src/libsyntax/syntax.rs LIBSYNTAX_INPUTS := $(wildcard $(addprefix $(S)src/libsyntax/, \ - syntax.rc *.rs */*.rs */*/*.rs)) + *.rs */*.rs */*/*.rs)) DRIVER_CRATE := $(S)src/driver/driver.rs diff --git a/mk/tools.mk b/mk/tools.mk index 8319d8d4e48..7b50441b3c7 100644 --- a/mk/tools.mk +++ b/mk/tools.mk @@ -12,23 +12,23 @@ # and host architectures # The test runner that runs the cfail/rfail/rpass and bxench tests -COMPILETEST_CRATE := $(S)src/compiletest/compiletest.rc -COMPILETEST_INPUTS := $(wildcard $(S)src/compiletest/*rs) +COMPILETEST_CRATE := $(S)src/compiletest/compiletest.rs +COMPILETEST_INPUTS := $(wildcard $(S)src/compiletest/*.rs) # Rustpkg, the package manager and build system -RUSTPKG_LIB := $(S)src/librustpkg/rustpkg.rc -RUSTPKG_INPUTS := $(wildcard $(S)src/librustpkg/*rs) +RUSTPKG_LIB := $(S)src/librustpkg/rustpkg.rs +RUSTPKG_INPUTS := $(wildcard $(S)src/librustpkg/*.rs) # Rustdoc, the documentation tool -RUSTDOC_LIB := $(S)src/librustdoc/rustdoc.rc +RUSTDOC_LIB := $(S)src/librustdoc/rustdoc.rs RUSTDOC_INPUTS := $(wildcard $(S)src/librustdoc/*.rs) # Rusti, the JIT REPL -RUSTI_LIB := $(S)src/librusti/rusti.rc +RUSTI_LIB := $(S)src/librusti/rusti.rs RUSTI_INPUTS := $(wildcard $(S)src/librusti/*.rs) # Rust, the convenience tool -RUST_LIB := $(S)src/librust/rust.rc +RUST_LIB := $(S)src/librust/rust.rs RUST_INPUTS := $(wildcard $(S)src/librust/*.rs) # FIXME: These are only built for the host arch. Eventually we'll diff --git a/src/compiletest/compiletest.rc b/src/compiletest/compiletest.rc deleted file mode 100644 index e8876c4851b..00000000000 --- a/src/compiletest/compiletest.rc +++ /dev/null @@ -1,267 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[crate_type = "bin"]; - -#[allow(non_camel_case_types)]; - -#[no_core]; // XXX: Remove after snapshot -#[no_std]; - -extern mod core(name = "std", vers = "0.7-pre"); -extern mod extra(name = "extra", vers = "0.7-pre"); - -use core::prelude::*; -use core::*; - -use extra::getopts; -use extra::test; - -use core::result::{Ok, Err}; - -use common::config; -use common::mode_run_pass; -use common::mode_run_fail; -use common::mode_compile_fail; -use common::mode_pretty; -use common::mode_debug_info; -use common::mode; -use util::logv; - -pub mod procsrv; -pub mod util; -pub mod header; -pub mod runtest; -pub mod common; -pub mod errors; - -mod std { - pub use core::cmp; - pub use core::str; - pub use core::sys; - pub use core::unstable; -} - -pub fn main() { - let args = os::args(); - let config = parse_config(args); - log_config(&config); - run_tests(&config); -} - -pub fn parse_config(args: ~[~str]) -> config { - let opts = - ~[getopts::reqopt("compile-lib-path"), - getopts::reqopt("run-lib-path"), - getopts::reqopt("rustc-path"), getopts::reqopt("src-base"), - getopts::reqopt("build-base"), getopts::reqopt("aux-base"), - getopts::reqopt("stage-id"), - getopts::reqopt("mode"), getopts::optflag("ignored"), - getopts::optopt("runtool"), getopts::optopt("rustcflags"), - getopts::optflag("verbose"), - getopts::optopt("logfile"), - getopts::optflag("jit"), - getopts::optflag("newrt"), - getopts::optopt("target"), - getopts::optopt("adb-path"), - getopts::optopt("adb-test-dir") - ]; - - assert!(!args.is_empty()); - let args_ = vec::tail(args); - let matches = - &match getopts::getopts(args_, opts) { - Ok(m) => m, - Err(f) => fail!(getopts::fail_str(f)) - }; - - fn opt_path(m: &getopts::Matches, nm: &str) -> Path { - Path(getopts::opt_str(m, nm)) - } - - config { - compile_lib_path: getopts::opt_str(matches, "compile-lib-path"), - run_lib_path: getopts::opt_str(matches, "run-lib-path"), - rustc_path: opt_path(matches, "rustc-path"), - src_base: opt_path(matches, "src-base"), - build_base: opt_path(matches, "build-base"), - aux_base: opt_path(matches, "aux-base"), - stage_id: getopts::opt_str(matches, "stage-id"), - mode: str_mode(getopts::opt_str(matches, "mode")), - run_ignored: getopts::opt_present(matches, "ignored"), - filter: - if !matches.free.is_empty() { - option::Some(copy matches.free[0]) - } else { option::None }, - logfile: getopts::opt_maybe_str(matches, "logfile").map(|s| Path(*s)), - runtool: getopts::opt_maybe_str(matches, "runtool"), - rustcflags: getopts::opt_maybe_str(matches, "rustcflags"), - jit: getopts::opt_present(matches, "jit"), - newrt: getopts::opt_present(matches, "newrt"), - target: opt_str2(getopts::opt_maybe_str(matches, "target")).to_str(), - adb_path: opt_str2(getopts::opt_maybe_str(matches, "adb-path")).to_str(), - adb_test_dir: - opt_str2(getopts::opt_maybe_str(matches, "adb-test-dir")).to_str(), - adb_device_status: - if (opt_str2(getopts::opt_maybe_str(matches, "target")) == - ~"arm-linux-androideabi") { - if (opt_str2(getopts::opt_maybe_str(matches, "adb-test-dir")) != - ~"(none)" && - opt_str2(getopts::opt_maybe_str(matches, "adb-test-dir")) != - ~"") { true } - else { false } - } else { false }, - verbose: getopts::opt_present(matches, "verbose") - } -} - -pub fn log_config(config: &config) { - let c = config; - logv(c, fmt!("configuration:")); - logv(c, fmt!("compile_lib_path: %s", config.compile_lib_path)); - logv(c, fmt!("run_lib_path: %s", config.run_lib_path)); - logv(c, fmt!("rustc_path: %s", config.rustc_path.to_str())); - logv(c, fmt!("src_base: %s", config.src_base.to_str())); - logv(c, fmt!("build_base: %s", config.build_base.to_str())); - logv(c, fmt!("stage_id: %s", config.stage_id)); - logv(c, fmt!("mode: %s", mode_str(config.mode))); - logv(c, fmt!("run_ignored: %b", config.run_ignored)); - logv(c, fmt!("filter: %s", opt_str(&config.filter))); - logv(c, fmt!("runtool: %s", opt_str(&config.runtool))); - logv(c, fmt!("rustcflags: %s", opt_str(&config.rustcflags))); - logv(c, fmt!("jit: %b", config.jit)); - logv(c, fmt!("newrt: %b", config.newrt)); - logv(c, fmt!("target: %s", config.target)); - logv(c, fmt!("adb_path: %s", config.adb_path)); - logv(c, fmt!("adb_test_dir: %s", config.adb_test_dir)); - logv(c, fmt!("adb_device_status: %b", config.adb_device_status)); - logv(c, fmt!("verbose: %b", config.verbose)); - logv(c, fmt!("\n")); -} - -pub fn opt_str<'a>(maybestr: &'a Option<~str>) -> &'a str { - match *maybestr { - option::None => "(none)", - option::Some(ref s) => { - let s: &'a str = *s; - s - } - } -} - -pub fn opt_str2(maybestr: Option<~str>) -> ~str { - match maybestr { None => ~"(none)", Some(s) => { s } } -} - -pub fn str_opt(maybestr: ~str) -> Option<~str> { - if maybestr != ~"(none)" { option::Some(maybestr) } else { option::None } -} - -pub fn str_mode(s: ~str) -> mode { - match s { - ~"compile-fail" => mode_compile_fail, - ~"run-fail" => mode_run_fail, - ~"run-pass" => mode_run_pass, - ~"pretty" => mode_pretty, - ~"debug-info" => mode_debug_info, - _ => fail!("invalid mode") - } -} - -pub fn mode_str(mode: mode) -> ~str { - match mode { - mode_compile_fail => ~"compile-fail", - mode_run_fail => ~"run-fail", - mode_run_pass => ~"run-pass", - mode_pretty => ~"pretty", - mode_debug_info => ~"debug-info", - } -} - -pub fn run_tests(config: &config) { - let opts = test_opts(config); - let tests = make_tests(config); - let res = test::run_tests_console(&opts, tests); - if !res { fail!("Some tests failed"); } -} - -pub fn test_opts(config: &config) -> test::TestOpts { - test::TestOpts { - filter: copy config.filter, - run_ignored: config.run_ignored, - logfile: copy config.logfile, - run_tests: true, - run_benchmarks: false, - save_results: option::None, - compare_results: option::None - } -} - -pub fn make_tests(config: &config) -> ~[test::TestDescAndFn] { - debug!("making tests from %s", - config.src_base.to_str()); - let mut tests = ~[]; - let dirs = os::list_dir_path(&config.src_base); - for dirs.iter().advance |file| { - let file = copy *file; - debug!("inspecting file %s", file.to_str()); - if is_test(config, file) { - tests.push(make_test(config, file)) - } - } - tests -} - -pub fn is_test(config: &config, testfile: &Path) -> bool { - // Pretty-printer does not work with .rc files yet - let valid_extensions = - match config.mode { - mode_pretty => ~[~".rs"], - _ => ~[~".rc", ~".rs"] - }; - let invalid_prefixes = ~[~".", ~"#", ~"~"]; - let name = testfile.filename().get(); - - let mut valid = false; - - for valid_extensions.iter().advance |ext| { - if name.ends_with(*ext) { valid = true; } - } - - for invalid_prefixes.iter().advance |pre| { - if name.starts_with(*pre) { valid = false; } - } - - return valid; -} - -pub fn make_test(config: &config, testfile: &Path) -> test::TestDescAndFn { - test::TestDescAndFn { - desc: test::TestDesc { - name: make_test_name(config, testfile), - ignore: header::is_test_ignored(config, testfile), - should_fail: false - }, - testfn: make_test_closure(config, testfile), - } -} - -pub fn make_test_name(config: &config, testfile: &Path) -> test::TestName { - test::DynTestName(fmt!("[%s] %s", - mode_str(config.mode), - testfile.to_str())) -} - -pub fn make_test_closure(config: &config, testfile: &Path) -> test::TestFn { - use core::cell::Cell; - let config = Cell::new(copy *config); - let testfile = Cell::new(testfile.to_str()); - test::DynTestFn(|| { runtest::run(config.take(), testfile.take()) }) -} diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs new file mode 100644 index 00000000000..e8876c4851b --- /dev/null +++ b/src/compiletest/compiletest.rs @@ -0,0 +1,267 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[crate_type = "bin"]; + +#[allow(non_camel_case_types)]; + +#[no_core]; // XXX: Remove after snapshot +#[no_std]; + +extern mod core(name = "std", vers = "0.7-pre"); +extern mod extra(name = "extra", vers = "0.7-pre"); + +use core::prelude::*; +use core::*; + +use extra::getopts; +use extra::test; + +use core::result::{Ok, Err}; + +use common::config; +use common::mode_run_pass; +use common::mode_run_fail; +use common::mode_compile_fail; +use common::mode_pretty; +use common::mode_debug_info; +use common::mode; +use util::logv; + +pub mod procsrv; +pub mod util; +pub mod header; +pub mod runtest; +pub mod common; +pub mod errors; + +mod std { + pub use core::cmp; + pub use core::str; + pub use core::sys; + pub use core::unstable; +} + +pub fn main() { + let args = os::args(); + let config = parse_config(args); + log_config(&config); + run_tests(&config); +} + +pub fn parse_config(args: ~[~str]) -> config { + let opts = + ~[getopts::reqopt("compile-lib-path"), + getopts::reqopt("run-lib-path"), + getopts::reqopt("rustc-path"), getopts::reqopt("src-base"), + getopts::reqopt("build-base"), getopts::reqopt("aux-base"), + getopts::reqopt("stage-id"), + getopts::reqopt("mode"), getopts::optflag("ignored"), + getopts::optopt("runtool"), getopts::optopt("rustcflags"), + getopts::optflag("verbose"), + getopts::optopt("logfile"), + getopts::optflag("jit"), + getopts::optflag("newrt"), + getopts::optopt("target"), + getopts::optopt("adb-path"), + getopts::optopt("adb-test-dir") + ]; + + assert!(!args.is_empty()); + let args_ = vec::tail(args); + let matches = + &match getopts::getopts(args_, opts) { + Ok(m) => m, + Err(f) => fail!(getopts::fail_str(f)) + }; + + fn opt_path(m: &getopts::Matches, nm: &str) -> Path { + Path(getopts::opt_str(m, nm)) + } + + config { + compile_lib_path: getopts::opt_str(matches, "compile-lib-path"), + run_lib_path: getopts::opt_str(matches, "run-lib-path"), + rustc_path: opt_path(matches, "rustc-path"), + src_base: opt_path(matches, "src-base"), + build_base: opt_path(matches, "build-base"), + aux_base: opt_path(matches, "aux-base"), + stage_id: getopts::opt_str(matches, "stage-id"), + mode: str_mode(getopts::opt_str(matches, "mode")), + run_ignored: getopts::opt_present(matches, "ignored"), + filter: + if !matches.free.is_empty() { + option::Some(copy matches.free[0]) + } else { option::None }, + logfile: getopts::opt_maybe_str(matches, "logfile").map(|s| Path(*s)), + runtool: getopts::opt_maybe_str(matches, "runtool"), + rustcflags: getopts::opt_maybe_str(matches, "rustcflags"), + jit: getopts::opt_present(matches, "jit"), + newrt: getopts::opt_present(matches, "newrt"), + target: opt_str2(getopts::opt_maybe_str(matches, "target")).to_str(), + adb_path: opt_str2(getopts::opt_maybe_str(matches, "adb-path")).to_str(), + adb_test_dir: + opt_str2(getopts::opt_maybe_str(matches, "adb-test-dir")).to_str(), + adb_device_status: + if (opt_str2(getopts::opt_maybe_str(matches, "target")) == + ~"arm-linux-androideabi") { + if (opt_str2(getopts::opt_maybe_str(matches, "adb-test-dir")) != + ~"(none)" && + opt_str2(getopts::opt_maybe_str(matches, "adb-test-dir")) != + ~"") { true } + else { false } + } else { false }, + verbose: getopts::opt_present(matches, "verbose") + } +} + +pub fn log_config(config: &config) { + let c = config; + logv(c, fmt!("configuration:")); + logv(c, fmt!("compile_lib_path: %s", config.compile_lib_path)); + logv(c, fmt!("run_lib_path: %s", config.run_lib_path)); + logv(c, fmt!("rustc_path: %s", config.rustc_path.to_str())); + logv(c, fmt!("src_base: %s", config.src_base.to_str())); + logv(c, fmt!("build_base: %s", config.build_base.to_str())); + logv(c, fmt!("stage_id: %s", config.stage_id)); + logv(c, fmt!("mode: %s", mode_str(config.mode))); + logv(c, fmt!("run_ignored: %b", config.run_ignored)); + logv(c, fmt!("filter: %s", opt_str(&config.filter))); + logv(c, fmt!("runtool: %s", opt_str(&config.runtool))); + logv(c, fmt!("rustcflags: %s", opt_str(&config.rustcflags))); + logv(c, fmt!("jit: %b", config.jit)); + logv(c, fmt!("newrt: %b", config.newrt)); + logv(c, fmt!("target: %s", config.target)); + logv(c, fmt!("adb_path: %s", config.adb_path)); + logv(c, fmt!("adb_test_dir: %s", config.adb_test_dir)); + logv(c, fmt!("adb_device_status: %b", config.adb_device_status)); + logv(c, fmt!("verbose: %b", config.verbose)); + logv(c, fmt!("\n")); +} + +pub fn opt_str<'a>(maybestr: &'a Option<~str>) -> &'a str { + match *maybestr { + option::None => "(none)", + option::Some(ref s) => { + let s: &'a str = *s; + s + } + } +} + +pub fn opt_str2(maybestr: Option<~str>) -> ~str { + match maybestr { None => ~"(none)", Some(s) => { s } } +} + +pub fn str_opt(maybestr: ~str) -> Option<~str> { + if maybestr != ~"(none)" { option::Some(maybestr) } else { option::None } +} + +pub fn str_mode(s: ~str) -> mode { + match s { + ~"compile-fail" => mode_compile_fail, + ~"run-fail" => mode_run_fail, + ~"run-pass" => mode_run_pass, + ~"pretty" => mode_pretty, + ~"debug-info" => mode_debug_info, + _ => fail!("invalid mode") + } +} + +pub fn mode_str(mode: mode) -> ~str { + match mode { + mode_compile_fail => ~"compile-fail", + mode_run_fail => ~"run-fail", + mode_run_pass => ~"run-pass", + mode_pretty => ~"pretty", + mode_debug_info => ~"debug-info", + } +} + +pub fn run_tests(config: &config) { + let opts = test_opts(config); + let tests = make_tests(config); + let res = test::run_tests_console(&opts, tests); + if !res { fail!("Some tests failed"); } +} + +pub fn test_opts(config: &config) -> test::TestOpts { + test::TestOpts { + filter: copy config.filter, + run_ignored: config.run_ignored, + logfile: copy config.logfile, + run_tests: true, + run_benchmarks: false, + save_results: option::None, + compare_results: option::None + } +} + +pub fn make_tests(config: &config) -> ~[test::TestDescAndFn] { + debug!("making tests from %s", + config.src_base.to_str()); + let mut tests = ~[]; + let dirs = os::list_dir_path(&config.src_base); + for dirs.iter().advance |file| { + let file = copy *file; + debug!("inspecting file %s", file.to_str()); + if is_test(config, file) { + tests.push(make_test(config, file)) + } + } + tests +} + +pub fn is_test(config: &config, testfile: &Path) -> bool { + // Pretty-printer does not work with .rc files yet + let valid_extensions = + match config.mode { + mode_pretty => ~[~".rs"], + _ => ~[~".rc", ~".rs"] + }; + let invalid_prefixes = ~[~".", ~"#", ~"~"]; + let name = testfile.filename().get(); + + let mut valid = false; + + for valid_extensions.iter().advance |ext| { + if name.ends_with(*ext) { valid = true; } + } + + for invalid_prefixes.iter().advance |pre| { + if name.starts_with(*pre) { valid = false; } + } + + return valid; +} + +pub fn make_test(config: &config, testfile: &Path) -> test::TestDescAndFn { + test::TestDescAndFn { + desc: test::TestDesc { + name: make_test_name(config, testfile), + ignore: header::is_test_ignored(config, testfile), + should_fail: false + }, + testfn: make_test_closure(config, testfile), + } +} + +pub fn make_test_name(config: &config, testfile: &Path) -> test::TestName { + test::DynTestName(fmt!("[%s] %s", + mode_str(config.mode), + testfile.to_str())) +} + +pub fn make_test_closure(config: &config, testfile: &Path) -> test::TestFn { + use core::cell::Cell; + let config = Cell::new(copy *config); + let testfile = Cell::new(testfile.to_str()); + test::DynTestFn(|| { runtest::run(config.take(), testfile.take()) }) +} diff --git a/src/libextra/extra.rs b/src/libextra/extra.rs new file mode 100644 index 00000000000..11aebdf467f --- /dev/null +++ b/src/libextra/extra.rs @@ -0,0 +1,155 @@ +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/*! + +Rust extras. + +The `extra` crate is a set of useful modules for a variety of +purposes, including collections, numerics, I/O, serialization, +and concurrency. + +Rust extras are part of the standard Rust distribution. + +*/ + +#[link(name = "extra", + vers = "0.7-pre", + uuid = "122bed0b-c19b-4b82-b0b7-7ae8aead7297", + url = "https://github.com/mozilla/rust/tree/master/src/libextra")]; + +#[comment = "Rust extras"]; +#[license = "MIT/ASL2"]; +#[crate_type = "lib"]; + +#[deny(non_camel_case_types)]; +#[deny(missing_doc)]; + +#[no_std]; + +extern mod core(name = "std", vers = "0.7-pre"); + +use core::str::{StrSlice, OwnedStr}; + +pub use core::os; + +pub mod uv_ll; + +// General io and system-services modules + +pub mod net; +pub mod net_ip; +pub mod net_tcp; +pub mod net_url; + +// libuv modules +pub mod uv; +pub mod uv_iotask; +pub mod uv_global_loop; + + +// Utility modules + +pub mod c_vec; +pub mod timer; +pub mod io_util; +pub mod rc; + +// Concurrency + +pub mod sync; +pub mod arc; +pub mod comm; +pub mod future; +pub mod task_pool; +pub mod flatpipes; + +// Collections + +pub mod bitv; +pub mod deque; +pub mod fun_treemap; +pub mod list; +pub mod priority_queue; +pub mod rope; +pub mod smallintmap; + +pub mod sort; + +pub mod dlist; +pub mod treemap; + +// Crypto +#[path="crypto/digest.rs"] +pub mod digest; +#[path="crypto/sha1.rs"] +pub mod sha1; +#[path="crypto/sha2.rs"] +pub mod sha2; + +// And ... other stuff + +pub mod ebml; +pub mod dbg; +pub mod getopts; +pub mod json; +pub mod md4; +pub mod tempfile; +pub mod term; +pub mod time; +pub mod arena; +pub mod par; +pub mod base64; +pub mod rl; +pub mod workcache; +#[path="num/bigint.rs"] +pub mod bigint; +#[path="num/rational.rs"] +pub mod rational; +#[path="num/complex.rs"] +pub mod complex; +pub mod stats; +pub mod semver; +pub mod fileinput; +pub mod flate; + +#[cfg(unicode)] +mod unicode; + +#[path="terminfo/terminfo.rs"] +pub mod terminfo; + +// Compiler support modules + +pub mod test; +pub mod serialize; + +// A curious inner-module that's not exported that contains the binding +// 'extra' so that macro-expanded references to extra::serialize and such +// can be resolved within libextra. +#[doc(hidden)] +pub mod std { + pub use serialize; + pub use test; + + // For bootstrapping. + pub use core::clone; + pub use core::condition; + pub use core::cmp; + pub use core::sys; + pub use core::unstable; + pub use core::str; + pub use core::os; +} +#[doc(hidden)] +pub mod extra { + pub use serialize; + pub use test; +} diff --git a/src/libextra/std.rc b/src/libextra/std.rc deleted file mode 100644 index 11aebdf467f..00000000000 --- a/src/libextra/std.rc +++ /dev/null @@ -1,155 +0,0 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/*! - -Rust extras. - -The `extra` crate is a set of useful modules for a variety of -purposes, including collections, numerics, I/O, serialization, -and concurrency. - -Rust extras are part of the standard Rust distribution. - -*/ - -#[link(name = "extra", - vers = "0.7-pre", - uuid = "122bed0b-c19b-4b82-b0b7-7ae8aead7297", - url = "https://github.com/mozilla/rust/tree/master/src/libextra")]; - -#[comment = "Rust extras"]; -#[license = "MIT/ASL2"]; -#[crate_type = "lib"]; - -#[deny(non_camel_case_types)]; -#[deny(missing_doc)]; - -#[no_std]; - -extern mod core(name = "std", vers = "0.7-pre"); - -use core::str::{StrSlice, OwnedStr}; - -pub use core::os; - -pub mod uv_ll; - -// General io and system-services modules - -pub mod net; -pub mod net_ip; -pub mod net_tcp; -pub mod net_url; - -// libuv modules -pub mod uv; -pub mod uv_iotask; -pub mod uv_global_loop; - - -// Utility modules - -pub mod c_vec; -pub mod timer; -pub mod io_util; -pub mod rc; - -// Concurrency - -pub mod sync; -pub mod arc; -pub mod comm; -pub mod future; -pub mod task_pool; -pub mod flatpipes; - -// Collections - -pub mod bitv; -pub mod deque; -pub mod fun_treemap; -pub mod list; -pub mod priority_queue; -pub mod rope; -pub mod smallintmap; - -pub mod sort; - -pub mod dlist; -pub mod treemap; - -// Crypto -#[path="crypto/digest.rs"] -pub mod digest; -#[path="crypto/sha1.rs"] -pub mod sha1; -#[path="crypto/sha2.rs"] -pub mod sha2; - -// And ... other stuff - -pub mod ebml; -pub mod dbg; -pub mod getopts; -pub mod json; -pub mod md4; -pub mod tempfile; -pub mod term; -pub mod time; -pub mod arena; -pub mod par; -pub mod base64; -pub mod rl; -pub mod workcache; -#[path="num/bigint.rs"] -pub mod bigint; -#[path="num/rational.rs"] -pub mod rational; -#[path="num/complex.rs"] -pub mod complex; -pub mod stats; -pub mod semver; -pub mod fileinput; -pub mod flate; - -#[cfg(unicode)] -mod unicode; - -#[path="terminfo/terminfo.rs"] -pub mod terminfo; - -// Compiler support modules - -pub mod test; -pub mod serialize; - -// A curious inner-module that's not exported that contains the binding -// 'extra' so that macro-expanded references to extra::serialize and such -// can be resolved within libextra. -#[doc(hidden)] -pub mod std { - pub use serialize; - pub use test; - - // For bootstrapping. - pub use core::clone; - pub use core::condition; - pub use core::cmp; - pub use core::sys; - pub use core::unstable; - pub use core::str; - pub use core::os; -} -#[doc(hidden)] -pub mod extra { - pub use serialize; - pub use test; -} diff --git a/src/librust/rust.rc b/src/librust/rust.rc deleted file mode 100644 index 68427745ff5..00000000000 --- a/src/librust/rust.rc +++ /dev/null @@ -1,255 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// rust - central access to other rust tools -// FIXME #2238 Make commands run and test emit proper file endings on windows -// FIXME #2238 Make run only accept source that emits an executable - -#[link(name = "rust", - vers = "0.7-pre", - uuid = "4a24da33-5cc8-4037-9352-2cbe9bd9d27c", - url = "https://github.com/mozilla/rust/tree/master/src/rust")]; - -#[license = "MIT/ASL2"]; -#[crate_type = "lib"]; - -#[no_std]; - -extern mod core(name = "std"); - -extern mod rustpkg; -extern mod rustdoc; -extern mod rusti; -extern mod rustc; - -use core::prelude::*; - -use core::io; -use core::os; -use core::run; -use core::libc::exit; - -// For bootstrapping. -mod std { - pub use core::os; - pub use core::str; - pub use core::unstable; -} - -enum ValidUsage { - Valid(int), Invalid -} - -impl ValidUsage { - fn is_valid(&self) -> bool { - match *self { - Valid(_) => true, - Invalid => false - } - } -} - -enum Action<'self> { - Call(&'self fn(args: &[~str]) -> ValidUsage), - CallMain(&'static str, &'self fn()), -} - -enum UsageSource<'self> { - UsgStr(&'self str), - UsgCall(&'self fn()), -} - -struct Command<'self> { - cmd: &'self str, - action: Action<'self>, - usage_line: &'self str, - usage_full: UsageSource<'self>, -} - -static commands: &'static [Command<'static>] = &[ - Command{ - cmd: "build", - action: CallMain("rustc", rustc::main), - usage_line: "compile rust source files", - usage_full: UsgCall(rustc_help), - }, - Command{ - cmd: "run", - action: Call(cmd_run), - usage_line: "build an executable, and run it", - usage_full: UsgStr( - "The run command is an shortcut for the command line \n\ - \"rustc -o ~ && ./~ [...]\".\ - \n\nUsage:\trust run [...]" - ) - }, - Command{ - cmd: "test", - action: Call(cmd_test), - usage_line: "build a test executable, and run it", - usage_full: UsgStr( - "The test command is an shortcut for the command line \n\ - \"rustc --test -o test~ && \ - ./test~\"\n\nUsage:\trust test " - ) - }, - Command{ - cmd: "doc", - action: CallMain("rustdoc", rustdoc::main), - usage_line: "generate documentation from doc comments", - usage_full: UsgCall(rustdoc::config::usage), - }, - Command{ - cmd: "pkg", - action: CallMain("rustpkg", rustpkg::main), - usage_line: "download, build, install rust packages", - usage_full: UsgCall(rustpkg::usage::general), - }, - Command{ - cmd: "sketch", - action: CallMain("rusti", rusti::main), - usage_line: "run a rust interpreter", - usage_full: UsgStr("\nUsage:\trusti"), - }, - Command{ - cmd: "help", - action: Call(cmd_help), - usage_line: "show detailed usage of a command", - usage_full: UsgStr( - "The help command displays the usage text of another command.\n\ - The text is either build in, or provided by the corresponding \ - program.\n\nUsage:\trust help " - ) - } -]; - -fn rustc_help() { - rustc::usage(copy os::args()[0]) -} - -fn find_cmd(command_string: &str) -> Option { - do commands.iter().find_ |command| { - command.cmd == command_string - }.map_consume(|x| copy *x) -} - -fn cmd_help(args: &[~str]) -> ValidUsage { - fn print_usage(command_string: ~str) -> ValidUsage { - match find_cmd(command_string) { - Some(command) => { - match command.action { - CallMain(prog, _) => io::println(fmt!( - "The %s command is an alias for the %s program.", - command.cmd, prog)), - _ => () - } - match command.usage_full { - UsgStr(msg) => io::println(fmt!("%s\n", msg)), - UsgCall(f) => f(), - } - Valid(0) - }, - None => Invalid - } - } - - match args { - [ref command_string] => print_usage(copy *command_string), - _ => Invalid - } -} - -fn cmd_test(args: &[~str]) -> ValidUsage { - match args { - [ref filename] => { - let test_exec = Path(*filename).filestem().unwrap() + "test~"; - invoke("rustc", &[~"--test", filename.to_owned(), - ~"-o", test_exec.to_owned()], rustc::main); - let exit_code = run::process_status(~"./" + test_exec, []); - Valid(exit_code) - } - _ => Invalid - } -} - -fn cmd_run(args: &[~str]) -> ValidUsage { - match args { - [ref filename, ..prog_args] => { - let exec = Path(*filename).filestem().unwrap() + "~"; - invoke("rustc", &[filename.to_owned(), ~"-o", exec.to_owned()], - rustc::main); - let exit_code = run::process_status(~"./"+exec, prog_args); - Valid(exit_code) - } - _ => Invalid - } -} - -fn invoke(prog: &str, args: &[~str], f: &fn()) { - let mut osargs = ~[prog.to_owned()]; - osargs.push_all_move(args.to_owned()); - os::set_args(osargs); - f(); -} - -fn do_command(command: &Command, args: &[~str]) -> ValidUsage { - match command.action { - Call(f) => f(args), - CallMain(prog, f) => { - invoke(prog, args, f); - Valid(0) - } - } -} - -fn usage() { - static indent: uint = 8; - - io::print( - "The rust tool is a convenience for managing rust source code.\n\ - It acts as a shortcut for programs of the rust tool chain.\n\ - \n\ - Usage:\trust [arguments]\n\ - \n\ - The commands are:\n\ - \n" - ); - - for commands.iter().advance |command| { - let padding = " ".repeat(indent - command.cmd.len()); - io::println(fmt!(" %s%s%s", - command.cmd, padding, command.usage_line)); - } - - io::print( - "\n\ - Use \"rust help \" for more information about a command.\n\ - \n" - ); - -} - -pub fn main() { - let os_args = os::args(); - let args = os_args.tail(); - - if !args.is_empty() { - let r = find_cmd(*args.head()); - for r.iter().advance |command| { - let result = do_command(command, args.tail()); - match result { - Valid(exit_code) => unsafe { exit(exit_code.to_i32()) }, - _ => loop - } - } - } - - usage(); -} diff --git a/src/librust/rust.rs b/src/librust/rust.rs new file mode 100644 index 00000000000..68427745ff5 --- /dev/null +++ b/src/librust/rust.rs @@ -0,0 +1,255 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// rust - central access to other rust tools +// FIXME #2238 Make commands run and test emit proper file endings on windows +// FIXME #2238 Make run only accept source that emits an executable + +#[link(name = "rust", + vers = "0.7-pre", + uuid = "4a24da33-5cc8-4037-9352-2cbe9bd9d27c", + url = "https://github.com/mozilla/rust/tree/master/src/rust")]; + +#[license = "MIT/ASL2"]; +#[crate_type = "lib"]; + +#[no_std]; + +extern mod core(name = "std"); + +extern mod rustpkg; +extern mod rustdoc; +extern mod rusti; +extern mod rustc; + +use core::prelude::*; + +use core::io; +use core::os; +use core::run; +use core::libc::exit; + +// For bootstrapping. +mod std { + pub use core::os; + pub use core::str; + pub use core::unstable; +} + +enum ValidUsage { + Valid(int), Invalid +} + +impl ValidUsage { + fn is_valid(&self) -> bool { + match *self { + Valid(_) => true, + Invalid => false + } + } +} + +enum Action<'self> { + Call(&'self fn(args: &[~str]) -> ValidUsage), + CallMain(&'static str, &'self fn()), +} + +enum UsageSource<'self> { + UsgStr(&'self str), + UsgCall(&'self fn()), +} + +struct Command<'self> { + cmd: &'self str, + action: Action<'self>, + usage_line: &'self str, + usage_full: UsageSource<'self>, +} + +static commands: &'static [Command<'static>] = &[ + Command{ + cmd: "build", + action: CallMain("rustc", rustc::main), + usage_line: "compile rust source files", + usage_full: UsgCall(rustc_help), + }, + Command{ + cmd: "run", + action: Call(cmd_run), + usage_line: "build an executable, and run it", + usage_full: UsgStr( + "The run command is an shortcut for the command line \n\ + \"rustc -o ~ && ./~ [...]\".\ + \n\nUsage:\trust run [...]" + ) + }, + Command{ + cmd: "test", + action: Call(cmd_test), + usage_line: "build a test executable, and run it", + usage_full: UsgStr( + "The test command is an shortcut for the command line \n\ + \"rustc --test -o test~ && \ + ./test~\"\n\nUsage:\trust test " + ) + }, + Command{ + cmd: "doc", + action: CallMain("rustdoc", rustdoc::main), + usage_line: "generate documentation from doc comments", + usage_full: UsgCall(rustdoc::config::usage), + }, + Command{ + cmd: "pkg", + action: CallMain("rustpkg", rustpkg::main), + usage_line: "download, build, install rust packages", + usage_full: UsgCall(rustpkg::usage::general), + }, + Command{ + cmd: "sketch", + action: CallMain("rusti", rusti::main), + usage_line: "run a rust interpreter", + usage_full: UsgStr("\nUsage:\trusti"), + }, + Command{ + cmd: "help", + action: Call(cmd_help), + usage_line: "show detailed usage of a command", + usage_full: UsgStr( + "The help command displays the usage text of another command.\n\ + The text is either build in, or provided by the corresponding \ + program.\n\nUsage:\trust help " + ) + } +]; + +fn rustc_help() { + rustc::usage(copy os::args()[0]) +} + +fn find_cmd(command_string: &str) -> Option { + do commands.iter().find_ |command| { + command.cmd == command_string + }.map_consume(|x| copy *x) +} + +fn cmd_help(args: &[~str]) -> ValidUsage { + fn print_usage(command_string: ~str) -> ValidUsage { + match find_cmd(command_string) { + Some(command) => { + match command.action { + CallMain(prog, _) => io::println(fmt!( + "The %s command is an alias for the %s program.", + command.cmd, prog)), + _ => () + } + match command.usage_full { + UsgStr(msg) => io::println(fmt!("%s\n", msg)), + UsgCall(f) => f(), + } + Valid(0) + }, + None => Invalid + } + } + + match args { + [ref command_string] => print_usage(copy *command_string), + _ => Invalid + } +} + +fn cmd_test(args: &[~str]) -> ValidUsage { + match args { + [ref filename] => { + let test_exec = Path(*filename).filestem().unwrap() + "test~"; + invoke("rustc", &[~"--test", filename.to_owned(), + ~"-o", test_exec.to_owned()], rustc::main); + let exit_code = run::process_status(~"./" + test_exec, []); + Valid(exit_code) + } + _ => Invalid + } +} + +fn cmd_run(args: &[~str]) -> ValidUsage { + match args { + [ref filename, ..prog_args] => { + let exec = Path(*filename).filestem().unwrap() + "~"; + invoke("rustc", &[filename.to_owned(), ~"-o", exec.to_owned()], + rustc::main); + let exit_code = run::process_status(~"./"+exec, prog_args); + Valid(exit_code) + } + _ => Invalid + } +} + +fn invoke(prog: &str, args: &[~str], f: &fn()) { + let mut osargs = ~[prog.to_owned()]; + osargs.push_all_move(args.to_owned()); + os::set_args(osargs); + f(); +} + +fn do_command(command: &Command, args: &[~str]) -> ValidUsage { + match command.action { + Call(f) => f(args), + CallMain(prog, f) => { + invoke(prog, args, f); + Valid(0) + } + } +} + +fn usage() { + static indent: uint = 8; + + io::print( + "The rust tool is a convenience for managing rust source code.\n\ + It acts as a shortcut for programs of the rust tool chain.\n\ + \n\ + Usage:\trust [arguments]\n\ + \n\ + The commands are:\n\ + \n" + ); + + for commands.iter().advance |command| { + let padding = " ".repeat(indent - command.cmd.len()); + io::println(fmt!(" %s%s%s", + command.cmd, padding, command.usage_line)); + } + + io::print( + "\n\ + Use \"rust help \" for more information about a command.\n\ + \n" + ); + +} + +pub fn main() { + let os_args = os::args(); + let args = os_args.tail(); + + if !args.is_empty() { + let r = find_cmd(*args.head()); + for r.iter().advance |command| { + let result = do_command(command, args.tail()); + match result { + Valid(exit_code) => unsafe { exit(exit_code.to_i32()) }, + _ => loop + } + } + } + + usage(); +} diff --git a/src/librustc/rustc.rc b/src/librustc/rustc.rc deleted file mode 100644 index 20705b3d797..00000000000 --- a/src/librustc/rustc.rc +++ /dev/null @@ -1,369 +0,0 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[link(name = "rustc", - vers = "0.7-pre", - uuid = "0ce89b41-2f92-459e-bbc1-8f5fe32f16cf", - url = "https://github.com/mozilla/rust/tree/master/src/rustc")]; - -#[comment = "The Rust compiler"]; -#[license = "MIT/ASL2"]; -#[crate_type = "lib"]; - -#[allow(non_implicitly_copyable_typarams)]; -#[allow(non_camel_case_types)]; -#[deny(deprecated_pattern)]; - -#[no_core]; -#[no_std]; - -extern mod core(name = "std"); -extern mod extra(name = "extra"); -extern mod syntax; - -extern mod std(name = "std", vers = "0.7-pre"); - -use core::prelude::*; - -use driver::driver::{host_triple, optgroups, early_error}; -use driver::driver::{str_input, file_input, build_session_options}; -use driver::driver::{build_session, build_configuration, parse_pretty}; -use driver::driver::{pp_mode, pretty_print_input, list_metadata}; -use driver::driver::{compile_input}; -use driver::session; -use middle::lint; - -use core::io; -use core::os; -use core::result; -use core::str; -use core::task; -use core::uint; -use core::vec; -use extra::getopts::{groups, opt_present}; -use extra::getopts; -use syntax::codemap; -use syntax::diagnostic; - -pub mod middle { - #[path = "trans/mod.rs"] - pub mod trans; - pub mod ty; - pub mod subst; - pub mod resolve; - #[path = "typeck/mod.rs"] - pub mod typeck; - pub mod check_loop; - pub mod check_match; - pub mod check_const; - pub mod lint; - #[path = "borrowck/mod.rs"] - pub mod borrowck; - pub mod dataflow; - pub mod mem_categorization; - pub mod liveness; - pub mod kind; - pub mod freevars; - pub mod pat_util; - pub mod region; - pub mod const_eval; - pub mod astencode; - pub mod lang_items; - pub mod privacy; - pub mod moves; - pub mod entry; - pub mod effect; -} - -pub mod front { - pub mod config; - pub mod test; - pub mod std_inject; -} - -pub mod back { - pub mod link; - pub mod abi; - pub mod upcall; - pub mod arm; - pub mod mips; - pub mod x86; - pub mod x86_64; - pub mod rpath; - pub mod target_strs; - pub mod passes; -} - -#[path = "metadata/mod.rs"] -pub mod metadata; - -#[path = "driver/mod.rs"] -pub mod driver; - -pub mod util { - pub mod common; - pub mod ppaux; - pub mod enum_set; -} - -pub mod lib { - pub mod llvm; -} - -// A curious inner module that allows ::std::foo to be available in here for -// macros. -mod std { - pub use core::cmp; - pub use core::os; - pub use core::str; - pub use core::sys; - pub use core::to_bytes; - pub use core::unstable; - pub use extra::serialize; -} - -pub fn version(argv0: &str) { - let mut vers = ~"unknown version"; - let env_vers = env!("CFG_VERSION"); - if env_vers.len() != 0 { vers = env_vers.to_owned(); } - io::println(fmt!("%s %s", argv0, vers)); - io::println(fmt!("host: %s", host_triple())); -} - -pub fn usage(argv0: &str) { - let message = fmt!("Usage: %s [OPTIONS] INPUT", argv0); - io::println(fmt!("%s\ -Additional help: - -W help Print 'lint' options and default settings - -Z help Print internal options for debugging rustc\n", - groups::usage(message, optgroups()))); -} - -pub fn describe_warnings() { - io::println(fmt!(" -Available lint options: - -W Warn about - -A Allow - -D Deny - -F Forbid (deny, and deny all overrides) -")); - - let lint_dict = lint::get_lint_dict(); - let mut max_key = 0; - for lint_dict.each_key |k| { max_key = uint::max(k.len(), max_key); } - fn padded(max: uint, s: &str) -> ~str { - str::from_bytes(vec::from_elem(max - s.len(), ' ' as u8)) + s - } - io::println(fmt!("\nAvailable lint checks:\n")); - io::println(fmt!(" %s %7.7s %s", - padded(max_key, "name"), "default", "meaning")); - io::println(fmt!(" %s %7.7s %s\n", - padded(max_key, "----"), "-------", "-------")); - for lint_dict.each |k, v| { - let k = k.replace("_", "-"); - io::println(fmt!(" %s %7.7s %s", - padded(max_key, k), - match v.default { - lint::allow => ~"allow", - lint::warn => ~"warn", - lint::deny => ~"deny", - lint::forbid => ~"forbid" - }, - v.desc)); - } - io::println(""); -} - -pub fn describe_debug_flags() { - io::println(fmt!("\nAvailable debug options:\n")); - let r = session::debugging_opts_map(); - for r.iter().advance |pair| { - let (name, desc, _) = /*bad*/copy *pair; - io::println(fmt!(" -Z %-20s -- %s", name, desc)); - } -} - -pub fn run_compiler(args: &~[~str], demitter: diagnostic::Emitter) { - // Don't display log spew by default. Can override with RUST_LOG. - ::core::logging::console_off(); - - let mut args = /*bad*/copy *args; - let binary = args.shift().to_managed(); - - if args.is_empty() { usage(binary); return; } - - let matches = - &match getopts::groups::getopts(args, optgroups()) { - Ok(m) => m, - Err(f) => { - early_error(demitter, getopts::fail_str(f)); - } - }; - - if opt_present(matches, "h") || opt_present(matches, "help") { - usage(binary); - return; - } - - // Display the available lint options if "-W help" or only "-W" is given. - let lint_flags = vec::append(getopts::opt_strs(matches, "W"), - getopts::opt_strs(matches, "warn")); - - let show_lint_options = lint_flags.iter().any_(|x| x == &~"help") || - (opt_present(matches, "W") && lint_flags.is_empty()); - - if show_lint_options { - describe_warnings(); - return; - } - - let r = getopts::opt_strs(matches, "Z"); - if r.iter().any_(|x| x == &~"help") { - describe_debug_flags(); - return; - } - - if getopts::opt_maybe_str(matches, "passes") == Some(~"list") { - back::passes::list_passes(); - return; - } - - if opt_present(matches, "v") || opt_present(matches, "version") { - version(binary); - return; - } - let input = match matches.free.len() { - 0u => early_error(demitter, ~"no input filename given"), - 1u => { - let ifile = matches.free[0].as_slice(); - if "-" == ifile { - let src = str::from_bytes(io::stdin().read_whole_stream()); - str_input(src.to_managed()) - } else { - file_input(Path(ifile)) - } - } - _ => early_error(demitter, ~"multiple input filenames provided") - }; - - let sopts = build_session_options(binary, matches, demitter); - let sess = build_session(sopts, demitter); - let odir = getopts::opt_maybe_str(matches, "out-dir"); - let odir = odir.map(|o| Path(*o)); - let ofile = getopts::opt_maybe_str(matches, "o"); - let ofile = ofile.map(|o| Path(*o)); - let cfg = build_configuration(sess, binary, &input); - let pretty = getopts::opt_default(matches, "pretty", "normal").map( - |a| parse_pretty(sess, *a)); - match pretty { - Some::(ppm) => { - pretty_print_input(sess, cfg, &input, ppm); - return; - } - None:: => {/* continue */ } - } - let ls = opt_present(matches, "ls"); - if ls { - match input { - file_input(ref ifile) => { - list_metadata(sess, &(*ifile), io::stdout()); - } - str_input(_) => { - early_error(demitter, ~"can not list metadata for stdin"); - } - } - return; - } - - compile_input(sess, cfg, &input, &odir, &ofile); -} - -#[deriving(Eq)] -pub enum monitor_msg { - fatal, - done, -} - -/* -This is a sanity check that any failure of the compiler is performed -through the diagnostic module and reported properly - we shouldn't be calling -plain-old-fail on any execution path that might be taken. Since we have -console logging off by default, hitting a plain fail statement would make the -compiler silently exit, which would be terrible. - -This method wraps the compiler in a subtask and injects a function into the -diagnostic emitter which records when we hit a fatal error. If the task -fails without recording a fatal error then we've encountered a compiler -bug and need to present an error. -*/ -pub fn monitor(f: ~fn(diagnostic::Emitter)) { - use core::comm::*; - let (p, ch) = stream(); - let ch = SharedChan::new(ch); - let ch_capture = ch.clone(); - match do task::try || { - let ch = ch_capture.clone(); - let ch_capture = ch.clone(); - // The 'diagnostics emitter'. Every error, warning, etc. should - // go through this function. - let demitter: @fn(Option<(@codemap::CodeMap, codemap::span)>, - &str, - diagnostic::level) = - |cmsp, msg, lvl| { - if lvl == diagnostic::fatal { - ch_capture.send(fatal); - } - diagnostic::emit(cmsp, msg, lvl); - }; - - struct finally { - ch: SharedChan, - } - - impl Drop for finally { - fn finalize(&self) { self.ch.send(done); } - } - - let _finally = finally { ch: ch }; - - f(demitter) - } { - result::Ok(_) => { /* fallthrough */ } - result::Err(_) => { - // Task failed without emitting a fatal diagnostic - if p.recv() == done { - diagnostic::emit( - None, - diagnostic::ice_msg("unexpected failure"), - diagnostic::error); - - let xs = [ - ~"the compiler hit an unexpected failure path. \ - this is a bug", - ~"try running with RUST_LOG=rustc=1,::rt::backtrace \ - to get further details and report the results \ - to github.com/mozilla/rust/issues" - ]; - for xs.iter().advance |note| { - diagnostic::emit(None, *note, diagnostic::note) - } - } - // Fail so the process returns a failure code - fail!(); - } - } -} - -pub fn main() { - let args = os::args(); - do monitor |demitter| { - run_compiler(&args, demitter); - } -} diff --git a/src/librustc/rustc.rs b/src/librustc/rustc.rs new file mode 100644 index 00000000000..20705b3d797 --- /dev/null +++ b/src/librustc/rustc.rs @@ -0,0 +1,369 @@ +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[link(name = "rustc", + vers = "0.7-pre", + uuid = "0ce89b41-2f92-459e-bbc1-8f5fe32f16cf", + url = "https://github.com/mozilla/rust/tree/master/src/rustc")]; + +#[comment = "The Rust compiler"]; +#[license = "MIT/ASL2"]; +#[crate_type = "lib"]; + +#[allow(non_implicitly_copyable_typarams)]; +#[allow(non_camel_case_types)]; +#[deny(deprecated_pattern)]; + +#[no_core]; +#[no_std]; + +extern mod core(name = "std"); +extern mod extra(name = "extra"); +extern mod syntax; + +extern mod std(name = "std", vers = "0.7-pre"); + +use core::prelude::*; + +use driver::driver::{host_triple, optgroups, early_error}; +use driver::driver::{str_input, file_input, build_session_options}; +use driver::driver::{build_session, build_configuration, parse_pretty}; +use driver::driver::{pp_mode, pretty_print_input, list_metadata}; +use driver::driver::{compile_input}; +use driver::session; +use middle::lint; + +use core::io; +use core::os; +use core::result; +use core::str; +use core::task; +use core::uint; +use core::vec; +use extra::getopts::{groups, opt_present}; +use extra::getopts; +use syntax::codemap; +use syntax::diagnostic; + +pub mod middle { + #[path = "trans/mod.rs"] + pub mod trans; + pub mod ty; + pub mod subst; + pub mod resolve; + #[path = "typeck/mod.rs"] + pub mod typeck; + pub mod check_loop; + pub mod check_match; + pub mod check_const; + pub mod lint; + #[path = "borrowck/mod.rs"] + pub mod borrowck; + pub mod dataflow; + pub mod mem_categorization; + pub mod liveness; + pub mod kind; + pub mod freevars; + pub mod pat_util; + pub mod region; + pub mod const_eval; + pub mod astencode; + pub mod lang_items; + pub mod privacy; + pub mod moves; + pub mod entry; + pub mod effect; +} + +pub mod front { + pub mod config; + pub mod test; + pub mod std_inject; +} + +pub mod back { + pub mod link; + pub mod abi; + pub mod upcall; + pub mod arm; + pub mod mips; + pub mod x86; + pub mod x86_64; + pub mod rpath; + pub mod target_strs; + pub mod passes; +} + +#[path = "metadata/mod.rs"] +pub mod metadata; + +#[path = "driver/mod.rs"] +pub mod driver; + +pub mod util { + pub mod common; + pub mod ppaux; + pub mod enum_set; +} + +pub mod lib { + pub mod llvm; +} + +// A curious inner module that allows ::std::foo to be available in here for +// macros. +mod std { + pub use core::cmp; + pub use core::os; + pub use core::str; + pub use core::sys; + pub use core::to_bytes; + pub use core::unstable; + pub use extra::serialize; +} + +pub fn version(argv0: &str) { + let mut vers = ~"unknown version"; + let env_vers = env!("CFG_VERSION"); + if env_vers.len() != 0 { vers = env_vers.to_owned(); } + io::println(fmt!("%s %s", argv0, vers)); + io::println(fmt!("host: %s", host_triple())); +} + +pub fn usage(argv0: &str) { + let message = fmt!("Usage: %s [OPTIONS] INPUT", argv0); + io::println(fmt!("%s\ +Additional help: + -W help Print 'lint' options and default settings + -Z help Print internal options for debugging rustc\n", + groups::usage(message, optgroups()))); +} + +pub fn describe_warnings() { + io::println(fmt!(" +Available lint options: + -W Warn about + -A Allow + -D Deny + -F Forbid (deny, and deny all overrides) +")); + + let lint_dict = lint::get_lint_dict(); + let mut max_key = 0; + for lint_dict.each_key |k| { max_key = uint::max(k.len(), max_key); } + fn padded(max: uint, s: &str) -> ~str { + str::from_bytes(vec::from_elem(max - s.len(), ' ' as u8)) + s + } + io::println(fmt!("\nAvailable lint checks:\n")); + io::println(fmt!(" %s %7.7s %s", + padded(max_key, "name"), "default", "meaning")); + io::println(fmt!(" %s %7.7s %s\n", + padded(max_key, "----"), "-------", "-------")); + for lint_dict.each |k, v| { + let k = k.replace("_", "-"); + io::println(fmt!(" %s %7.7s %s", + padded(max_key, k), + match v.default { + lint::allow => ~"allow", + lint::warn => ~"warn", + lint::deny => ~"deny", + lint::forbid => ~"forbid" + }, + v.desc)); + } + io::println(""); +} + +pub fn describe_debug_flags() { + io::println(fmt!("\nAvailable debug options:\n")); + let r = session::debugging_opts_map(); + for r.iter().advance |pair| { + let (name, desc, _) = /*bad*/copy *pair; + io::println(fmt!(" -Z %-20s -- %s", name, desc)); + } +} + +pub fn run_compiler(args: &~[~str], demitter: diagnostic::Emitter) { + // Don't display log spew by default. Can override with RUST_LOG. + ::core::logging::console_off(); + + let mut args = /*bad*/copy *args; + let binary = args.shift().to_managed(); + + if args.is_empty() { usage(binary); return; } + + let matches = + &match getopts::groups::getopts(args, optgroups()) { + Ok(m) => m, + Err(f) => { + early_error(demitter, getopts::fail_str(f)); + } + }; + + if opt_present(matches, "h") || opt_present(matches, "help") { + usage(binary); + return; + } + + // Display the available lint options if "-W help" or only "-W" is given. + let lint_flags = vec::append(getopts::opt_strs(matches, "W"), + getopts::opt_strs(matches, "warn")); + + let show_lint_options = lint_flags.iter().any_(|x| x == &~"help") || + (opt_present(matches, "W") && lint_flags.is_empty()); + + if show_lint_options { + describe_warnings(); + return; + } + + let r = getopts::opt_strs(matches, "Z"); + if r.iter().any_(|x| x == &~"help") { + describe_debug_flags(); + return; + } + + if getopts::opt_maybe_str(matches, "passes") == Some(~"list") { + back::passes::list_passes(); + return; + } + + if opt_present(matches, "v") || opt_present(matches, "version") { + version(binary); + return; + } + let input = match matches.free.len() { + 0u => early_error(demitter, ~"no input filename given"), + 1u => { + let ifile = matches.free[0].as_slice(); + if "-" == ifile { + let src = str::from_bytes(io::stdin().read_whole_stream()); + str_input(src.to_managed()) + } else { + file_input(Path(ifile)) + } + } + _ => early_error(demitter, ~"multiple input filenames provided") + }; + + let sopts = build_session_options(binary, matches, demitter); + let sess = build_session(sopts, demitter); + let odir = getopts::opt_maybe_str(matches, "out-dir"); + let odir = odir.map(|o| Path(*o)); + let ofile = getopts::opt_maybe_str(matches, "o"); + let ofile = ofile.map(|o| Path(*o)); + let cfg = build_configuration(sess, binary, &input); + let pretty = getopts::opt_default(matches, "pretty", "normal").map( + |a| parse_pretty(sess, *a)); + match pretty { + Some::(ppm) => { + pretty_print_input(sess, cfg, &input, ppm); + return; + } + None:: => {/* continue */ } + } + let ls = opt_present(matches, "ls"); + if ls { + match input { + file_input(ref ifile) => { + list_metadata(sess, &(*ifile), io::stdout()); + } + str_input(_) => { + early_error(demitter, ~"can not list metadata for stdin"); + } + } + return; + } + + compile_input(sess, cfg, &input, &odir, &ofile); +} + +#[deriving(Eq)] +pub enum monitor_msg { + fatal, + done, +} + +/* +This is a sanity check that any failure of the compiler is performed +through the diagnostic module and reported properly - we shouldn't be calling +plain-old-fail on any execution path that might be taken. Since we have +console logging off by default, hitting a plain fail statement would make the +compiler silently exit, which would be terrible. + +This method wraps the compiler in a subtask and injects a function into the +diagnostic emitter which records when we hit a fatal error. If the task +fails without recording a fatal error then we've encountered a compiler +bug and need to present an error. +*/ +pub fn monitor(f: ~fn(diagnostic::Emitter)) { + use core::comm::*; + let (p, ch) = stream(); + let ch = SharedChan::new(ch); + let ch_capture = ch.clone(); + match do task::try || { + let ch = ch_capture.clone(); + let ch_capture = ch.clone(); + // The 'diagnostics emitter'. Every error, warning, etc. should + // go through this function. + let demitter: @fn(Option<(@codemap::CodeMap, codemap::span)>, + &str, + diagnostic::level) = + |cmsp, msg, lvl| { + if lvl == diagnostic::fatal { + ch_capture.send(fatal); + } + diagnostic::emit(cmsp, msg, lvl); + }; + + struct finally { + ch: SharedChan, + } + + impl Drop for finally { + fn finalize(&self) { self.ch.send(done); } + } + + let _finally = finally { ch: ch }; + + f(demitter) + } { + result::Ok(_) => { /* fallthrough */ } + result::Err(_) => { + // Task failed without emitting a fatal diagnostic + if p.recv() == done { + diagnostic::emit( + None, + diagnostic::ice_msg("unexpected failure"), + diagnostic::error); + + let xs = [ + ~"the compiler hit an unexpected failure path. \ + this is a bug", + ~"try running with RUST_LOG=rustc=1,::rt::backtrace \ + to get further details and report the results \ + to github.com/mozilla/rust/issues" + ]; + for xs.iter().advance |note| { + diagnostic::emit(None, *note, diagnostic::note) + } + } + // Fail so the process returns a failure code + fail!(); + } + } +} + +pub fn main() { + let args = os::args(); + do monitor |demitter| { + run_compiler(&args, demitter); + } +} diff --git a/src/librustdoc/rustdoc.rc b/src/librustdoc/rustdoc.rc deleted file mode 100644 index d02620229f5..00000000000 --- a/src/librustdoc/rustdoc.rc +++ /dev/null @@ -1,162 +0,0 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Rustdoc - The Rust documentation generator - -#[link(name = "rustdoc", - vers = "0.7-pre", - uuid = "f8abd014-b281-484d-a0c3-26e3de8e2412", - url = "https://github.com/mozilla/rust/tree/master/src/rustdoc")]; - -#[comment = "The Rust documentation generator"]; -#[license = "MIT/ASL2"]; -#[crate_type = "lib"]; - -#[allow(non_implicitly_copyable_typarams)]; - -#[no_std]; - -extern mod core(name = "std"); -extern mod extra(name = "extra"); - -extern mod rustc; -extern mod syntax; - -use core::prelude::*; - -use config::Config; -use doc::Item; -use doc::ItemUtils; - -use core::*; - -pub mod pass; -pub mod config; -pub mod parse; -pub mod extract; -pub mod attr_parser; -pub mod doc; -pub mod markdown_index_pass; -pub mod markdown_pass; -pub mod markdown_writer; -pub mod fold; -pub mod path_pass; -pub mod attr_pass; -pub mod tystr_pass; -pub mod prune_hidden_pass; -pub mod desc_to_brief_pass; -pub mod text_pass; -pub mod unindent_pass; -pub mod trim_pass; -pub mod astsrv; -pub mod demo; -pub mod sort_pass; -pub mod sort_item_name_pass; -pub mod sort_item_type_pass; -pub mod page_pass; -pub mod sectionalize_pass; -pub mod escape_pass; -pub mod prune_private_pass; -pub mod util; - -mod std { - pub use core::clone; - pub use core::cmp; - pub use core::os; - pub use core::str; - pub use core::sys; - pub use core::unstable; -} - -pub fn main() { - let args = os::args(); - - if args.iter().any_(|x| "-h" == *x) || args.iter().any_(|x| "--help" == *x) { - config::usage(); - return; - } - - let config = match config::parse_config(args) { - Ok(config) => config, - Err(err) => { - io::println(fmt!("error: %s", err)); - return; - } - }; - - run(config); -} - -/// Runs rustdoc over the given file -fn run(config: Config) { - - let source_file = copy config.input_crate; - - // Create an AST service from the source code - do astsrv::from_file(source_file.to_str()) |srv| { - - // Just time how long it takes for the AST to become available - do time(~"wait_ast") { - do astsrv::exec(srv.clone()) |_ctxt| { } - }; - - // Extract the initial doc tree from the AST. This contains - // just names and node ids. - let doc = time(~"extract", || { - let default_name = copy source_file; - extract::from_srv(srv.clone(), default_name.to_str()) - }); - - // Refine and publish the document - pass::run_passes(srv, doc, ~[ - // Generate type and signature strings - tystr_pass::mk_pass(), - // Record the full paths to various nodes - path_pass::mk_pass(), - // Extract the docs attributes and attach them to doc nodes - attr_pass::mk_pass(), - // Perform various text escaping - escape_pass::mk_pass(), - // Remove things marked doc(hidden) - prune_hidden_pass::mk_pass(), - // Remove things that are private - prune_private_pass::mk_pass(), - // Extract brief documentation from the full descriptions - desc_to_brief_pass::mk_pass(), - // Massage the text to remove extra indentation - unindent_pass::mk_pass(), - // Split text into multiple sections according to headers - sectionalize_pass::mk_pass(), - // Trim extra spaces from text - trim_pass::mk_pass(), - // Sort items by name - sort_item_name_pass::mk_pass(), - // Sort items again by kind - sort_item_type_pass::mk_pass(), - // Create indexes appropriate for markdown - markdown_index_pass::mk_pass(copy config), - // Break the document into pages if required by the - // output format - page_pass::mk_pass(config.output_style), - // Render - markdown_pass::mk_pass( - markdown_writer::make_writer_factory(copy config) - ) - ]); - } -} - -pub fn time(what: ~str, f: &fn() -> T) -> T { - let start = extra::time::precise_time_s(); - let rv = f(); - let end = extra::time::precise_time_s(); - info!("time: %3.3f s %s", end - start, what); - rv -} diff --git a/src/librustdoc/rustdoc.rs b/src/librustdoc/rustdoc.rs new file mode 100644 index 00000000000..d02620229f5 --- /dev/null +++ b/src/librustdoc/rustdoc.rs @@ -0,0 +1,162 @@ +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Rustdoc - The Rust documentation generator + +#[link(name = "rustdoc", + vers = "0.7-pre", + uuid = "f8abd014-b281-484d-a0c3-26e3de8e2412", + url = "https://github.com/mozilla/rust/tree/master/src/rustdoc")]; + +#[comment = "The Rust documentation generator"]; +#[license = "MIT/ASL2"]; +#[crate_type = "lib"]; + +#[allow(non_implicitly_copyable_typarams)]; + +#[no_std]; + +extern mod core(name = "std"); +extern mod extra(name = "extra"); + +extern mod rustc; +extern mod syntax; + +use core::prelude::*; + +use config::Config; +use doc::Item; +use doc::ItemUtils; + +use core::*; + +pub mod pass; +pub mod config; +pub mod parse; +pub mod extract; +pub mod attr_parser; +pub mod doc; +pub mod markdown_index_pass; +pub mod markdown_pass; +pub mod markdown_writer; +pub mod fold; +pub mod path_pass; +pub mod attr_pass; +pub mod tystr_pass; +pub mod prune_hidden_pass; +pub mod desc_to_brief_pass; +pub mod text_pass; +pub mod unindent_pass; +pub mod trim_pass; +pub mod astsrv; +pub mod demo; +pub mod sort_pass; +pub mod sort_item_name_pass; +pub mod sort_item_type_pass; +pub mod page_pass; +pub mod sectionalize_pass; +pub mod escape_pass; +pub mod prune_private_pass; +pub mod util; + +mod std { + pub use core::clone; + pub use core::cmp; + pub use core::os; + pub use core::str; + pub use core::sys; + pub use core::unstable; +} + +pub fn main() { + let args = os::args(); + + if args.iter().any_(|x| "-h" == *x) || args.iter().any_(|x| "--help" == *x) { + config::usage(); + return; + } + + let config = match config::parse_config(args) { + Ok(config) => config, + Err(err) => { + io::println(fmt!("error: %s", err)); + return; + } + }; + + run(config); +} + +/// Runs rustdoc over the given file +fn run(config: Config) { + + let source_file = copy config.input_crate; + + // Create an AST service from the source code + do astsrv::from_file(source_file.to_str()) |srv| { + + // Just time how long it takes for the AST to become available + do time(~"wait_ast") { + do astsrv::exec(srv.clone()) |_ctxt| { } + }; + + // Extract the initial doc tree from the AST. This contains + // just names and node ids. + let doc = time(~"extract", || { + let default_name = copy source_file; + extract::from_srv(srv.clone(), default_name.to_str()) + }); + + // Refine and publish the document + pass::run_passes(srv, doc, ~[ + // Generate type and signature strings + tystr_pass::mk_pass(), + // Record the full paths to various nodes + path_pass::mk_pass(), + // Extract the docs attributes and attach them to doc nodes + attr_pass::mk_pass(), + // Perform various text escaping + escape_pass::mk_pass(), + // Remove things marked doc(hidden) + prune_hidden_pass::mk_pass(), + // Remove things that are private + prune_private_pass::mk_pass(), + // Extract brief documentation from the full descriptions + desc_to_brief_pass::mk_pass(), + // Massage the text to remove extra indentation + unindent_pass::mk_pass(), + // Split text into multiple sections according to headers + sectionalize_pass::mk_pass(), + // Trim extra spaces from text + trim_pass::mk_pass(), + // Sort items by name + sort_item_name_pass::mk_pass(), + // Sort items again by kind + sort_item_type_pass::mk_pass(), + // Create indexes appropriate for markdown + markdown_index_pass::mk_pass(copy config), + // Break the document into pages if required by the + // output format + page_pass::mk_pass(config.output_style), + // Render + markdown_pass::mk_pass( + markdown_writer::make_writer_factory(copy config) + ) + ]); + } +} + +pub fn time(what: ~str, f: &fn() -> T) -> T { + let start = extra::time::precise_time_s(); + let rv = f(); + let end = extra::time::precise_time_s(); + info!("time: %3.3f s %s", end - start, what); + rv +} diff --git a/src/librusti/rusti.rc b/src/librusti/rusti.rc deleted file mode 100644 index 57a2a48a0f6..00000000000 --- a/src/librusti/rusti.rc +++ /dev/null @@ -1,665 +0,0 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/*! - * rusti - A REPL using the JIT backend - * - * Rusti works by serializing state between lines of input. This means that each - * line can be run in a separate task, and the only limiting factor is that all - * local bound variables are encodable. - * - * This is accomplished by feeding in generated input to rustc for execution in - * the JIT compiler. Currently input actually gets fed in three times to get - * information about the program. - * - * - Pass #1 - * In this pass, the input is simply thrown at the parser and the input comes - * back. This validates the structure of the program, and at this stage the - * global items (fns, structs, impls, traits, etc.) are filtered from the - * input into the "global namespace". These declarations shadow all previous - * declarations of an item by the same name. - * - * - Pass #2 - * After items have been stripped, the remaining input is passed to rustc - * along with all local variables declared (initialized to nothing). This pass - * runs up to typechecking. From this, we can learn about the types of each - * bound variable, what variables are bound, and also ensure that all the - * types are encodable (the input can actually be run). - * - * - Pass #3 - * Finally, a program is generated to deserialize the local variable state, - * run the code input, and then reserialize all bindings back into a local - * hash map. Once this code runs, the input has fully been run and the REPL - * waits for new input. - * - * Encoding/decoding is done with EBML, and there is simply a map of ~str -> - * ~[u8] maintaining the values of each local binding (by name). - */ - -#[link(name = "rusti", - vers = "0.7-pre", - uuid = "7fb5bf52-7d45-4fee-8325-5ad3311149fc", - url = "https://github.com/mozilla/rust/tree/master/src/rusti")]; - -#[license = "MIT/ASL2"]; -#[crate_type = "lib"]; - -extern mod extra; -extern mod rustc; -extern mod syntax; - -use std::{libc, io, os, task, vec}; -use std::cell::Cell; -use extra::rl; - -use rustc::driver::{driver, session}; -use syntax::{ast, diagnostic}; -use syntax::ast_util::*; -use syntax::parse::token; -use syntax::print::pprust; - -use program::Program; -use utils::*; - -mod program; -pub mod utils; - -/** - * A structure shared across REPL instances for storing history - * such as statements and view items. I wish the AST was sendable. - */ -pub struct Repl { - prompt: ~str, - binary: ~str, - running: bool, - lib_search_paths: ~[~str], - - program: Program, -} - -// Action to do after reading a :command -enum CmdAction { - action_none, - action_run_line(~str), -} - -/// Run an input string in a Repl, returning the new Repl. -fn run(mut repl: Repl, input: ~str) -> Repl { - // Build some necessary rustc boilerplate for compiling things - let binary = repl.binary.to_managed(); - let options = @session::options { - crate_type: session::unknown_crate, - binary: binary, - addl_lib_search_paths: @mut repl.lib_search_paths.map(|p| Path(*p)), - jit: true, - .. copy *session::basic_options() - }; - // Because we assume that everything is encodable (and assert so), add some - // extra helpful information if the error crops up. Otherwise people are - // bound to be very confused when they find out code is running that they - // never typed in... - let sess = driver::build_session(options, |cm, msg, lvl| { - diagnostic::emit(cm, msg, lvl); - if msg.contains("failed to find an implementation of trait") && - msg.contains("extra::serialize::Encodable") { - diagnostic::emit(cm, - "Currrently rusti serializes bound locals between \ - different lines of input. This means that all \ - values of local variables need to be encodable, \ - and this type isn't encodable", - diagnostic::note); - } - }); - let intr = token::get_ident_interner(); - - // - // Stage 1: parse the input and filter it into the program (as necessary) - // - debug!("parsing: %s", input); - let crate = parse_input(sess, binary, input); - let mut to_run = ~[]; // statements to run (emitted back into code) - let new_locals = @mut ~[]; // new locals being defined - let mut result = None; // resultant expression (to print via pp) - do find_main(crate, sess) |blk| { - // Fish out all the view items, be sure to record 'extern mod' items - // differently beause they must appear before all 'use' statements - for blk.node.view_items.iter().advance |vi| { - let s = do with_pp(intr) |pp, _| { - pprust::print_view_item(pp, *vi); - }; - match vi.node { - ast::view_item_extern_mod(*) => { - repl.program.record_extern(s); - } - ast::view_item_use(*) => { repl.program.record_view_item(s); } - } - } - - // Iterate through all of the block's statements, inserting them into - // the correct portions of the program - for blk.node.stmts.iter().advance |stmt| { - let s = do with_pp(intr) |pp, _| { pprust::print_stmt(pp, *stmt); }; - match stmt.node { - ast::stmt_decl(d, _) => { - match d.node { - ast::decl_item(it) => { - let name = sess.str_of(it.ident); - match it.node { - // Structs are treated specially because to make - // them at all usable they need to be decorated - // with #[deriving(Encoable, Decodable)] - ast::item_struct(*) => { - repl.program.record_struct(name, s); - } - // Item declarations are hoisted out of main() - _ => { repl.program.record_item(name, s); } - } - } - - // Local declarations must be specially dealt with, - // record all local declarations for use later on - ast::decl_local(l) => { - let mutbl = l.node.is_mutbl; - do each_binding(l) |path, _| { - let s = do with_pp(intr) |pp, _| { - pprust::print_path(pp, path, false); - }; - new_locals.push((s, mutbl)); - } - to_run.push(s); - } - } - } - - // run statements with expressions (they have effects) - ast::stmt_mac(*) | ast::stmt_semi(*) | ast::stmt_expr(*) => { - to_run.push(s); - } - } - } - result = do blk.node.expr.map_consume |e| { - do with_pp(intr) |pp, _| { pprust::print_expr(pp, e); } - }; - } - // return fast for empty inputs - if to_run.len() == 0 && result.is_none() { - return repl; - } - - // - // Stage 2: run everything up to typeck to learn the types of the new - // variables introduced into the program - // - info!("Learning about the new types in the program"); - repl.program.set_cache(); // before register_new_vars (which changes them) - let input = to_run.connect("\n"); - let test = repl.program.test_code(input, &result, *new_locals); - debug!("testing with ^^^^^^ %?", (||{ println(test) })()); - let dinput = driver::str_input(test.to_managed()); - let cfg = driver::build_configuration(sess, binary, &dinput); - let outputs = driver::build_output_filenames(&dinput, &None, &None, [], sess); - let (crate, tcx) = driver::compile_upto(sess, copy cfg, &dinput, - driver::cu_typeck, Some(outputs)); - // Once we're typechecked, record the types of all local variables defined - // in this input - do find_main(crate.expect("crate after cu_typeck"), sess) |blk| { - repl.program.register_new_vars(blk, tcx.expect("tcx after cu_typeck")); - } - - // - // Stage 3: Actually run the code in the JIT - // - info!("actually running code"); - let code = repl.program.code(input, &result); - debug!("actually running ^^^^^^ %?", (||{ println(code) })()); - let input = driver::str_input(code.to_managed()); - let cfg = driver::build_configuration(sess, binary, &input); - let outputs = driver::build_output_filenames(&input, &None, &None, [], sess); - let sess = driver::build_session(options, diagnostic::emit); - driver::compile_upto(sess, cfg, &input, driver::cu_everything, - Some(outputs)); - - // - // Stage 4: Inform the program that computation is done so it can update all - // local variable bindings. - // - info!("cleaning up after code"); - repl.program.consume_cache(); - - return repl; - - fn parse_input(sess: session::Session, binary: @str, - input: &str) -> @ast::crate { - let code = fmt!("fn main() {\n %s \n}", input); - let input = driver::str_input(code.to_managed()); - let cfg = driver::build_configuration(sess, binary, &input); - let outputs = driver::build_output_filenames(&input, &None, &None, [], sess); - let (crate, _) = driver::compile_upto(sess, cfg, &input, - driver::cu_parse, Some(outputs)); - crate.expect("parsing should return a crate") - } - - fn find_main(crate: @ast::crate, sess: session::Session, - f: &fn(&ast::blk)) { - for crate.node.module.items.iter().advance |item| { - match item.node { - ast::item_fn(_, _, _, _, ref blk) => { - if item.ident == sess.ident_of("main") { - return f(blk); - } - } - _ => {} - } - } - fail!("main function was expected somewhere..."); - } -} - -// Compiles a crate given by the filename as a library if the compiled -// version doesn't exist or is older than the source file. Binary is -// the name of the compiling executable. Returns Some(true) if it -// successfully compiled, Some(false) if the crate wasn't compiled -// because it already exists and is newer than the source file, or -// None if there were compile errors. -fn compile_crate(src_filename: ~str, binary: ~str) -> Option { - match do task::try { - let src_path = Path(src_filename); - let binary = binary.to_managed(); - let options = @session::options { - binary: binary, - addl_lib_search_paths: @mut ~[os::getcwd()], - .. copy *session::basic_options() - }; - let input = driver::file_input(copy src_path); - let sess = driver::build_session(options, diagnostic::emit); - *sess.building_library = true; - let cfg = driver::build_configuration(sess, binary, &input); - let outputs = driver::build_output_filenames( - &input, &None, &None, [], sess); - // If the library already exists and is newer than the source - // file, skip compilation and return None. - let mut should_compile = true; - let dir = os::list_dir_path(&Path(outputs.out_filename.dirname())); - let maybe_lib_path = do dir.iter().find_ |file| { - // The actual file's name has a hash value and version - // number in it which is unknown at this time, so looking - // for a file that matches out_filename won't work, - // instead we guess which file is the library by matching - // the prefix and suffix of out_filename to files in the - // directory. - let file_str = file.filename().get(); - file_str.starts_with(outputs.out_filename.filestem().get()) - && file_str.ends_with(outputs.out_filename.filetype().get()) - }; - match maybe_lib_path { - Some(lib_path) => { - let (src_mtime, _) = src_path.get_mtime().get(); - let (lib_mtime, _) = lib_path.get_mtime().get(); - if lib_mtime >= src_mtime { - should_compile = false; - } - }, - None => { }, - } - if (should_compile) { - println(fmt!("compiling %s...", src_filename)); - driver::compile_upto(sess, cfg, &input, driver::cu_everything, - Some(outputs)); - true - } else { false } - } { - Ok(true) => Some(true), - Ok(false) => Some(false), - Err(_) => None, - } -} - -/// Tries to get a line from rl after outputting a prompt. Returns -/// None if no input was read (e.g. EOF was reached). -fn get_line(use_rl: bool, prompt: &str) -> Option<~str> { - if use_rl { - let result = unsafe { rl::read(prompt) }; - - match result { - None => None, - Some(line) => { - unsafe { rl::add_history(line) }; - Some(line) - } - } - } else { - if io::stdin().eof() { - None - } else { - Some(io::stdin().read_line()) - } - } -} - -/// Run a command, e.g. :clear, :exit, etc. -fn run_cmd(repl: &mut Repl, _in: @io::Reader, _out: @io::Writer, - cmd: ~str, args: ~[~str], use_rl: bool) -> CmdAction { - let mut action = action_none; - match cmd { - ~"exit" => repl.running = false, - ~"clear" => { - repl.program.clear(); - - // XXX: Win32 version of linenoise can't do this - //rl::clear(); - } - ~"help" => { - println( - ":{\\n ..lines.. \\n:}\\n - execute multiline command\n\ - :load ... - loads given crates as dynamic libraries\n\ - :clear - clear the bindings\n\ - :exit - exit from the repl\n\ - :help - show this message"); - } - ~"load" => { - let mut loaded_crates: ~[~str] = ~[]; - for args.iter().advance |arg| { - let (crate, filename) = - if arg.ends_with(".rs") || arg.ends_with(".rc") { - (arg.slice_to(arg.len() - 3).to_owned(), copy *arg) - } else { - (copy *arg, *arg + ".rs") - }; - match compile_crate(filename, copy repl.binary) { - Some(_) => loaded_crates.push(crate), - None => { } - } - } - for loaded_crates.iter().advance |crate| { - let crate_path = Path(*crate); - let crate_dir = crate_path.dirname(); - repl.program.record_extern(fmt!("extern mod %s;", *crate)); - if !repl.lib_search_paths.iter().any_(|x| x == &crate_dir) { - repl.lib_search_paths.push(crate_dir); - } - } - if loaded_crates.is_empty() { - println("no crates loaded"); - } else { - println(fmt!("crates loaded: %s", - loaded_crates.connect(", "))); - } - } - ~"{" => { - let mut multiline_cmd = ~""; - let mut end_multiline = false; - while (!end_multiline) { - match get_line(use_rl, "rusti| ") { - None => fail!("unterminated multiline command :{ .. :}"), - Some(line) => { - if line.trim() == ":}" { - end_multiline = true; - } else { - multiline_cmd += line + "\n"; - } - } - } - } - action = action_run_line(multiline_cmd); - } - _ => println(~"unknown cmd: " + cmd) - } - return action; -} - -/// Executes a line of input, which may either be rust code or a -/// :command. Returns a new Repl if it has changed. -pub fn run_line(repl: &mut Repl, in: @io::Reader, out: @io::Writer, line: ~str, - use_rl: bool) - -> Option { - if line.starts_with(":") { - // drop the : and the \n (one byte each) - let full = line.slice(1, line.len()); - let split: ~[~str] = full.word_iter().transform(|s| s.to_owned()).collect(); - let len = split.len(); - - if len > 0 { - let cmd = copy split[0]; - - if !cmd.is_empty() { - let args = if len > 1 { - vec::slice(split, 1, len).to_owned() - } else { ~[] }; - - match run_cmd(repl, in, out, cmd, args, use_rl) { - action_none => { } - action_run_line(multiline_cmd) => { - if !multiline_cmd.is_empty() { - return run_line(repl, in, out, multiline_cmd, use_rl); - } - } - } - return None; - } - } - } - - let line = Cell::new(line); - let r = Cell::new(copy *repl); - let result = do task::try { - run(r.take(), line.take()) - }; - - if result.is_ok() { - return Some(result.get()); - } - return None; -} - -pub fn main() { - let args = os::args(); - let in = io::stdin(); - let out = io::stdout(); - let mut repl = Repl { - prompt: ~"rusti> ", - binary: copy args[0], - running: true, - lib_search_paths: ~[], - - program: Program::new(), - }; - - let istty = unsafe { libc::isatty(libc::STDIN_FILENO as i32) } != 0; - - // only print this stuff if the user is actually typing into rusti - if istty { - println("WARNING: The Rust REPL is experimental and may be"); - println("unstable. If you encounter problems, please use the"); - println("compiler instead. Type :help for help."); - - unsafe { - do rl::complete |line, suggest| { - if line.starts_with(":") { - suggest(~":clear"); - suggest(~":exit"); - suggest(~":help"); - suggest(~":load"); - } - } - } - } - - while repl.running { - match get_line(istty, repl.prompt) { - None => break, - Some(line) => { - if line.is_empty() { - if istty { - println("()"); - } - loop; - } - match run_line(&mut repl, in, out, line, istty) { - Some(new_repl) => repl = new_repl, - None => { } - } - } - } - } -} - -#[cfg(test)] -mod tests { - use std::io; - use std::iterator::IteratorUtil; - use program::Program; - use super::*; - - fn repl() -> Repl { - Repl { - prompt: ~"rusti> ", - binary: ~"rusti", - running: true, - lib_search_paths: ~[], - program: Program::new(), - } - } - - fn run_program(prog: &str) { - let mut r = repl(); - for prog.split_iter('\n').advance |cmd| { - let result = run_line(&mut r, io::stdin(), io::stdout(), - cmd.to_owned(), false); - r = result.expect(fmt!("the command '%s' failed", cmd)); - } - } - - #[test] - // FIXME: #7220 rusti on 32bit mac doesn't work. - #[cfg(not(target_word_size="32", - target_os="macos"))] - fn run_all() { - // FIXME(#7071): - // By default, unit tests are run in parallel. Rusti, on the other hand, - // does not enjoy doing this. I suspect that it is because the LLVM - // bindings are not thread-safe (when running parallel tests, some tests - // were triggering assertions in LLVM (or segfaults). Hence, this - // function exists to run everything serially (sadface). - // - // To get some interesting output, run with RUST_LOG=rusti::tests - - debug!("hopefully this runs"); - run_program(""); - - debug!("regression test for #5937"); - run_program("use std::hashmap;"); - - debug!("regression test for #5784"); - run_program("let a = 3;"); - - // XXX: can't spawn new tasks because the JIT code is cleaned up - // after the main function is done. - // debug!("regression test for #5803"); - // run_program(" - // spawn( || println(\"Please don't segfault\") ); - // do spawn { println(\"Please?\"); } - // "); - - debug!("inferred integers are usable"); - run_program("let a = 2;\n()\n"); - run_program(" - let a = 3; - let b = 4u; - assert!((a as uint) + b == 7) - "); - - debug!("local variables can be shadowed"); - run_program(" - let a = 3; - let a = 5; - assert!(a == 5) - "); - - debug!("strings are usable"); - run_program(" - let a = ~\"\"; - let b = \"\"; - let c = @\"\"; - let d = a + b + c; - assert!(d.len() == 0); - "); - - debug!("vectors are usable"); - run_program(" - let a = ~[1, 2, 3]; - let b = &[1, 2, 3]; - let c = @[1, 2, 3]; - let d = a + b + c; - assert!(d.len() == 9); - let e: &[int] = []; - "); - - debug!("structs are usable"); - run_program(" - struct A{ a: int } - let b = A{ a: 3 }; - assert!(b.a == 3) - "); - - debug!("mutable variables"); - run_program(" - let mut a = 3; - a = 5; - let mut b = std::hashmap::HashSet::new::(); - b.insert(a); - assert!(b.contains(&5)) - assert!(b.len() == 1) - "); - - debug!("functions are cached"); - run_program(" - fn fib(x: int) -> int { if x < 2 {x} else { fib(x - 1) + fib(x - 2) } } - let a = fib(3); - let a = a + fib(4); - assert!(a == 5) - "); - - debug!("modules are cached"); - run_program(" - mod b { pub fn foo() -> uint { 3 } } - assert!(b::foo() == 3) - "); - - debug!("multiple function definitions are allowed"); - run_program(" - fn f() {} - fn f() {} - f() - "); - - debug!("multiple item definitions are allowed"); - run_program(" - fn f() {} - mod f {} - struct f; - enum f {} - fn f() {} - f() - "); - } - - #[test] - // FIXME: #7220 rusti on 32bit mac doesn't work. - #[cfg(not(target_word_size="32", - target_os="macos"))] - fn exit_quits() { - let mut r = repl(); - assert!(r.running); - let result = run_line(&mut r, io::stdin(), io::stdout(), - ~":exit", false); - assert!(result.is_none()); - assert!(!r.running); - } -} diff --git a/src/librusti/rusti.rs b/src/librusti/rusti.rs new file mode 100644 index 00000000000..57a2a48a0f6 --- /dev/null +++ b/src/librusti/rusti.rs @@ -0,0 +1,665 @@ +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/*! + * rusti - A REPL using the JIT backend + * + * Rusti works by serializing state between lines of input. This means that each + * line can be run in a separate task, and the only limiting factor is that all + * local bound variables are encodable. + * + * This is accomplished by feeding in generated input to rustc for execution in + * the JIT compiler. Currently input actually gets fed in three times to get + * information about the program. + * + * - Pass #1 + * In this pass, the input is simply thrown at the parser and the input comes + * back. This validates the structure of the program, and at this stage the + * global items (fns, structs, impls, traits, etc.) are filtered from the + * input into the "global namespace". These declarations shadow all previous + * declarations of an item by the same name. + * + * - Pass #2 + * After items have been stripped, the remaining input is passed to rustc + * along with all local variables declared (initialized to nothing). This pass + * runs up to typechecking. From this, we can learn about the types of each + * bound variable, what variables are bound, and also ensure that all the + * types are encodable (the input can actually be run). + * + * - Pass #3 + * Finally, a program is generated to deserialize the local variable state, + * run the code input, and then reserialize all bindings back into a local + * hash map. Once this code runs, the input has fully been run and the REPL + * waits for new input. + * + * Encoding/decoding is done with EBML, and there is simply a map of ~str -> + * ~[u8] maintaining the values of each local binding (by name). + */ + +#[link(name = "rusti", + vers = "0.7-pre", + uuid = "7fb5bf52-7d45-4fee-8325-5ad3311149fc", + url = "https://github.com/mozilla/rust/tree/master/src/rusti")]; + +#[license = "MIT/ASL2"]; +#[crate_type = "lib"]; + +extern mod extra; +extern mod rustc; +extern mod syntax; + +use std::{libc, io, os, task, vec}; +use std::cell::Cell; +use extra::rl; + +use rustc::driver::{driver, session}; +use syntax::{ast, diagnostic}; +use syntax::ast_util::*; +use syntax::parse::token; +use syntax::print::pprust; + +use program::Program; +use utils::*; + +mod program; +pub mod utils; + +/** + * A structure shared across REPL instances for storing history + * such as statements and view items. I wish the AST was sendable. + */ +pub struct Repl { + prompt: ~str, + binary: ~str, + running: bool, + lib_search_paths: ~[~str], + + program: Program, +} + +// Action to do after reading a :command +enum CmdAction { + action_none, + action_run_line(~str), +} + +/// Run an input string in a Repl, returning the new Repl. +fn run(mut repl: Repl, input: ~str) -> Repl { + // Build some necessary rustc boilerplate for compiling things + let binary = repl.binary.to_managed(); + let options = @session::options { + crate_type: session::unknown_crate, + binary: binary, + addl_lib_search_paths: @mut repl.lib_search_paths.map(|p| Path(*p)), + jit: true, + .. copy *session::basic_options() + }; + // Because we assume that everything is encodable (and assert so), add some + // extra helpful information if the error crops up. Otherwise people are + // bound to be very confused when they find out code is running that they + // never typed in... + let sess = driver::build_session(options, |cm, msg, lvl| { + diagnostic::emit(cm, msg, lvl); + if msg.contains("failed to find an implementation of trait") && + msg.contains("extra::serialize::Encodable") { + diagnostic::emit(cm, + "Currrently rusti serializes bound locals between \ + different lines of input. This means that all \ + values of local variables need to be encodable, \ + and this type isn't encodable", + diagnostic::note); + } + }); + let intr = token::get_ident_interner(); + + // + // Stage 1: parse the input and filter it into the program (as necessary) + // + debug!("parsing: %s", input); + let crate = parse_input(sess, binary, input); + let mut to_run = ~[]; // statements to run (emitted back into code) + let new_locals = @mut ~[]; // new locals being defined + let mut result = None; // resultant expression (to print via pp) + do find_main(crate, sess) |blk| { + // Fish out all the view items, be sure to record 'extern mod' items + // differently beause they must appear before all 'use' statements + for blk.node.view_items.iter().advance |vi| { + let s = do with_pp(intr) |pp, _| { + pprust::print_view_item(pp, *vi); + }; + match vi.node { + ast::view_item_extern_mod(*) => { + repl.program.record_extern(s); + } + ast::view_item_use(*) => { repl.program.record_view_item(s); } + } + } + + // Iterate through all of the block's statements, inserting them into + // the correct portions of the program + for blk.node.stmts.iter().advance |stmt| { + let s = do with_pp(intr) |pp, _| { pprust::print_stmt(pp, *stmt); }; + match stmt.node { + ast::stmt_decl(d, _) => { + match d.node { + ast::decl_item(it) => { + let name = sess.str_of(it.ident); + match it.node { + // Structs are treated specially because to make + // them at all usable they need to be decorated + // with #[deriving(Encoable, Decodable)] + ast::item_struct(*) => { + repl.program.record_struct(name, s); + } + // Item declarations are hoisted out of main() + _ => { repl.program.record_item(name, s); } + } + } + + // Local declarations must be specially dealt with, + // record all local declarations for use later on + ast::decl_local(l) => { + let mutbl = l.node.is_mutbl; + do each_binding(l) |path, _| { + let s = do with_pp(intr) |pp, _| { + pprust::print_path(pp, path, false); + }; + new_locals.push((s, mutbl)); + } + to_run.push(s); + } + } + } + + // run statements with expressions (they have effects) + ast::stmt_mac(*) | ast::stmt_semi(*) | ast::stmt_expr(*) => { + to_run.push(s); + } + } + } + result = do blk.node.expr.map_consume |e| { + do with_pp(intr) |pp, _| { pprust::print_expr(pp, e); } + }; + } + // return fast for empty inputs + if to_run.len() == 0 && result.is_none() { + return repl; + } + + // + // Stage 2: run everything up to typeck to learn the types of the new + // variables introduced into the program + // + info!("Learning about the new types in the program"); + repl.program.set_cache(); // before register_new_vars (which changes them) + let input = to_run.connect("\n"); + let test = repl.program.test_code(input, &result, *new_locals); + debug!("testing with ^^^^^^ %?", (||{ println(test) })()); + let dinput = driver::str_input(test.to_managed()); + let cfg = driver::build_configuration(sess, binary, &dinput); + let outputs = driver::build_output_filenames(&dinput, &None, &None, [], sess); + let (crate, tcx) = driver::compile_upto(sess, copy cfg, &dinput, + driver::cu_typeck, Some(outputs)); + // Once we're typechecked, record the types of all local variables defined + // in this input + do find_main(crate.expect("crate after cu_typeck"), sess) |blk| { + repl.program.register_new_vars(blk, tcx.expect("tcx after cu_typeck")); + } + + // + // Stage 3: Actually run the code in the JIT + // + info!("actually running code"); + let code = repl.program.code(input, &result); + debug!("actually running ^^^^^^ %?", (||{ println(code) })()); + let input = driver::str_input(code.to_managed()); + let cfg = driver::build_configuration(sess, binary, &input); + let outputs = driver::build_output_filenames(&input, &None, &None, [], sess); + let sess = driver::build_session(options, diagnostic::emit); + driver::compile_upto(sess, cfg, &input, driver::cu_everything, + Some(outputs)); + + // + // Stage 4: Inform the program that computation is done so it can update all + // local variable bindings. + // + info!("cleaning up after code"); + repl.program.consume_cache(); + + return repl; + + fn parse_input(sess: session::Session, binary: @str, + input: &str) -> @ast::crate { + let code = fmt!("fn main() {\n %s \n}", input); + let input = driver::str_input(code.to_managed()); + let cfg = driver::build_configuration(sess, binary, &input); + let outputs = driver::build_output_filenames(&input, &None, &None, [], sess); + let (crate, _) = driver::compile_upto(sess, cfg, &input, + driver::cu_parse, Some(outputs)); + crate.expect("parsing should return a crate") + } + + fn find_main(crate: @ast::crate, sess: session::Session, + f: &fn(&ast::blk)) { + for crate.node.module.items.iter().advance |item| { + match item.node { + ast::item_fn(_, _, _, _, ref blk) => { + if item.ident == sess.ident_of("main") { + return f(blk); + } + } + _ => {} + } + } + fail!("main function was expected somewhere..."); + } +} + +// Compiles a crate given by the filename as a library if the compiled +// version doesn't exist or is older than the source file. Binary is +// the name of the compiling executable. Returns Some(true) if it +// successfully compiled, Some(false) if the crate wasn't compiled +// because it already exists and is newer than the source file, or +// None if there were compile errors. +fn compile_crate(src_filename: ~str, binary: ~str) -> Option { + match do task::try { + let src_path = Path(src_filename); + let binary = binary.to_managed(); + let options = @session::options { + binary: binary, + addl_lib_search_paths: @mut ~[os::getcwd()], + .. copy *session::basic_options() + }; + let input = driver::file_input(copy src_path); + let sess = driver::build_session(options, diagnostic::emit); + *sess.building_library = true; + let cfg = driver::build_configuration(sess, binary, &input); + let outputs = driver::build_output_filenames( + &input, &None, &None, [], sess); + // If the library already exists and is newer than the source + // file, skip compilation and return None. + let mut should_compile = true; + let dir = os::list_dir_path(&Path(outputs.out_filename.dirname())); + let maybe_lib_path = do dir.iter().find_ |file| { + // The actual file's name has a hash value and version + // number in it which is unknown at this time, so looking + // for a file that matches out_filename won't work, + // instead we guess which file is the library by matching + // the prefix and suffix of out_filename to files in the + // directory. + let file_str = file.filename().get(); + file_str.starts_with(outputs.out_filename.filestem().get()) + && file_str.ends_with(outputs.out_filename.filetype().get()) + }; + match maybe_lib_path { + Some(lib_path) => { + let (src_mtime, _) = src_path.get_mtime().get(); + let (lib_mtime, _) = lib_path.get_mtime().get(); + if lib_mtime >= src_mtime { + should_compile = false; + } + }, + None => { }, + } + if (should_compile) { + println(fmt!("compiling %s...", src_filename)); + driver::compile_upto(sess, cfg, &input, driver::cu_everything, + Some(outputs)); + true + } else { false } + } { + Ok(true) => Some(true), + Ok(false) => Some(false), + Err(_) => None, + } +} + +/// Tries to get a line from rl after outputting a prompt. Returns +/// None if no input was read (e.g. EOF was reached). +fn get_line(use_rl: bool, prompt: &str) -> Option<~str> { + if use_rl { + let result = unsafe { rl::read(prompt) }; + + match result { + None => None, + Some(line) => { + unsafe { rl::add_history(line) }; + Some(line) + } + } + } else { + if io::stdin().eof() { + None + } else { + Some(io::stdin().read_line()) + } + } +} + +/// Run a command, e.g. :clear, :exit, etc. +fn run_cmd(repl: &mut Repl, _in: @io::Reader, _out: @io::Writer, + cmd: ~str, args: ~[~str], use_rl: bool) -> CmdAction { + let mut action = action_none; + match cmd { + ~"exit" => repl.running = false, + ~"clear" => { + repl.program.clear(); + + // XXX: Win32 version of linenoise can't do this + //rl::clear(); + } + ~"help" => { + println( + ":{\\n ..lines.. \\n:}\\n - execute multiline command\n\ + :load ... - loads given crates as dynamic libraries\n\ + :clear - clear the bindings\n\ + :exit - exit from the repl\n\ + :help - show this message"); + } + ~"load" => { + let mut loaded_crates: ~[~str] = ~[]; + for args.iter().advance |arg| { + let (crate, filename) = + if arg.ends_with(".rs") || arg.ends_with(".rc") { + (arg.slice_to(arg.len() - 3).to_owned(), copy *arg) + } else { + (copy *arg, *arg + ".rs") + }; + match compile_crate(filename, copy repl.binary) { + Some(_) => loaded_crates.push(crate), + None => { } + } + } + for loaded_crates.iter().advance |crate| { + let crate_path = Path(*crate); + let crate_dir = crate_path.dirname(); + repl.program.record_extern(fmt!("extern mod %s;", *crate)); + if !repl.lib_search_paths.iter().any_(|x| x == &crate_dir) { + repl.lib_search_paths.push(crate_dir); + } + } + if loaded_crates.is_empty() { + println("no crates loaded"); + } else { + println(fmt!("crates loaded: %s", + loaded_crates.connect(", "))); + } + } + ~"{" => { + let mut multiline_cmd = ~""; + let mut end_multiline = false; + while (!end_multiline) { + match get_line(use_rl, "rusti| ") { + None => fail!("unterminated multiline command :{ .. :}"), + Some(line) => { + if line.trim() == ":}" { + end_multiline = true; + } else { + multiline_cmd += line + "\n"; + } + } + } + } + action = action_run_line(multiline_cmd); + } + _ => println(~"unknown cmd: " + cmd) + } + return action; +} + +/// Executes a line of input, which may either be rust code or a +/// :command. Returns a new Repl if it has changed. +pub fn run_line(repl: &mut Repl, in: @io::Reader, out: @io::Writer, line: ~str, + use_rl: bool) + -> Option { + if line.starts_with(":") { + // drop the : and the \n (one byte each) + let full = line.slice(1, line.len()); + let split: ~[~str] = full.word_iter().transform(|s| s.to_owned()).collect(); + let len = split.len(); + + if len > 0 { + let cmd = copy split[0]; + + if !cmd.is_empty() { + let args = if len > 1 { + vec::slice(split, 1, len).to_owned() + } else { ~[] }; + + match run_cmd(repl, in, out, cmd, args, use_rl) { + action_none => { } + action_run_line(multiline_cmd) => { + if !multiline_cmd.is_empty() { + return run_line(repl, in, out, multiline_cmd, use_rl); + } + } + } + return None; + } + } + } + + let line = Cell::new(line); + let r = Cell::new(copy *repl); + let result = do task::try { + run(r.take(), line.take()) + }; + + if result.is_ok() { + return Some(result.get()); + } + return None; +} + +pub fn main() { + let args = os::args(); + let in = io::stdin(); + let out = io::stdout(); + let mut repl = Repl { + prompt: ~"rusti> ", + binary: copy args[0], + running: true, + lib_search_paths: ~[], + + program: Program::new(), + }; + + let istty = unsafe { libc::isatty(libc::STDIN_FILENO as i32) } != 0; + + // only print this stuff if the user is actually typing into rusti + if istty { + println("WARNING: The Rust REPL is experimental and may be"); + println("unstable. If you encounter problems, please use the"); + println("compiler instead. Type :help for help."); + + unsafe { + do rl::complete |line, suggest| { + if line.starts_with(":") { + suggest(~":clear"); + suggest(~":exit"); + suggest(~":help"); + suggest(~":load"); + } + } + } + } + + while repl.running { + match get_line(istty, repl.prompt) { + None => break, + Some(line) => { + if line.is_empty() { + if istty { + println("()"); + } + loop; + } + match run_line(&mut repl, in, out, line, istty) { + Some(new_repl) => repl = new_repl, + None => { } + } + } + } + } +} + +#[cfg(test)] +mod tests { + use std::io; + use std::iterator::IteratorUtil; + use program::Program; + use super::*; + + fn repl() -> Repl { + Repl { + prompt: ~"rusti> ", + binary: ~"rusti", + running: true, + lib_search_paths: ~[], + program: Program::new(), + } + } + + fn run_program(prog: &str) { + let mut r = repl(); + for prog.split_iter('\n').advance |cmd| { + let result = run_line(&mut r, io::stdin(), io::stdout(), + cmd.to_owned(), false); + r = result.expect(fmt!("the command '%s' failed", cmd)); + } + } + + #[test] + // FIXME: #7220 rusti on 32bit mac doesn't work. + #[cfg(not(target_word_size="32", + target_os="macos"))] + fn run_all() { + // FIXME(#7071): + // By default, unit tests are run in parallel. Rusti, on the other hand, + // does not enjoy doing this. I suspect that it is because the LLVM + // bindings are not thread-safe (when running parallel tests, some tests + // were triggering assertions in LLVM (or segfaults). Hence, this + // function exists to run everything serially (sadface). + // + // To get some interesting output, run with RUST_LOG=rusti::tests + + debug!("hopefully this runs"); + run_program(""); + + debug!("regression test for #5937"); + run_program("use std::hashmap;"); + + debug!("regression test for #5784"); + run_program("let a = 3;"); + + // XXX: can't spawn new tasks because the JIT code is cleaned up + // after the main function is done. + // debug!("regression test for #5803"); + // run_program(" + // spawn( || println(\"Please don't segfault\") ); + // do spawn { println(\"Please?\"); } + // "); + + debug!("inferred integers are usable"); + run_program("let a = 2;\n()\n"); + run_program(" + let a = 3; + let b = 4u; + assert!((a as uint) + b == 7) + "); + + debug!("local variables can be shadowed"); + run_program(" + let a = 3; + let a = 5; + assert!(a == 5) + "); + + debug!("strings are usable"); + run_program(" + let a = ~\"\"; + let b = \"\"; + let c = @\"\"; + let d = a + b + c; + assert!(d.len() == 0); + "); + + debug!("vectors are usable"); + run_program(" + let a = ~[1, 2, 3]; + let b = &[1, 2, 3]; + let c = @[1, 2, 3]; + let d = a + b + c; + assert!(d.len() == 9); + let e: &[int] = []; + "); + + debug!("structs are usable"); + run_program(" + struct A{ a: int } + let b = A{ a: 3 }; + assert!(b.a == 3) + "); + + debug!("mutable variables"); + run_program(" + let mut a = 3; + a = 5; + let mut b = std::hashmap::HashSet::new::(); + b.insert(a); + assert!(b.contains(&5)) + assert!(b.len() == 1) + "); + + debug!("functions are cached"); + run_program(" + fn fib(x: int) -> int { if x < 2 {x} else { fib(x - 1) + fib(x - 2) } } + let a = fib(3); + let a = a + fib(4); + assert!(a == 5) + "); + + debug!("modules are cached"); + run_program(" + mod b { pub fn foo() -> uint { 3 } } + assert!(b::foo() == 3) + "); + + debug!("multiple function definitions are allowed"); + run_program(" + fn f() {} + fn f() {} + f() + "); + + debug!("multiple item definitions are allowed"); + run_program(" + fn f() {} + mod f {} + struct f; + enum f {} + fn f() {} + f() + "); + } + + #[test] + // FIXME: #7220 rusti on 32bit mac doesn't work. + #[cfg(not(target_word_size="32", + target_os="macos"))] + fn exit_quits() { + let mut r = repl(); + assert!(r.running); + let result = run_line(&mut r, io::stdin(), io::stdout(), + ~":exit", false); + assert!(result.is_none()); + assert!(!r.running); + } +} diff --git a/src/librustpkg/rustpkg.rc b/src/librustpkg/rustpkg.rc deleted file mode 100644 index 9242e450e24..00000000000 --- a/src/librustpkg/rustpkg.rc +++ /dev/null @@ -1,474 +0,0 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// rustpkg - a package manager and build system for Rust - -#[link(name = "rustpkg", - vers = "0.7-pre", - uuid = "25de5e6e-279e-4a20-845c-4cabae92daaf", - url = "https://github.com/mozilla/rust/tree/master/src/librustpkg")]; - -#[license = "MIT/ASL2"]; -#[crate_type = "lib"]; - -#[no_core]; -#[no_std]; - -extern mod core(name = "std"); -extern mod extra(name = "extra"); - -extern mod rustc; -extern mod syntax; - -use core::prelude::*; -use core::*; -pub use core::path::Path; -use core::hashmap::HashMap; -use rustc::driver::{driver, session}; -use rustc::metadata::filesearch; -use extra::{getopts}; -use syntax::{ast, diagnostic}; -use util::*; -use messages::*; -use path_util::{build_pkg_id_in_workspace, first_pkgid_src_in_workspace}; -use path_util::{u_rwx, rust_path}; -use path_util::{built_executable_in_workspace, built_library_in_workspace}; -use path_util::{target_executable_in_workspace, target_library_in_workspace}; -use workspace::{each_pkg_parent_workspace, pkg_parent_workspaces}; -use context::Ctx; -use package_id::PkgId; -use package_source::PkgSrc; - -mod conditions; -mod context; -mod crate; -mod messages; -mod package_id; -mod package_path; -mod package_source; -mod path_util; -mod search; -mod target; -#[cfg(test)] -mod tests; -mod util; -mod version; -mod workspace; - -pub mod usage; - -mod std { - pub use core::cmp; - pub use core::condition; - pub use core::os; - pub use core::str; - pub use core::sys; - pub use core::unstable; -} - -/// A PkgScript represents user-supplied custom logic for -/// special build hooks. This only exists for packages with -/// an explicit package script. -struct PkgScript<'self> { - /// Uniquely identifies this package - id: &'self PkgId, - // Used to have this field: deps: ~[(~str, Option<~str>)] - // but I think it shouldn't be stored here - /// The contents of the package script: either a file path, - /// or a string containing the text of the input - input: driver::input, - /// The session to use *only* for compiling the custom - /// build script - sess: session::Session, - /// The config for compiling the custom build script - cfg: ast::crate_cfg, - /// The crate for the custom build script - crate: @ast::crate, - /// Directory in which to store build output - build_dir: Path -} - -impl<'self> PkgScript<'self> { - /// Given the path name for a package script - /// and a package ID, parse the package script into - /// a PkgScript that we can then execute - fn parse<'a>(script: Path, workspace: &Path, id: &'a PkgId) -> PkgScript<'a> { - // Get the executable name that was invoked - let binary = os::args()[0].to_managed(); - // Build the rustc session data structures to pass - // to the compiler - let options = @session::options { - binary: binary, - crate_type: session::bin_crate, - .. copy *session::basic_options() - }; - let input = driver::file_input(script); - let sess = driver::build_session(options, diagnostic::emit); - let cfg = driver::build_configuration(sess, binary, &input); - let (crate, _) = driver::compile_upto(sess, copy cfg, &input, driver::cu_parse, None); - let work_dir = build_pkg_id_in_workspace(id, workspace); - - debug!("Returning package script with id %?", id); - - PkgScript { - id: id, - input: input, - sess: sess, - cfg: cfg, - crate: crate.unwrap(), - build_dir: work_dir - } - } - - /// Run the contents of this package script, where - /// is the command to pass to it (e.g., "build", "clean", "install") - /// Returns a pair of an exit code and list of configs (obtained by - /// calling the package script's configs() function if it exists - // FIXME (#4432): Use workcache to only compile the script when changed - fn run_custom(&self, what: ~str) -> (~[~str], ExitCode) { - debug!("run_custom: %s", what); - let sess = self.sess; - - debug!("Working directory = %s", self.build_dir.to_str()); - // Collect together any user-defined commands in the package script - let crate = util::ready_crate(sess, self.crate); - debug!("Building output filenames with script name %s", - driver::source_name(&self.input)); - match filesearch::get_rustpkg_sysroot() { - Ok(r) => { - let root = r.pop().pop().pop().pop(); // :-\ - debug!("Root is %s, calling compile_rest", root.to_str()); - let exe = self.build_dir.push(~"pkg" + util::exe_suffix()); - let binary = os::args()[0].to_managed(); - util::compile_crate_from_input(&self.input, - &self.build_dir, - sess, - crate, - driver::build_configuration(sess, - binary, &self.input)); - debug!("Running program: %s %s %s", exe.to_str(), root.to_str(), what); - let status = run::process_status(exe.to_str(), [root.to_str(), what]); - if status != 0 { - return (~[], status); - } - else { - debug!("Running program (configs): %s %s %s", - exe.to_str(), root.to_str(), "configs"); - let output = run::process_output(exe.to_str(), [root.to_str(), ~"configs"]); - // Run the configs() function to get the configs - let cfgs = str::from_bytes_slice(output.output).word_iter() - .transform(|w| w.to_owned()).collect(); - (cfgs, output.status) - } - } - Err(e) => { - fail!("Running package script, couldn't find rustpkg sysroot (%s)", e) - } - } - } - - fn hash(&self) -> ~str { - self.id.hash() - } - -} - -impl Ctx { - - fn run(&self, cmd: &str, args: ~[~str]) { - match cmd { - "build" => { - if args.len() < 1 { - return usage::build(); - } - // The package id is presumed to be the first command-line - // argument - let pkgid = PkgId::new(copy args[0]); - for each_pkg_parent_workspace(&pkgid) |workspace| { - self.build(workspace, &pkgid); - } - } - "clean" => { - if args.len() < 1 { - return usage::build(); - } - // The package id is presumed to be the first command-line - // argument - let pkgid = PkgId::new(copy args[0]); - let cwd = os::getcwd(); - self.clean(&cwd, &pkgid); // tjc: should use workspace, not cwd - } - "do" => { - if args.len() < 2 { - return usage::do_cmd(); - } - - self.do_cmd(copy args[0], copy args[1]); - } - "info" => { - self.info(); - } - "install" => { - if args.len() < 1 { - return usage::install(); - } - - // The package id is presumed to be the first command-line - // argument - let pkgid = PkgId::new(args[0]); - let workspaces = pkg_parent_workspaces(&pkgid); - if workspaces.is_empty() { - let rp = rust_path(); - assert!(!rp.is_empty()); - let src = PkgSrc::new(&rp[0], &build_pkg_id_in_workspace(&pkgid, &rp[0]), - &pkgid); - src.fetch_git(); - self.install(&rp[0], &pkgid); - } - else { - for each_pkg_parent_workspace(&pkgid) |workspace| { - self.install(workspace, &pkgid); - } - } - } - "prefer" => { - if args.len() < 1 { - return usage::uninstall(); - } - - self.prefer(args[0], None); - } - "test" => { - self.test(); - } - "uninstall" => { - if args.len() < 1 { - return usage::uninstall(); - } - - self.uninstall(args[0], None); - } - "unprefer" => { - if args.len() < 1 { - return usage::uninstall(); - } - - self.unprefer(args[0], None); - } - _ => fail!(fmt!("I don't know the command `%s`", cmd)) - } - } - - fn do_cmd(&self, _cmd: &str, _pkgname: &str) { - // stub - fail!("`do` not yet implemented"); - } - - fn build(&self, workspace: &Path, pkgid: &PkgId) { - debug!("build: workspace = %s pkgid = %s", workspace.to_str(), - pkgid.to_str()); - let src_dir = first_pkgid_src_in_workspace(pkgid, workspace); - let build_dir = build_pkg_id_in_workspace(pkgid, workspace); - debug!("Destination dir = %s", build_dir.to_str()); - - // Create the package source - let mut src = PkgSrc::new(workspace, &build_dir, pkgid); - debug!("Package src = %?", src); - - // Is there custom build logic? If so, use it - let pkg_src_dir = src_dir; - let mut custom = false; - debug!("Package source directory = %?", pkg_src_dir); - let cfgs = match pkg_src_dir.chain_ref(|p| src.package_script_option(p)) { - Some(package_script_path) => { - let pscript = PkgScript::parse(package_script_path, - workspace, - pkgid); - // Limited right now -- we're only running the post_build - // hook and probably fail otherwise - // also post_build should be called pre_build - let (cfgs, hook_result) = pscript.run_custom(~"post_build"); - debug!("Command return code = %?", hook_result); - if hook_result != 0 { - fail!("Error running custom build command") - } - custom = true; - // otherwise, the package script succeeded - cfgs - } - None => { - debug!("No package script, continuing"); - ~[] - } - }; - - // If there was a package script, it should have finished - // the build already. Otherwise... - if !custom { - // Find crates inside the workspace - src.find_crates(); - // Build it! - src.build(self, build_dir, cfgs); - } - } - - fn clean(&self, workspace: &Path, id: &PkgId) { - // Could also support a custom build hook in the pkg - // script for cleaning files rustpkg doesn't know about. - // Do something reasonable for now - - let dir = build_pkg_id_in_workspace(id, workspace); - note(fmt!("Cleaning package %s (removing directory %s)", - id.to_str(), dir.to_str())); - if os::path_exists(&dir) { - os::remove_dir_recursive(&dir); - note(fmt!("Removed directory %s", dir.to_str())); - } - - note(fmt!("Cleaned package %s", id.to_str())); - } - - fn info(&self) { - // stub - fail!("info not yet implemented"); - } - - fn install(&self, workspace: &Path, id: &PkgId) { - use conditions::copy_failed::cond; - - // Should use RUST_PATH in the future. - // Also should use workcache to not build if not necessary. - self.build(workspace, id); - debug!("install: workspace = %s, id = %s", workspace.to_str(), - id.to_str()); - - // Now copy stuff into the install dirs - let maybe_executable = built_executable_in_workspace(id, workspace); - let maybe_library = built_library_in_workspace(id, workspace); - let target_exec = target_executable_in_workspace(id, workspace); - let target_lib = maybe_library.map(|_p| target_library_in_workspace(id, workspace)); - - debug!("target_exec = %s target_lib = %? \ - maybe_executable = %? maybe_library = %?", - target_exec.to_str(), target_lib, - maybe_executable, maybe_library); - - for maybe_executable.iter().advance |exec| { - debug!("Copying: %s -> %s", exec.to_str(), target_exec.to_str()); - if !(os::mkdir_recursive(&target_exec.dir_path(), u_rwx) && - os::copy_file(exec, &target_exec)) { - cond.raise((copy *exec, copy target_exec)); - } - } - for maybe_library.iter().advance |lib| { - let target_lib = (copy target_lib).expect(fmt!("I built %s but apparently \ - didn't install it!", lib.to_str())); - debug!("Copying: %s -> %s", lib.to_str(), target_lib.to_str()); - if !(os::mkdir_recursive(&target_lib.dir_path(), u_rwx) && - os::copy_file(lib, &target_lib)) { - cond.raise((copy *lib, copy target_lib)); - } - } - } - - fn prefer(&self, _id: &str, _vers: Option<~str>) { - fail!("prefer not yet implemented"); - } - - fn test(&self) { - // stub - fail!("test not yet implemented"); - } - - fn uninstall(&self, _id: &str, _vers: Option<~str>) { - fail!("uninstall not yet implemented"); - } - - fn unprefer(&self, _id: &str, _vers: Option<~str>) { - fail!("unprefer not yet implemented"); - } -} - - -pub fn main() { - io::println("WARNING: The Rust package manager is experimental and may be unstable"); - - let args = os::args(); - let opts = ~[getopts::optflag("h"), getopts::optflag("help"), - getopts::optflag("j"), getopts::optflag("json"), - getopts::optmulti("c"), getopts::optmulti("cfg")]; - let matches = &match getopts::getopts(args, opts) { - result::Ok(m) => m, - result::Err(f) => { - error(fmt!("%s", getopts::fail_str(f))); - - return; - } - }; - let help = getopts::opt_present(matches, "h") || - getopts::opt_present(matches, "help"); - let json = getopts::opt_present(matches, "j") || - getopts::opt_present(matches, "json"); - let mut args = copy matches.free; - - args.shift(); - - if (args.len() < 1) { - return usage::general(); - } - - let cmd = args.shift(); - - if !util::is_cmd(cmd) { - return usage::general(); - } else if help { - return match cmd { - ~"build" => usage::build(), - ~"clean" => usage::clean(), - ~"do" => usage::do_cmd(), - ~"info" => usage::info(), - ~"install" => usage::install(), - ~"prefer" => usage::prefer(), - ~"test" => usage::test(), - ~"uninstall" => usage::uninstall(), - ~"unprefer" => usage::unprefer(), - _ => usage::general() - }; - } - - let sroot = match filesearch::get_rustpkg_sysroot() { - Ok(r) => Some(@r.pop().pop()), Err(_) => None - }; - debug!("Using sysroot: %?", sroot); - Ctx { - sysroot_opt: sroot, // Currently, only tests override this - json: json, - dep_cache: @mut HashMap::new() - }.run(cmd, args); -} - -/** - * Get the working directory of the package script. - * Assumes that the package script has been compiled - * in is the working directory. - */ -pub fn work_dir() -> Path { - os::self_exe_path().get() -} - -/** - * Get the source directory of the package (i.e. - * where the crates are located). Assumes - * that the cwd is changed to it before - * running this executable. - */ -pub fn src_dir() -> Path { - os::getcwd() -} diff --git a/src/librustpkg/rustpkg.rs b/src/librustpkg/rustpkg.rs new file mode 100644 index 00000000000..9242e450e24 --- /dev/null +++ b/src/librustpkg/rustpkg.rs @@ -0,0 +1,474 @@ +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// rustpkg - a package manager and build system for Rust + +#[link(name = "rustpkg", + vers = "0.7-pre", + uuid = "25de5e6e-279e-4a20-845c-4cabae92daaf", + url = "https://github.com/mozilla/rust/tree/master/src/librustpkg")]; + +#[license = "MIT/ASL2"]; +#[crate_type = "lib"]; + +#[no_core]; +#[no_std]; + +extern mod core(name = "std"); +extern mod extra(name = "extra"); + +extern mod rustc; +extern mod syntax; + +use core::prelude::*; +use core::*; +pub use core::path::Path; +use core::hashmap::HashMap; +use rustc::driver::{driver, session}; +use rustc::metadata::filesearch; +use extra::{getopts}; +use syntax::{ast, diagnostic}; +use util::*; +use messages::*; +use path_util::{build_pkg_id_in_workspace, first_pkgid_src_in_workspace}; +use path_util::{u_rwx, rust_path}; +use path_util::{built_executable_in_workspace, built_library_in_workspace}; +use path_util::{target_executable_in_workspace, target_library_in_workspace}; +use workspace::{each_pkg_parent_workspace, pkg_parent_workspaces}; +use context::Ctx; +use package_id::PkgId; +use package_source::PkgSrc; + +mod conditions; +mod context; +mod crate; +mod messages; +mod package_id; +mod package_path; +mod package_source; +mod path_util; +mod search; +mod target; +#[cfg(test)] +mod tests; +mod util; +mod version; +mod workspace; + +pub mod usage; + +mod std { + pub use core::cmp; + pub use core::condition; + pub use core::os; + pub use core::str; + pub use core::sys; + pub use core::unstable; +} + +/// A PkgScript represents user-supplied custom logic for +/// special build hooks. This only exists for packages with +/// an explicit package script. +struct PkgScript<'self> { + /// Uniquely identifies this package + id: &'self PkgId, + // Used to have this field: deps: ~[(~str, Option<~str>)] + // but I think it shouldn't be stored here + /// The contents of the package script: either a file path, + /// or a string containing the text of the input + input: driver::input, + /// The session to use *only* for compiling the custom + /// build script + sess: session::Session, + /// The config for compiling the custom build script + cfg: ast::crate_cfg, + /// The crate for the custom build script + crate: @ast::crate, + /// Directory in which to store build output + build_dir: Path +} + +impl<'self> PkgScript<'self> { + /// Given the path name for a package script + /// and a package ID, parse the package script into + /// a PkgScript that we can then execute + fn parse<'a>(script: Path, workspace: &Path, id: &'a PkgId) -> PkgScript<'a> { + // Get the executable name that was invoked + let binary = os::args()[0].to_managed(); + // Build the rustc session data structures to pass + // to the compiler + let options = @session::options { + binary: binary, + crate_type: session::bin_crate, + .. copy *session::basic_options() + }; + let input = driver::file_input(script); + let sess = driver::build_session(options, diagnostic::emit); + let cfg = driver::build_configuration(sess, binary, &input); + let (crate, _) = driver::compile_upto(sess, copy cfg, &input, driver::cu_parse, None); + let work_dir = build_pkg_id_in_workspace(id, workspace); + + debug!("Returning package script with id %?", id); + + PkgScript { + id: id, + input: input, + sess: sess, + cfg: cfg, + crate: crate.unwrap(), + build_dir: work_dir + } + } + + /// Run the contents of this package script, where + /// is the command to pass to it (e.g., "build", "clean", "install") + /// Returns a pair of an exit code and list of configs (obtained by + /// calling the package script's configs() function if it exists + // FIXME (#4432): Use workcache to only compile the script when changed + fn run_custom(&self, what: ~str) -> (~[~str], ExitCode) { + debug!("run_custom: %s", what); + let sess = self.sess; + + debug!("Working directory = %s", self.build_dir.to_str()); + // Collect together any user-defined commands in the package script + let crate = util::ready_crate(sess, self.crate); + debug!("Building output filenames with script name %s", + driver::source_name(&self.input)); + match filesearch::get_rustpkg_sysroot() { + Ok(r) => { + let root = r.pop().pop().pop().pop(); // :-\ + debug!("Root is %s, calling compile_rest", root.to_str()); + let exe = self.build_dir.push(~"pkg" + util::exe_suffix()); + let binary = os::args()[0].to_managed(); + util::compile_crate_from_input(&self.input, + &self.build_dir, + sess, + crate, + driver::build_configuration(sess, + binary, &self.input)); + debug!("Running program: %s %s %s", exe.to_str(), root.to_str(), what); + let status = run::process_status(exe.to_str(), [root.to_str(), what]); + if status != 0 { + return (~[], status); + } + else { + debug!("Running program (configs): %s %s %s", + exe.to_str(), root.to_str(), "configs"); + let output = run::process_output(exe.to_str(), [root.to_str(), ~"configs"]); + // Run the configs() function to get the configs + let cfgs = str::from_bytes_slice(output.output).word_iter() + .transform(|w| w.to_owned()).collect(); + (cfgs, output.status) + } + } + Err(e) => { + fail!("Running package script, couldn't find rustpkg sysroot (%s)", e) + } + } + } + + fn hash(&self) -> ~str { + self.id.hash() + } + +} + +impl Ctx { + + fn run(&self, cmd: &str, args: ~[~str]) { + match cmd { + "build" => { + if args.len() < 1 { + return usage::build(); + } + // The package id is presumed to be the first command-line + // argument + let pkgid = PkgId::new(copy args[0]); + for each_pkg_parent_workspace(&pkgid) |workspace| { + self.build(workspace, &pkgid); + } + } + "clean" => { + if args.len() < 1 { + return usage::build(); + } + // The package id is presumed to be the first command-line + // argument + let pkgid = PkgId::new(copy args[0]); + let cwd = os::getcwd(); + self.clean(&cwd, &pkgid); // tjc: should use workspace, not cwd + } + "do" => { + if args.len() < 2 { + return usage::do_cmd(); + } + + self.do_cmd(copy args[0], copy args[1]); + } + "info" => { + self.info(); + } + "install" => { + if args.len() < 1 { + return usage::install(); + } + + // The package id is presumed to be the first command-line + // argument + let pkgid = PkgId::new(args[0]); + let workspaces = pkg_parent_workspaces(&pkgid); + if workspaces.is_empty() { + let rp = rust_path(); + assert!(!rp.is_empty()); + let src = PkgSrc::new(&rp[0], &build_pkg_id_in_workspace(&pkgid, &rp[0]), + &pkgid); + src.fetch_git(); + self.install(&rp[0], &pkgid); + } + else { + for each_pkg_parent_workspace(&pkgid) |workspace| { + self.install(workspace, &pkgid); + } + } + } + "prefer" => { + if args.len() < 1 { + return usage::uninstall(); + } + + self.prefer(args[0], None); + } + "test" => { + self.test(); + } + "uninstall" => { + if args.len() < 1 { + return usage::uninstall(); + } + + self.uninstall(args[0], None); + } + "unprefer" => { + if args.len() < 1 { + return usage::uninstall(); + } + + self.unprefer(args[0], None); + } + _ => fail!(fmt!("I don't know the command `%s`", cmd)) + } + } + + fn do_cmd(&self, _cmd: &str, _pkgname: &str) { + // stub + fail!("`do` not yet implemented"); + } + + fn build(&self, workspace: &Path, pkgid: &PkgId) { + debug!("build: workspace = %s pkgid = %s", workspace.to_str(), + pkgid.to_str()); + let src_dir = first_pkgid_src_in_workspace(pkgid, workspace); + let build_dir = build_pkg_id_in_workspace(pkgid, workspace); + debug!("Destination dir = %s", build_dir.to_str()); + + // Create the package source + let mut src = PkgSrc::new(workspace, &build_dir, pkgid); + debug!("Package src = %?", src); + + // Is there custom build logic? If so, use it + let pkg_src_dir = src_dir; + let mut custom = false; + debug!("Package source directory = %?", pkg_src_dir); + let cfgs = match pkg_src_dir.chain_ref(|p| src.package_script_option(p)) { + Some(package_script_path) => { + let pscript = PkgScript::parse(package_script_path, + workspace, + pkgid); + // Limited right now -- we're only running the post_build + // hook and probably fail otherwise + // also post_build should be called pre_build + let (cfgs, hook_result) = pscript.run_custom(~"post_build"); + debug!("Command return code = %?", hook_result); + if hook_result != 0 { + fail!("Error running custom build command") + } + custom = true; + // otherwise, the package script succeeded + cfgs + } + None => { + debug!("No package script, continuing"); + ~[] + } + }; + + // If there was a package script, it should have finished + // the build already. Otherwise... + if !custom { + // Find crates inside the workspace + src.find_crates(); + // Build it! + src.build(self, build_dir, cfgs); + } + } + + fn clean(&self, workspace: &Path, id: &PkgId) { + // Could also support a custom build hook in the pkg + // script for cleaning files rustpkg doesn't know about. + // Do something reasonable for now + + let dir = build_pkg_id_in_workspace(id, workspace); + note(fmt!("Cleaning package %s (removing directory %s)", + id.to_str(), dir.to_str())); + if os::path_exists(&dir) { + os::remove_dir_recursive(&dir); + note(fmt!("Removed directory %s", dir.to_str())); + } + + note(fmt!("Cleaned package %s", id.to_str())); + } + + fn info(&self) { + // stub + fail!("info not yet implemented"); + } + + fn install(&self, workspace: &Path, id: &PkgId) { + use conditions::copy_failed::cond; + + // Should use RUST_PATH in the future. + // Also should use workcache to not build if not necessary. + self.build(workspace, id); + debug!("install: workspace = %s, id = %s", workspace.to_str(), + id.to_str()); + + // Now copy stuff into the install dirs + let maybe_executable = built_executable_in_workspace(id, workspace); + let maybe_library = built_library_in_workspace(id, workspace); + let target_exec = target_executable_in_workspace(id, workspace); + let target_lib = maybe_library.map(|_p| target_library_in_workspace(id, workspace)); + + debug!("target_exec = %s target_lib = %? \ + maybe_executable = %? maybe_library = %?", + target_exec.to_str(), target_lib, + maybe_executable, maybe_library); + + for maybe_executable.iter().advance |exec| { + debug!("Copying: %s -> %s", exec.to_str(), target_exec.to_str()); + if !(os::mkdir_recursive(&target_exec.dir_path(), u_rwx) && + os::copy_file(exec, &target_exec)) { + cond.raise((copy *exec, copy target_exec)); + } + } + for maybe_library.iter().advance |lib| { + let target_lib = (copy target_lib).expect(fmt!("I built %s but apparently \ + didn't install it!", lib.to_str())); + debug!("Copying: %s -> %s", lib.to_str(), target_lib.to_str()); + if !(os::mkdir_recursive(&target_lib.dir_path(), u_rwx) && + os::copy_file(lib, &target_lib)) { + cond.raise((copy *lib, copy target_lib)); + } + } + } + + fn prefer(&self, _id: &str, _vers: Option<~str>) { + fail!("prefer not yet implemented"); + } + + fn test(&self) { + // stub + fail!("test not yet implemented"); + } + + fn uninstall(&self, _id: &str, _vers: Option<~str>) { + fail!("uninstall not yet implemented"); + } + + fn unprefer(&self, _id: &str, _vers: Option<~str>) { + fail!("unprefer not yet implemented"); + } +} + + +pub fn main() { + io::println("WARNING: The Rust package manager is experimental and may be unstable"); + + let args = os::args(); + let opts = ~[getopts::optflag("h"), getopts::optflag("help"), + getopts::optflag("j"), getopts::optflag("json"), + getopts::optmulti("c"), getopts::optmulti("cfg")]; + let matches = &match getopts::getopts(args, opts) { + result::Ok(m) => m, + result::Err(f) => { + error(fmt!("%s", getopts::fail_str(f))); + + return; + } + }; + let help = getopts::opt_present(matches, "h") || + getopts::opt_present(matches, "help"); + let json = getopts::opt_present(matches, "j") || + getopts::opt_present(matches, "json"); + let mut args = copy matches.free; + + args.shift(); + + if (args.len() < 1) { + return usage::general(); + } + + let cmd = args.shift(); + + if !util::is_cmd(cmd) { + return usage::general(); + } else if help { + return match cmd { + ~"build" => usage::build(), + ~"clean" => usage::clean(), + ~"do" => usage::do_cmd(), + ~"info" => usage::info(), + ~"install" => usage::install(), + ~"prefer" => usage::prefer(), + ~"test" => usage::test(), + ~"uninstall" => usage::uninstall(), + ~"unprefer" => usage::unprefer(), + _ => usage::general() + }; + } + + let sroot = match filesearch::get_rustpkg_sysroot() { + Ok(r) => Some(@r.pop().pop()), Err(_) => None + }; + debug!("Using sysroot: %?", sroot); + Ctx { + sysroot_opt: sroot, // Currently, only tests override this + json: json, + dep_cache: @mut HashMap::new() + }.run(cmd, args); +} + +/** + * Get the working directory of the package script. + * Assumes that the package script has been compiled + * in is the working directory. + */ +pub fn work_dir() -> Path { + os::self_exe_path().get() +} + +/** + * Get the source directory of the package (i.e. + * where the crates are located). Assumes + * that the cwd is changed to it before + * running this executable. + */ +pub fn src_dir() -> Path { + os::getcwd() +} diff --git a/src/libstd/core.rc b/src/libstd/core.rc deleted file mode 100644 index 13c54799fac..00000000000 --- a/src/libstd/core.rc +++ /dev/null @@ -1,230 +0,0 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/*! - -# The Rust standard library - -The Rust standard library is a group of interrelated modules defining -the core language traits, operations on built-in data types, collections, -platform abstractions, the task scheduler, runtime support for language -features and other common functionality. - -`std` includes modules corresponding to each of the integer types, -each of the floating point types, the `bool` type, tuples, characters, -strings (`str`), vectors (`vec`), managed boxes (`managed`), owned -boxes (`owned`), and unsafe and borrowed pointers (`ptr`, `borrowed`). -Additionally, `std` provides pervasive types (`option` and `result`), -task creation and communication primitives (`task`, `comm`), platform -abstractions (`os` and `path`), basic I/O abstractions (`io`), common -traits (`kinds`, `ops`, `cmp`, `num`, `to_str`), and complete bindings -to the C standard library (`libc`). - -# Standard library injection and the Rust prelude - -`std` is imported at the topmost level of every crate by default, as -if the first line of each crate was - - extern mod std; - -This means that the contents of std can be accessed from any context -with the `std::` path prefix, as in `use std::vec`, `use std::task::spawn`, -etc. - -Additionally, `std` contains a `prelude` module that reexports many of the -most common types, traits and functions. The contents of the prelude are -imported into every *module* by default. Implicitly, all modules behave as if -they contained the following prologue: - - use std::prelude::*; - -*/ - - -#[link(name = "std", - vers = "0.7-pre", - uuid = "c70c24a7-5551-4f73-8e37-380b11d80be8", - url = "https://github.com/mozilla/rust/tree/master/src/libstd")]; - -#[comment = "The Rust standard library"]; -#[license = "MIT/ASL2"]; -#[crate_type = "lib"]; - -// Don't link to std. We are std. -#[no_std]; - -#[deny(non_camel_case_types)]; -#[deny(missing_doc)]; - -// Make std testable by not duplicating lang items. See #2912 -#[cfg(test)] extern mod realstd(name = "std"); -#[cfg(test)] pub use kinds = realstd::kinds; -#[cfg(test)] pub use ops = realstd::ops; -#[cfg(test)] pub use cmp = realstd::cmp; - -// On Linux, link to the runtime with -lrt. -#[cfg(target_os = "linux")] -#[doc(hidden)] -pub mod linkhack { - #[link_args="-lrustrt -lrt"] - #[link_args = "-lpthread"] - extern { - } -} - -// Internal macros -mod macros; - -/* The Prelude. */ - -pub mod prelude; - -/* Primitive types */ - -#[path = "num/int_macros.rs"] mod int_macros; -#[path = "num/uint_macros.rs"] mod uint_macros; - -#[path = "num/int.rs"] pub mod int; -#[path = "num/i8.rs"] pub mod i8; -#[path = "num/i16.rs"] pub mod i16; -#[path = "num/i32.rs"] pub mod i32; -#[path = "num/i64.rs"] pub mod i64; - -#[path = "num/uint.rs"] pub mod uint; -#[path = "num/u8.rs"] pub mod u8; -#[path = "num/u16.rs"] pub mod u16; -#[path = "num/u32.rs"] pub mod u32; -#[path = "num/u64.rs"] pub mod u64; - -#[path = "num/float.rs"] pub mod float; -#[path = "num/f32.rs"] pub mod f32; -#[path = "num/f64.rs"] pub mod f64; - -pub mod nil; -pub mod bool; -pub mod char; -pub mod tuple; - -pub mod vec; -pub mod at_vec; -pub mod str; - -#[path = "str/ascii.rs"] -pub mod ascii; - -pub mod ptr; -pub mod owned; -pub mod managed; -pub mod borrow; - - -/* Core language traits */ - -#[cfg(not(test))] pub mod kinds; -#[cfg(not(test))] pub mod ops; -#[cfg(not(test))] pub mod cmp; - - -/* Common traits */ - -pub mod from_str; -#[path = "num/num.rs"] -pub mod num; -pub mod iter; -pub mod iterator; -pub mod to_str; -pub mod to_bytes; -pub mod clone; -pub mod io; -pub mod hash; -pub mod container; - - -/* Common data structures */ - -pub mod option; -pub mod result; -pub mod either; -pub mod hashmap; -pub mod cell; -pub mod trie; - - -/* Tasks and communication */ - -#[path = "task/mod.rs"] -pub mod task; -pub mod comm; -pub mod pipes; -pub mod local_data; - - -/* Runtime and platform support */ - -pub mod gc; -pub mod libc; -pub mod os; -pub mod path; -pub mod rand; -pub mod run; -pub mod sys; -pub mod cast; -pub mod repr; -pub mod cleanup; -pub mod reflect; -pub mod condition; -pub mod logging; -pub mod util; - - -/* Unsupported interfaces */ - -// Private APIs -#[path = "unstable/mod.rs"] -pub mod unstable; - -/* For internal use, not exported */ - -mod unicode; -#[path = "num/cmath.rs"] -mod cmath; -mod stackwalk; - -// XXX: This shouldn't be pub, and it should be reexported under 'unstable' -// but name resolution doesn't work without it being pub. -#[path = "rt/mod.rs"] -pub mod rt; - -// A curious inner-module that's not exported that contains the binding -// 'std' so that macro-expanded references to std::error and such -// can be resolved within libstd. -#[doc(hidden)] -mod core { - pub use clone; - pub use cmp; - pub use condition; - pub use option; - pub use kinds; - pub use sys; - pub use pipes; -} -#[doc(hidden)] -mod std { - pub use clone; - pub use cmp; - pub use condition; - pub use option; - pub use kinds; - pub use sys; - pub use pipes; - pub use unstable; - pub use str; - pub use os; -} diff --git a/src/libstd/std.rs b/src/libstd/std.rs new file mode 100644 index 00000000000..13c54799fac --- /dev/null +++ b/src/libstd/std.rs @@ -0,0 +1,230 @@ +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/*! + +# The Rust standard library + +The Rust standard library is a group of interrelated modules defining +the core language traits, operations on built-in data types, collections, +platform abstractions, the task scheduler, runtime support for language +features and other common functionality. + +`std` includes modules corresponding to each of the integer types, +each of the floating point types, the `bool` type, tuples, characters, +strings (`str`), vectors (`vec`), managed boxes (`managed`), owned +boxes (`owned`), and unsafe and borrowed pointers (`ptr`, `borrowed`). +Additionally, `std` provides pervasive types (`option` and `result`), +task creation and communication primitives (`task`, `comm`), platform +abstractions (`os` and `path`), basic I/O abstractions (`io`), common +traits (`kinds`, `ops`, `cmp`, `num`, `to_str`), and complete bindings +to the C standard library (`libc`). + +# Standard library injection and the Rust prelude + +`std` is imported at the topmost level of every crate by default, as +if the first line of each crate was + + extern mod std; + +This means that the contents of std can be accessed from any context +with the `std::` path prefix, as in `use std::vec`, `use std::task::spawn`, +etc. + +Additionally, `std` contains a `prelude` module that reexports many of the +most common types, traits and functions. The contents of the prelude are +imported into every *module* by default. Implicitly, all modules behave as if +they contained the following prologue: + + use std::prelude::*; + +*/ + + +#[link(name = "std", + vers = "0.7-pre", + uuid = "c70c24a7-5551-4f73-8e37-380b11d80be8", + url = "https://github.com/mozilla/rust/tree/master/src/libstd")]; + +#[comment = "The Rust standard library"]; +#[license = "MIT/ASL2"]; +#[crate_type = "lib"]; + +// Don't link to std. We are std. +#[no_std]; + +#[deny(non_camel_case_types)]; +#[deny(missing_doc)]; + +// Make std testable by not duplicating lang items. See #2912 +#[cfg(test)] extern mod realstd(name = "std"); +#[cfg(test)] pub use kinds = realstd::kinds; +#[cfg(test)] pub use ops = realstd::ops; +#[cfg(test)] pub use cmp = realstd::cmp; + +// On Linux, link to the runtime with -lrt. +#[cfg(target_os = "linux")] +#[doc(hidden)] +pub mod linkhack { + #[link_args="-lrustrt -lrt"] + #[link_args = "-lpthread"] + extern { + } +} + +// Internal macros +mod macros; + +/* The Prelude. */ + +pub mod prelude; + +/* Primitive types */ + +#[path = "num/int_macros.rs"] mod int_macros; +#[path = "num/uint_macros.rs"] mod uint_macros; + +#[path = "num/int.rs"] pub mod int; +#[path = "num/i8.rs"] pub mod i8; +#[path = "num/i16.rs"] pub mod i16; +#[path = "num/i32.rs"] pub mod i32; +#[path = "num/i64.rs"] pub mod i64; + +#[path = "num/uint.rs"] pub mod uint; +#[path = "num/u8.rs"] pub mod u8; +#[path = "num/u16.rs"] pub mod u16; +#[path = "num/u32.rs"] pub mod u32; +#[path = "num/u64.rs"] pub mod u64; + +#[path = "num/float.rs"] pub mod float; +#[path = "num/f32.rs"] pub mod f32; +#[path = "num/f64.rs"] pub mod f64; + +pub mod nil; +pub mod bool; +pub mod char; +pub mod tuple; + +pub mod vec; +pub mod at_vec; +pub mod str; + +#[path = "str/ascii.rs"] +pub mod ascii; + +pub mod ptr; +pub mod owned; +pub mod managed; +pub mod borrow; + + +/* Core language traits */ + +#[cfg(not(test))] pub mod kinds; +#[cfg(not(test))] pub mod ops; +#[cfg(not(test))] pub mod cmp; + + +/* Common traits */ + +pub mod from_str; +#[path = "num/num.rs"] +pub mod num; +pub mod iter; +pub mod iterator; +pub mod to_str; +pub mod to_bytes; +pub mod clone; +pub mod io; +pub mod hash; +pub mod container; + + +/* Common data structures */ + +pub mod option; +pub mod result; +pub mod either; +pub mod hashmap; +pub mod cell; +pub mod trie; + + +/* Tasks and communication */ + +#[path = "task/mod.rs"] +pub mod task; +pub mod comm; +pub mod pipes; +pub mod local_data; + + +/* Runtime and platform support */ + +pub mod gc; +pub mod libc; +pub mod os; +pub mod path; +pub mod rand; +pub mod run; +pub mod sys; +pub mod cast; +pub mod repr; +pub mod cleanup; +pub mod reflect; +pub mod condition; +pub mod logging; +pub mod util; + + +/* Unsupported interfaces */ + +// Private APIs +#[path = "unstable/mod.rs"] +pub mod unstable; + +/* For internal use, not exported */ + +mod unicode; +#[path = "num/cmath.rs"] +mod cmath; +mod stackwalk; + +// XXX: This shouldn't be pub, and it should be reexported under 'unstable' +// but name resolution doesn't work without it being pub. +#[path = "rt/mod.rs"] +pub mod rt; + +// A curious inner-module that's not exported that contains the binding +// 'std' so that macro-expanded references to std::error and such +// can be resolved within libstd. +#[doc(hidden)] +mod core { + pub use clone; + pub use cmp; + pub use condition; + pub use option; + pub use kinds; + pub use sys; + pub use pipes; +} +#[doc(hidden)] +mod std { + pub use clone; + pub use cmp; + pub use condition; + pub use option; + pub use kinds; + pub use sys; + pub use pipes; + pub use unstable; + pub use str; + pub use os; +} diff --git a/src/libsyntax/syntax.rc b/src/libsyntax/syntax.rc deleted file mode 100644 index 278600bc039..00000000000 --- a/src/libsyntax/syntax.rc +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/*! This module contains the Rust parser. It maps source text - * to token trees and to ASTs. It contains code for expanding - * macros. - */ - -#[link(name = "syntax", - vers = "0.7-pre", - uuid = "9311401b-d6ea-4cd9-a1d9-61f89499c645")]; - -#[license = "MIT/ASL2"]; -#[crate_type = "lib"]; - -#[allow(non_camel_case_types)]; -#[deny(deprecated_pattern)]; - -#[no_core]; -#[no_std]; - -extern mod core(name = "std"); -extern mod extra(name = "extra"); - -// For deriving(Encodable) purposes... -extern mod std(name = "std"); - -use core::prelude::*; - -pub mod util { - pub mod interner; - #[cfg(test)] - pub mod parser_testing; -} - -pub mod syntax { - pub use ext; - pub use parse; -} - -pub mod opt_vec; -pub mod attr; -pub mod diagnostic; -pub mod codemap; -pub mod abi; -pub mod ast; -pub mod ast_util; -pub mod ast_map; -pub mod visit; -pub mod fold; - - -#[path = "parse/mod.rs"] -pub mod parse; - -pub mod print { - pub mod pp; - pub mod pprust; -} - -pub mod ext { - pub mod asm; - pub mod base; - pub mod expand; - - pub mod quote; - - #[path = "deriving/mod.rs"] - pub mod deriving; - - pub mod build; - - pub mod tt { - pub mod transcribe; - pub mod macro_parser; - pub mod macro_rules; - } - - - pub mod fmt; - pub mod env; - pub mod bytes; - pub mod concat_idents; - pub mod log_syntax; - pub mod auto_encode; - pub mod source_util; - - #[path = "pipes/mod.rs"] - pub mod pipes; - - pub mod trace_macros; -} diff --git a/src/libsyntax/syntax.rs b/src/libsyntax/syntax.rs new file mode 100644 index 00000000000..278600bc039 --- /dev/null +++ b/src/libsyntax/syntax.rs @@ -0,0 +1,99 @@ +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/*! This module contains the Rust parser. It maps source text + * to token trees and to ASTs. It contains code for expanding + * macros. + */ + +#[link(name = "syntax", + vers = "0.7-pre", + uuid = "9311401b-d6ea-4cd9-a1d9-61f89499c645")]; + +#[license = "MIT/ASL2"]; +#[crate_type = "lib"]; + +#[allow(non_camel_case_types)]; +#[deny(deprecated_pattern)]; + +#[no_core]; +#[no_std]; + +extern mod core(name = "std"); +extern mod extra(name = "extra"); + +// For deriving(Encodable) purposes... +extern mod std(name = "std"); + +use core::prelude::*; + +pub mod util { + pub mod interner; + #[cfg(test)] + pub mod parser_testing; +} + +pub mod syntax { + pub use ext; + pub use parse; +} + +pub mod opt_vec; +pub mod attr; +pub mod diagnostic; +pub mod codemap; +pub mod abi; +pub mod ast; +pub mod ast_util; +pub mod ast_map; +pub mod visit; +pub mod fold; + + +#[path = "parse/mod.rs"] +pub mod parse; + +pub mod print { + pub mod pp; + pub mod pprust; +} + +pub mod ext { + pub mod asm; + pub mod base; + pub mod expand; + + pub mod quote; + + #[path = "deriving/mod.rs"] + pub mod deriving; + + pub mod build; + + pub mod tt { + pub mod transcribe; + pub mod macro_parser; + pub mod macro_rules; + } + + + pub mod fmt; + pub mod env; + pub mod bytes; + pub mod concat_idents; + pub mod log_syntax; + pub mod auto_encode; + pub mod source_util; + + #[path = "pipes/mod.rs"] + pub mod pipes; + + pub mod trace_macros; +} -- cgit 1.4.1-3-g733a5 From 5242e8d2bad01beec7c841d20952cb230bc9fd84 Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Mon, 24 Jun 2013 17:19:28 -0400 Subject: remove the redundant `each` method from OptVec --- src/librustc/metadata/encoder.rs | 4 ++-- src/librustc/middle/resolve.rs | 8 ++++---- src/librustc/middle/typeck/astconv.rs | 2 +- src/librustc/middle/typeck/collect.rs | 4 ++-- src/librustc/middle/typeck/rscope.rs | 2 +- src/libsyntax/ast_util.rs | 4 ++-- src/libsyntax/ext/deriving/generic.rs | 4 ++-- src/libsyntax/ext/pipes/pipec.rs | 4 ++-- src/libsyntax/opt_vec.rs | 7 ------- src/libsyntax/print/pprust.rs | 2 +- src/libsyntax/visit.rs | 4 ++-- 11 files changed, 19 insertions(+), 26 deletions(-) (limited to 'src/libsyntax') diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index d08342d8687..9c28da10e40 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -731,8 +731,8 @@ fn encode_info_for_method(ecx: &EncodeContext, } let mut combined_ty_params = opt_vec::Empty; - for owner_generics.ty_params.each |x| { combined_ty_params.push(copy *x) } - for method_generics.ty_params.each |x| { combined_ty_params.push(copy *x) } + for owner_generics.ty_params.iter().advance |x| { combined_ty_params.push(copy *x) } + for method_generics.ty_params.iter().advance |x| { combined_ty_params.push(copy *x) } let len = combined_ty_params.len(); encode_type_param_bounds(ebml_w, ecx, &combined_ty_params); diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index a8b837d869d..3a54c224b52 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -3834,8 +3834,8 @@ impl Resolver { pub fn resolve_type_parameters(@mut self, type_parameters: &OptVec, visitor: ResolveVisitor) { - for type_parameters.each |type_parameter| { - for type_parameter.bounds.each |bound| { + for type_parameters.iter().advance |type_parameter| { + for type_parameter.bounds.iter().advance |bound| { self.resolve_type_parameter_bound(bound, visitor); } } @@ -4181,13 +4181,13 @@ impl Resolver { } } - for bounds.each |bound| { + for bounds.iter().advance |bound| { self.resolve_type_parameter_bound(bound, visitor); } } ty_closure(c) => { - for c.bounds.each |bound| { + for c.bounds.iter().advance |bound| { self.resolve_type_parameter_bound(bound, visitor); } visit_ty(ty, ((), visitor)); diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs index 3b651451db8..5e6574850f1 100644 --- a/src/librustc/middle/typeck/astconv.rs +++ b/src/librustc/middle/typeck/astconv.rs @@ -752,7 +752,7 @@ fn conv_builtin_bounds(tcx: ty::ctxt, //! legal. let mut builtin_bounds = ty::EmptyBuiltinBounds(); - for ast_bounds.each |ast_bound| { + for ast_bounds.iter().advance |ast_bound| { match *ast_bound { ast::TraitTyParamBound(b) => { match lookup_def_tcx(tcx, b.path.span, b.ref_id) { diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index 3554376902c..7812a0ed0eb 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -775,7 +775,7 @@ pub fn ensure_no_ty_param_bounds(ccx: &CrateCtxt, span: span, generics: &ast::Generics, thing: &'static str) { - for generics.ty_params.each |ty_param| { + for generics.ty_params.iter().advance |ty_param| { if ty_param.bounds.len() > 0 { ccx.tcx.sess.span_err( span, @@ -1172,7 +1172,7 @@ pub fn ty_generics(ccx: &CrateCtxt, builtin_bounds: ty::EmptyBuiltinBounds(), trait_bounds: ~[] }; - for ast_bounds.each |ast_bound| { + for ast_bounds.iter().advance |ast_bound| { match *ast_bound { TraitTyParamBound(b) => { let ty = ty::mk_param(ccx.tcx, param_ty.idx, param_ty.def_id); diff --git a/src/librustc/middle/typeck/rscope.rs b/src/librustc/middle/typeck/rscope.rs index 16b490cd478..dc9fc264f85 100644 --- a/src/librustc/middle/typeck/rscope.rs +++ b/src/librustc/middle/typeck/rscope.rs @@ -57,7 +57,7 @@ impl RegionParamNames { } fn has_ident(&self, ident: ast::ident) -> bool { - for self.each |region_param_name| { + for self.iter().advance |region_param_name| { if *region_param_name == ident { return true; } diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 227d700452b..a233c330b64 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -394,10 +394,10 @@ impl id_range { pub fn id_visitor(vfn: @fn(node_id, T)) -> visit::vt { let visit_generics: @fn(&Generics, T) = |generics, t| { - for generics.ty_params.each |p| { + for generics.ty_params.iter().advance |p| { vfn(p.id, copy t); } - for generics.lifetimes.each |p| { + for generics.lifetimes.iter().advance |p| { vfn(p.id, copy t); } }; diff --git a/src/libsyntax/ext/deriving/generic.rs b/src/libsyntax/ext/deriving/generic.rs index 981b28afd02..83e446fa4c6 100644 --- a/src/libsyntax/ext/deriving/generic.rs +++ b/src/libsyntax/ext/deriving/generic.rs @@ -324,11 +324,11 @@ impl<'self> TraitDef<'self> { let mut trait_generics = self.generics.to_generics(cx, span, type_ident, generics); // Copy the lifetimes - for generics.lifetimes.each |l| { + for generics.lifetimes.iter().advance |l| { trait_generics.lifetimes.push(copy *l) }; // Create the type parameters. - for generics.ty_params.each |ty_param| { + for generics.ty_params.iter().advance |ty_param| { // I don't think this can be moved out of the loop, since // a TyParamBound requires an ast id let mut bounds = opt_vec::from( diff --git a/src/libsyntax/ext/pipes/pipec.rs b/src/libsyntax/ext/pipes/pipec.rs index 55ac9c5ec1c..da5455d4332 100644 --- a/src/libsyntax/ext/pipes/pipec.rs +++ b/src/libsyntax/ext/pipes/pipec.rs @@ -374,7 +374,7 @@ impl gen_init for protocol { fn buffer_ty_path(&self, cx: @ExtCtxt) -> @ast::Ty { let mut params: OptVec = opt_vec::Empty; for (copy self.states).iter().advance |s| { - for s.generics.ty_params.each |tp| { + for s.generics.ty_params.iter().advance |tp| { match params.iter().find_(|tpp| tp.ident == tpp.ident) { None => params.push(*tp), _ => () @@ -392,7 +392,7 @@ impl gen_init for protocol { let ext_cx = cx; let mut params: OptVec = opt_vec::Empty; let fields = do (copy self.states).iter().transform |s| { - for s.generics.ty_params.each |tp| { + for s.generics.ty_params.iter().advance |tp| { match params.iter().find_(|tpp| tp.ident == tpp.ident) { None => params.push(*tp), _ => () diff --git a/src/libsyntax/opt_vec.rs b/src/libsyntax/opt_vec.rs index 8917b481dc7..22b1d040d42 100644 --- a/src/libsyntax/opt_vec.rs +++ b/src/libsyntax/opt_vec.rs @@ -38,13 +38,6 @@ pub fn from(t: ~[T]) -> OptVec { } impl OptVec { - fn each(&self, blk: &fn(v: &T) -> bool) -> bool { - match *self { - Empty => true, - Vec(ref v) => v.iter().advance(blk) - } - } - fn push(&mut self, t: T) { match *self { Vec(ref mut v) => { diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 1a3155337a5..d7b5e57a57f 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1743,7 +1743,7 @@ pub fn print_bounds(s: @ps, bounds: @OptVec) { if !bounds.is_empty() { word(s.s, ":"); let mut first = true; - for bounds.each |bound| { + for bounds.iter().advance |bound| { nbsp(s); if first { first = false; diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index d7914832835..5e409be3e6c 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -334,7 +334,7 @@ pub fn visit_foreign_item(ni: @foreign_item, (e, v): (E, vt)) { pub fn visit_ty_param_bounds(bounds: &OptVec, (e, v): (E, vt)) { - for bounds.each |bound| { + for bounds.iter().advance |bound| { match *bound { TraitTyParamBound(ty) => visit_trait_ref(ty, (copy e, v)), RegionTyParamBound => {} @@ -343,7 +343,7 @@ pub fn visit_ty_param_bounds(bounds: &OptVec, } pub fn visit_generics(generics: &Generics, (e, v): (E, vt)) { - for generics.ty_params.each |tp| { + for generics.ty_params.iter().advance |tp| { visit_ty_param_bounds(tp.bounds, (copy e, v)); } } -- cgit 1.4.1-3-g733a5