From c8ce32e7f45a020eebcd7329fbe33e8b53f832a3 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Wed, 22 Aug 2012 17:58:05 -0700 Subject: [PATCH] Represent "item families" in the decoder as an enum This eliminates some match checks. Also get rid of other match checks in metadata code. --- src/rustc/metadata/decoder.rs | 190 +++++++++++++++++++++------------ src/rustc/metadata/encoder.rs | 11 +- src/rustc/metadata/tydecode.rs | 48 +++++---- 3 files changed, 157 insertions(+), 92 deletions(-) diff --git a/src/rustc/metadata/decoder.rs b/src/rustc/metadata/decoder.rs index 1b4fad2ca66..a1a2b7245eb 100644 --- a/src/rustc/metadata/decoder.rs +++ b/src/rustc/metadata/decoder.rs @@ -105,9 +105,56 @@ fn lookup_item(item_id: int, data: @~[u8]) -> ebml::doc { } } -fn item_family(item: ebml::doc) -> char { +enum Family { + Const, // c + Fn, // f + UnsafeFn, // u + PureFn, // p + StaticMethod, // F + UnsafeStaticMethod, // U + PureStaticMethod, // P + ForeignFn, // e + Type, // y + ForeignType, // T + Mod, // m + ForeignMod, // n + Enum, // t + Variant, // v + Impl, // i + Trait, // I + Class, // C + Struct, // S + PublicField, // g + PrivateField, // j + InheritedField // N +} + +fn item_family(item: ebml::doc) -> Family { let fam = ebml::get_doc(item, tag_items_data_item_family); - ebml::doc_as_u8(fam) as char + match ebml::doc_as_u8(fam) as char { + 'c' => Const, + 'f' => Fn, + 'u' => UnsafeFn, + 'p' => PureFn, + 'F' => StaticMethod, + 'U' => UnsafeStaticMethod, + 'P' => PureStaticMethod, + 'e' => ForeignFn, + 'y' => Type, + 'T' => ForeignType, + 'm' => Mod, + 'n' => ForeignMod, + 't' => Enum, + 'v' => Variant, + 'i' => Impl, + 'I' => Trait, + 'C' => Class, + 'S' => Struct, + 'g' => PublicField, + 'j' => PrivateField, + 'N' => InheritedField, + c => fail (#fmt("unexpected family char: %c", c)) + } } fn item_symbol(item: ebml::doc) -> ~str { @@ -245,31 +292,34 @@ fn item_name(intr: ident_interner, item: ebml::doc) -> ast::ident { fn item_to_def_like(item: ebml::doc, did: ast::def_id, cnum: ast::crate_num) -> def_like { - let fam_ch = item_family(item); - match fam_ch { - 'c' => dl_def(ast::def_const(did)), - 'C' => dl_def(ast::def_class(did, true)), - 'S' => dl_def(ast::def_class(did, false)), - 'u' => dl_def(ast::def_fn(did, ast::unsafe_fn)), - 'f' => dl_def(ast::def_fn(did, ast::impure_fn)), - 'p' => dl_def(ast::def_fn(did, ast::pure_fn)), - 'e' => dl_def(ast::def_fn(did, ast::extern_fn)), - 'U' => dl_def(ast::def_static_method(did, ast::unsafe_fn)), - 'F' => dl_def(ast::def_static_method(did, ast::impure_fn)), - 'P' => dl_def(ast::def_static_method(did, ast::pure_fn)), - 'y' => dl_def(ast::def_ty(did)), - 't' => dl_def(ast::def_ty(did)), - 'm' => dl_def(ast::def_mod(did)), - 'n' => dl_def(ast::def_foreign_mod(did)), - 'v' => { - let mut tid = option::get(item_parent_item(item)); - tid = {crate: cnum, node: tid.node}; - dl_def(ast::def_variant(tid, did)) + let fam = item_family(item); + match fam { + Const => dl_def(ast::def_const(did)), + Class => dl_def(ast::def_class(did, true)), + Struct => dl_def(ast::def_class(did, false)), + UnsafeFn => dl_def(ast::def_fn(did, ast::unsafe_fn)), + Fn => dl_def(ast::def_fn(did, ast::impure_fn)), + PureFn => dl_def(ast::def_fn(did, ast::pure_fn)), + ForeignFn => dl_def(ast::def_fn(did, ast::extern_fn)), + UnsafeStaticMethod => dl_def(ast::def_static_method(did, + ast::unsafe_fn)), + StaticMethod => dl_def(ast::def_static_method(did, ast::impure_fn)), + PureStaticMethod => dl_def(ast::def_static_method(did, ast::pure_fn)), + Type | ForeignType => dl_def(ast::def_ty(did)), + Mod => dl_def(ast::def_mod(did)), + ForeignMod => dl_def(ast::def_foreign_mod(did)), + Variant => { + match item_parent_item(item) { + some(t) => { + let tid = {crate: cnum, node: t.node}; + dl_def(ast::def_variant(tid, did)) + } + none => fail ~"item_to_def_like: enum item has no parent" + } } - 'I' => dl_def(ast::def_ty(did)), - 'i' => dl_impl(did), - 'g' | 'j' | 'N' => dl_field, - ch => fail fmt!{"unexpected family code: '%c'", ch} + Trait | Enum => dl_def(ast::def_ty(did)), + Impl => dl_impl(did), + PublicField | PrivateField | InheritedField => dl_field, } } @@ -642,12 +692,14 @@ fn get_trait_methods(intr: ident_interner, cdata: cmd, id: ast::node_id, let self_ty = get_self_ty(mth); vec::push(result, {ident: name, tps: bounds, fty: fty, self_ty: self_ty, - purity: match check item_family(mth) { - 'u' => ast::unsafe_fn, - 'f' => ast::impure_fn, - 'p' => ast::pure_fn + purity: match item_family(mth) { + UnsafeFn => ast::unsafe_fn, + Fn => ast::impure_fn, + PureFn => ast::pure_fn, + _ => fail ~"bad purity" }, vis: ast::public}); } + #debug("get_trait_methods: }"); @result } @@ -659,7 +711,7 @@ fn get_method_names_if_trait(intr: ident_interner, cdata: cmd, -> option<@DVec<(ast::ident, ast::self_ty_)>> { let item = lookup_item(node_id, cdata.data); - if item_family(item) != 'I' { + if item_family(item) != Trait { return none; } @@ -685,7 +737,7 @@ fn get_item_attrs(cdata: cmd, // Helper function that gets either fields or methods fn get_class_members(intr: ident_interner, cdata: cmd, id: ast::node_id, - p: fn(char) -> bool) -> ~[ty::field_ty] { + p: fn(Family) -> bool) -> ~[ty::field_ty] { let data = cdata.data; let item = lookup_item(id, data); let mut result = ~[]; @@ -702,33 +754,31 @@ fn get_class_members(intr: ident_interner, cdata: cmd, id: ast::node_id, result } -pure fn family_to_visibility(family: char) -> ast::visibility { +pure fn family_to_visibility(family: Family) -> ast::visibility { match family { - 'g' => ast::public, - 'j' => ast::private, - 'N' => ast::inherited, + PublicField => ast::public, + PrivateField => ast::private, + InheritedField => ast::inherited, _ => fail } } -/* 'g' for public field, 'j' for private field, 'N' for inherited field */ fn get_class_fields(intr: ident_interner, cdata: cmd, id: ast::node_id) -> ~[ty::field_ty] { - get_class_members(intr, cdata, id, |f| f == 'g' || f == 'j' || f == 'N') + get_class_members(intr, cdata, id, |f| f == PublicField + || f == PrivateField || f == InheritedField) } -fn family_has_type_params(fam_ch: char) -> bool { - match fam_ch { - 'c' | 'T' | 'm' | 'n' | 'g' | 'h' | 'j' | 'e' | 'N' => false, - 'f' | 'u' | 'p' | 'F' | 'U' | 'P' | 'y' | 't' | 'v' | 'i' | 'I' | 'C' - | 'a' | 'S' - => true, - _ => fail fmt!("'%c' is not a family", fam_ch) +fn family_has_type_params(fam: Family) -> bool { + match fam { + Const | ForeignType | Mod | ForeignMod | PublicField | PrivateField + | ForeignFn => false, + _ => true } } -fn family_names_type(fam_ch: char) -> bool { - match fam_ch { 'y' | 't' | 'I' => true, _ => false } +fn family_names_type(fam: Family) -> bool { + match fam { Type | Mod | Trait => true, _ => false } } fn read_path(d: ebml::doc) -> {path: ~str, pos: uint} { @@ -748,29 +798,29 @@ fn describe_def(items: ebml::doc, id: ast::def_id) -> ~str { return item_family_to_str(item_family(it)); } -fn item_family_to_str(fam: char) -> ~str { - match check fam { - 'c' => return ~"const", - 'f' => return ~"fn", - 'u' => return ~"unsafe fn", - 'p' => return ~"pure fn", - 'F' => return ~"static method", - 'U' => return ~"unsafe static method", - 'P' => return ~"pure static method", - 'e' => return ~"foreign fn", - 'y' => return ~"type", - 'T' => return ~"foreign type", - 't' => return ~"type", - 'm' => return ~"mod", - 'n' => return ~"foreign mod", - 'v' => return ~"enum", - 'i' => return ~"impl", - 'I' => return ~"trait", - 'C' => return ~"class", - 'S' => return ~"struct", - 'g' => return ~"public field", - 'j' => return ~"private field", - 'N' => return ~"inherited field" +fn item_family_to_str(fam: Family) -> ~str { + match fam { + Const => ~"const", + Fn => ~"fn", + UnsafeFn => ~"unsafe fn", + PureFn => ~"pure fn", + StaticMethod => ~"static method", + UnsafeStaticMethod => ~"unsafe static method", + PureStaticMethod => ~"pure static method", + ForeignFn => ~"foreign fn", + Type => ~"type", + ForeignType => ~"foreign type", + Mod => ~"mod", + ForeignMod => ~"foreign mod", + Enum => ~"enum", + Variant => ~"variant", + Impl => ~"impl", + Trait => ~"trait", + Class => ~"class", + Struct => ~"struct", + PublicField => ~"public field", + PrivateField => ~"private field", + InheritedField => ~"inherited field", } } diff --git a/src/rustc/metadata/encoder.rs b/src/rustc/metadata/encoder.rs index e14e64ddd0c..7b2e2b8a217 100644 --- a/src/rustc/metadata/encoder.rs +++ b/src/rustc/metadata/encoder.rs @@ -88,7 +88,7 @@ fn encode_region_param(ecx: @encode_ctxt, ebml_w: ebml::writer, fn encode_mutability(ebml_w: ebml::writer, mt: class_mutability) { do ebml_w.wr_tag(tag_class_mut) { let val = match mt { - class_immutable => 'i', + class_immutable => 'a', class_mutable => 'm' }; ebml_w.writer.write(&[val as u8]); @@ -472,7 +472,7 @@ fn purity_static_method_family(p: purity) -> char { unsafe_fn => 'U', pure_fn => 'P', impure_fn => 'F', - extern_fn => 'E' + _ => fail ~"extern fn can't be static" } } @@ -813,19 +813,22 @@ fn encode_info_for_items(ecx: @encode_ctxt, ebml_w: ebml::writer, visit_expr: |_e, _cx, _v| { }, visit_item: |i, cx, v, copy ebml_w| { visit::visit_item(i, cx, v); - match check ecx.tcx.items.get(i.id) { + match ecx.tcx.items.get(i.id) { ast_map::node_item(_, pt) => { encode_info_for_item(ecx, ebml_w, i, index, *pt); } + _ => fail ~"bad item" } }, visit_foreign_item: |ni, cx, v, copy ebml_w| { visit::visit_foreign_item(ni, cx, v); - match check ecx.tcx.items.get(ni.id) { + match ecx.tcx.items.get(ni.id) { ast_map::node_foreign_item(_, abi, pt) => { encode_info_for_foreign_item(ecx, ebml_w, ni, index, *pt, abi); } + // case for separate item and foreign-item tables + _ => fail ~"bad foreign item" } } with *visit::default_visitor() diff --git a/src/rustc/metadata/tydecode.rs b/src/rustc/metadata/tydecode.rs index 5b76e0da7f5..3677dce74d8 100644 --- a/src/rustc/metadata/tydecode.rs +++ b/src/rustc/metadata/tydecode.rs @@ -1,5 +1,8 @@ // Type decoding +// tjc note: Would be great to have a `match check` macro equivalent +// for some of these + import syntax::ast; import syntax::ast::*; import syntax::ast_util; @@ -103,10 +106,11 @@ fn parse_vstore(st: @pstate) -> ty::vstore { return ty::vstore_fixed(n); } - match check next(st) { + match next(st) { '~' => ty::vstore_uniq, '@' => ty::vstore_box, - '&' => ty::vstore_slice(parse_region(st)) + '&' => ty::vstore_slice(parse_region(st)), + _ => fail ~"parse_vstore: bad input" } } @@ -126,7 +130,7 @@ fn parse_substs(st: @pstate, conv: conv_did) -> ty::substs { } fn parse_bound_region(st: @pstate) -> ty::bound_region { - match check next(st) { + match next(st) { 's' => ty::br_self, 'a' => { let id = parse_int(st) as uint; @@ -138,12 +142,13 @@ fn parse_bound_region(st: @pstate) -> ty::bound_region { let id = parse_int(st); assert next(st) == '|'; ty::br_cap_avoid(id, @parse_bound_region(st)) - } + }, + _ => fail ~"parse_bound_region: bad input" } } fn parse_region(st: @pstate) -> ty::region { - match check next(st) { + match next(st) { 'b' => { ty::re_bound(parse_bound_region(st)) } @@ -163,13 +168,15 @@ fn parse_region(st: @pstate) -> ty::region { 't' => { ty::re_static } + _ => fail ~"parse_region: bad input" } } fn parse_opt(st: @pstate, f: fn() -> T) -> option { - match check next(st) { + match next(st) { 'n' => none, - 's' => some(f()) + 's' => some(f()), + _ => fail ~"parse_opt: bad input" } } @@ -183,7 +190,7 @@ fn parse_str(st: @pstate, term: char) -> ~str { } fn parse_ty(st: @pstate, conv: conv_did) -> ty::t { - match check next(st) { + match next(st) { 'n' => return ty::mk_nil(st.tcx), 'z' => return ty::mk_bot(st.tcx), 'b' => return ty::mk_bool(st.tcx), @@ -191,7 +198,7 @@ fn parse_ty(st: @pstate, conv: conv_did) -> ty::t { 'u' => return ty::mk_uint(st.tcx), 'l' => return ty::mk_float(st.tcx), 'M' => { - match check next(st) { + match next(st) { 'b' => return ty::mk_mach_uint(st.tcx, ast::ty_u8), 'w' => return ty::mk_mach_uint(st.tcx, ast::ty_u16), 'l' => return ty::mk_mach_uint(st.tcx, ast::ty_u32), @@ -201,7 +208,8 @@ fn parse_ty(st: @pstate, conv: conv_did) -> ty::t { 'L' => return ty::mk_mach_int(st.tcx, ast::ty_i32), 'D' => return ty::mk_mach_int(st.tcx, ast::ty_i64), 'f' => return ty::mk_mach_float(st.tcx, ast::ty_f32), - 'F' => return ty::mk_mach_float(st.tcx, ast::ty_f64) + 'F' => return ty::mk_mach_float(st.tcx, ast::ty_f64), + _ => fail ~"parse_ty: bad numeric type" } } 'c' => return ty::mk_char(st.tcx), @@ -270,10 +278,11 @@ fn parse_ty(st: @pstate, conv: conv_did) -> ty::t { } 'Y' => return ty::mk_type(st.tcx), 'C' => { - let ck = match check next(st) { + let ck = match next(st) { '&' => ty::ck_block, '@' => ty::ck_box, - '~' => ty::ck_uniq + '~' => ty::ck_uniq, + _ => fail ~"parse_ty: bad closure kind" }; return ty::mk_opaque_closure_ptr(st.tcx, ck); } @@ -354,11 +363,12 @@ fn parse_hex(st: @pstate) -> uint { } fn parse_purity(c: char) -> purity { - match check c { + match c { 'u' => unsafe_fn, 'p' => pure_fn, 'i' => impure_fn, - 'c' => extern_fn + 'c' => extern_fn, + _ => fail ~"parse_purity: bad purity" } } @@ -369,12 +379,13 @@ fn parse_ty_fn(st: @pstate, conv: conv_did) -> ty::fn_ty { assert (next(st) == '['); let mut inputs: ~[ty::arg] = ~[]; while peek(st) != ']' { - let mode = match check peek(st) { + let mode = match peek(st) { '&' => ast::by_mutbl_ref, '-' => ast::by_move, '+' => ast::by_copy, '=' => ast::by_ref, - '#' => ast::by_val + '#' => ast::by_val, + _ => fail ~"bad mode" }; st.pos += 1u; vec::push(inputs, {mode: ast::expl(mode), ty: parse_ty(st, conv)}); @@ -422,13 +433,14 @@ fn parse_bounds_data(data: @~[u8], start: uint, fn parse_bounds(st: @pstate, conv: conv_did) -> @~[ty::param_bound] { let mut bounds = ~[]; loop { - vec::push(bounds, match check next(st) { + vec::push(bounds, match next(st) { 'S' => ty::bound_send, 'C' => ty::bound_copy, 'K' => ty::bound_const, 'O' => ty::bound_owned, 'I' => ty::bound_trait(parse_ty(st, conv)), - '.' => break + '.' => break, + _ => fail ~"parse_bounds: bad bounds" }); } @bounds