diff options
| author | Kevin Atkinson <kevina@cs.utah.edu> | 2012-01-10 14:50:40 -0700 |
|---|---|---|
| committer | Graydon Hoare <graydon@mozilla.com> | 2012-01-10 15:59:57 -0800 |
| commit | 08abf8d37fa549ebc67f80d80530f4aa43d716e4 (patch) | |
| tree | f6c9bce62c494a37d989d07be4661f57c0c7eba3 /src/comp/metadata | |
| parent | d0fe6723fc2f431205092bda9ec399d932081bd0 (diff) | |
| download | rust-08abf8d37fa549ebc67f80d80530f4aa43d716e4.tar.gz rust-08abf8d37fa549ebc67f80d80530f4aa43d716e4.zip | |
Support explicit discriminant numbers on tag variants.
Addresses issue #1393. For now disallow disr. values unless all variants use nullary contractors (i.e. "enum-like"). Disr. values are now encoded in the crate metadata, but only when it will differ from the inferred value based on the order.
Diffstat (limited to 'src/comp/metadata')
| -rw-r--r-- | src/comp/metadata/common.rs | 3 | ||||
| -rw-r--r-- | src/comp/metadata/decoder.rs | 20 | ||||
| -rw-r--r-- | src/comp/metadata/encoder.rs | 12 |
3 files changed, 34 insertions, 1 deletions
diff --git a/src/comp/metadata/common.rs b/src/comp/metadata/common.rs index db415d5d31a..e1c05bf2c9f 100644 --- a/src/comp/metadata/common.rs +++ b/src/comp/metadata/common.rs @@ -70,6 +70,9 @@ const tag_item_method: uint = 0x31u; const tag_impl_iface: uint = 0x32u; const tag_impl_iface_did: uint = 0x33u; +// discriminator value for variants +const tag_disr_val: uint = 0x34u; + // djb's cdb hashes. fn hash_node_id(&&node_id: int) -> uint { ret 177573u ^ (node_id as uint); } diff --git a/src/comp/metadata/decoder.rs b/src/comp/metadata/decoder.rs index a253e116fe8..c40e459bb5c 100644 --- a/src/comp/metadata/decoder.rs +++ b/src/comp/metadata/decoder.rs @@ -88,6 +88,17 @@ fn variant_tag_id(d: ebml::doc) -> ast::def_id { ret parse_def_id(ebml::doc_data(tagdoc)); } +fn variant_disr_val(d: ebml::doc) -> option::t<int> { + alt ebml::maybe_get_doc(d, tag_disr_val) { + some(val_doc) { + let val_buf = ebml::doc_data(val_doc); + let val = int::parse_buf(val_buf, 10u); + ret some(val); + } + _ { ret none;} + } +} + fn doc_type(doc: ebml::doc, tcx: ty::ctxt, cdata: cmd) -> ty::t { let tp = ebml::get_doc(doc, tag_items_data_item_type); parse_ty_data(tp.data, cdata.cnum, tp.start, tcx, {|did| @@ -240,6 +251,7 @@ fn get_tag_variants(cdata: cmd, id: ast::node_id, tcx: ty::ctxt) let item = find_item(id, items); let infos: [ty::variant_info] = []; let variant_ids = tag_variant_ids(item, cdata); + let disr_val = 0; for did: ast::def_id in variant_ids { let item = find_item(did.node, items); let ctor_ty = item_type(item, tcx, cdata); @@ -250,7 +262,13 @@ fn get_tag_variants(cdata: cmd, id: ast::node_id, tcx: ty::ctxt) } _ { /* Nullary tag variant. */ } } - infos += [@{args: arg_tys, ctor_ty: ctor_ty, id: did}]; + alt variant_disr_val(item) { + some(val) { disr_val = val; } + _ { /* empty */ } + } + infos += [@{args: arg_tys, ctor_ty: ctor_ty, id: did, + disr_val: disr_val}]; + disr_val += 1; } ret infos; } diff --git a/src/comp/metadata/encoder.rs b/src/comp/metadata/encoder.rs index de1f9eacbcb..e666d204020 100644 --- a/src/comp/metadata/encoder.rs +++ b/src/comp/metadata/encoder.rs @@ -228,6 +228,12 @@ fn encode_discriminant(ecx: @encode_ctxt, ebml_w: ebml::writer, id: node_id) { ebml::end_tag(ebml_w); } +fn encode_disr_val(_ecx: @encode_ctxt, ebml_w: ebml::writer, disr_val: int) { + ebml::start_tag(ebml_w, tag_disr_val); + ebml_w.writer.write(str::bytes(int::to_str(disr_val,10u))); + ebml::end_tag(ebml_w); +} + fn encode_tag_id(ebml_w: ebml::writer, id: def_id) { ebml::start_tag(ebml_w, tag_items_data_item_tag_id); ebml_w.writer.write(str::bytes(def_to_str(id))); @@ -237,6 +243,7 @@ fn encode_tag_id(ebml_w: ebml::writer, id: def_id) { fn encode_tag_variant_info(ecx: @encode_ctxt, ebml_w: ebml::writer, id: node_id, variants: [variant], &index: [entry<int>], ty_params: [ty_param]) { + let disr_val = 0; for variant: variant in variants { index += [{val: variant.node.id, pos: ebml_w.writer.tell()}]; ebml::start_tag(ebml_w, tag_items_data_item); @@ -249,8 +256,13 @@ fn encode_tag_variant_info(ecx: @encode_ctxt, ebml_w: ebml::writer, encode_symbol(ecx, ebml_w, variant.node.id); } encode_discriminant(ecx, ebml_w, variant.node.id); + if variant.node.disr_val != disr_val { + encode_disr_val(ecx, ebml_w, variant.node.disr_val); + disr_val = variant.node.disr_val; + } encode_type_param_bounds(ebml_w, ecx, ty_params); ebml::end_tag(ebml_w); + disr_val += 1; } } |
