Skip to content

Commit 1680ccc

Browse files
committed
Classes WIP
Cross-crate metadata for classes works well enough that programs with classes in other crates compile successfully, but output wrong results. Checking in work so far to avoid merge hassles. (Tests are xfailed.)
1 parent 47d468f commit 1680ccc

File tree

18 files changed

+381
-116
lines changed

18 files changed

+381
-116
lines changed

src/rustc/metadata/common.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ const tag_path: uint = 0x40u;
7878
const tag_path_len: uint = 0x41u;
7979
const tag_path_elt_mod: uint = 0x42u;
8080
const tag_path_elt_name: uint = 0x43u;
81+
const tag_items_class_member: uint = 0x44u;
8182

8283
// used to encode crate_ctxt side tables
8384
enum astencode_tag { // Reserves 0x50 -- 0x6f

src/rustc/metadata/csearch.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import middle::trans::common::maps;
99
import std::map::hashmap;
1010

1111
export get_symbol;
12+
export get_class_items;
1213
export get_type_param_count;
1314
export lookup_defs;
1415
export lookup_method_purity;
@@ -35,6 +36,7 @@ fn get_type_param_count(cstore: cstore::cstore, def: ast::def_id) -> uint {
3536
fn lookup_defs(cstore: cstore::cstore, cnum: ast::crate_num,
3637
path: [ast::ident]) -> [ast::def] {
3738
let result = [];
39+
#debug("lookup_defs: path = %? cnum = %?", path, cnum);
3840
for (c, data, def) in resolve_path(cstore, cnum, path) {
3941
result += [decoder::lookup_def(c, data, def)];
4042
}
@@ -116,6 +118,12 @@ fn get_iface_methods(tcx: ty::ctxt, def: ast::def_id) -> @[ty::method] {
116118
decoder::get_iface_methods(cdata, def.node, tcx)
117119
}
118120

121+
fn get_class_items(tcx: ty::ctxt, def: ast::def_id) -> [@ty::class_item_ty] {
122+
let cstore = tcx.sess.cstore;
123+
let cdata = cstore::get_crate_data(cstore, def.crate);
124+
decoder::get_class_items(cdata, def.node, tcx)
125+
}
126+
119127
fn get_type(tcx: ty::ctxt, def: ast::def_id) -> ty::ty_param_bounds_and_ty {
120128
let cstore = tcx.sess.cstore;
121129
let cdata = cstore::get_crate_data(cstore, def.crate);

src/rustc/metadata/cstore.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -162,10 +162,9 @@ fn get_dep_hashes(cstore: cstore) -> [str] {
162162
}
163163

164164
fn get_path(cstore: cstore, d: ast::def_id) -> [str] {
165-
alt p(cstore).mod_path_map.find(d) {
166-
option::some(ds) { str::split_str(ds, "::") }
167-
option::none { [] }
168-
}
165+
// let f = bind str::split_str(_, "::");
166+
option::maybe([], p(cstore).mod_path_map.find(d),
167+
{|ds| str::split_str(ds, "::")})
169168
}
170169
// Local Variables:
171170
// mode: rust

src/rustc/metadata/decoder.rs

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,13 @@ import front::attr;
99
import middle::ty;
1010
import middle::ast_map;
1111
import common::*;
12-
import tydecode::{parse_ty_data, parse_def_id, parse_bounds_data};
12+
import tydecode::{parse_ty_data, parse_def_id, parse_bounds_data,
13+
parse_ident};
1314
import syntax::print::pprust;
1415
import cmd=cstore::crate_metadata;
1516
import middle::trans::common::maps;
1617

18+
export get_class_items;
1719
export get_symbol;
1820
export get_enum_variants;
1921
export get_type;
@@ -84,7 +86,10 @@ fn find_item(item_id: int, items: ebml::doc) -> ebml::doc {
8486
// to the item data.
8587
fn lookup_item(item_id: int, data: @[u8]) -> ebml::doc {
8688
let items = ebml::get_doc(ebml::doc(data), tag_items);
87-
ret find_item(item_id, items);
89+
alt maybe_find_item(item_id, items) {
90+
none { fail(#fmt("lookup_item: id not found: %d", item_id)); }
91+
some(d) { d }
92+
}
8893
}
8994

9095
fn item_family(item: ebml::doc) -> char {
@@ -105,6 +110,11 @@ fn item_parent_item(d: ebml::doc) -> option<ast::def_id> {
105110
found
106111
}
107112

113+
fn class_field_id(d: ebml::doc) -> ast::def_id {
114+
let tagdoc = ebml::get_doc(d, tag_def_id);
115+
ret parse_def_id(ebml::doc_data(tagdoc));
116+
}
117+
108118
fn variant_disr_val(d: ebml::doc) -> option<int> {
109119
option::chain(ebml::maybe_get_doc(d, tag_disr_val)) {|val_doc|
110120
int::parse_buf(ebml::doc_data(val_doc), 10u)
@@ -178,6 +188,7 @@ fn resolve_path(path: [ast::ident], data: @[u8]) -> [ast::def_id] {
178188
let paths = ebml::get_doc(md, tag_paths);
179189
let eqer = bind eq_item(_, s);
180190
let result: [ast::def_id] = [];
191+
#debug("resolve_path: looking up %s", s);
181192
for doc: ebml::doc in lookup_hash(paths, eqer, hash_path(s)) {
182193
let did_doc = ebml::get_doc(doc, tag_def_id);
183194
result += [parse_def_id(ebml::doc_data(did_doc))];
@@ -226,6 +237,7 @@ fn lookup_def(cnum: ast::crate_num, data: @[u8], did_: ast::def_id) ->
226237
// We treat references to enums as references to types.
227238
alt check fam_ch {
228239
'c' { ast::def_const(did) }
240+
'C' { ast::def_class(did) }
229241
'u' { ast::def_fn(did, ast::unsafe_fn) }
230242
'f' { ast::def_fn(did, ast::impure_fn) }
231243
'p' { ast::def_fn(did, ast::pure_fn) }
@@ -393,10 +405,48 @@ fn get_iface_methods(cdata: cmd, id: ast::node_id, tcx: ty::ctxt)
393405
@result
394406
}
395407

408+
/*
409+
FIXME
410+
This is not working. metadata is broken -- fields get encoded correctly,
411+
but not decoded. look at this code, see what it's actually writing out
412+
also see what "data" is
413+
*/
414+
fn get_class_items(cdata: cmd, id: ast::node_id, tcx: ty::ctxt)
415+
-> [@ty::class_item_ty] {
416+
let data = cdata.data;
417+
let item = lookup_item(id, data), result = [];
418+
#debug("get_class_items: %s", item_name(item));
419+
#debug("item: %?", item);
420+
// right tag?
421+
ebml::tagged_docs(item, tag_items_class_member) {|an_item|
422+
let fam = item_family(an_item);
423+
let decl = alt check fam {
424+
'g' {
425+
let name = item_name(an_item);
426+
#debug("why hello there! %s", name);
427+
let ty = doc_type(an_item, tcx, cdata);
428+
let did = class_field_id(an_item);
429+
{ident: name,
430+
id: did.node,
431+
contents: ty::var_ty(ty)}
432+
}
433+
_ {
434+
fail; // FIXME
435+
}
436+
};
437+
result += [@decl];
438+
}
439+
result
440+
}
441+
442+
443+
396444
fn family_has_type_params(fam_ch: char) -> bool {
397445
alt check fam_ch {
398-
'c' | 'T' | 'm' | 'n' { false }
399-
'f' | 'u' | 'p' | 'F' | 'U' | 'P' | 'y' | 't' | 'v' | 'i' | 'I' { true }
446+
'c' | 'T' | 'm' | 'n' | 'g' | 'h' { false }
447+
'f' | 'u' | 'p' | 'F' | 'U' | 'P' | 'y' | 't' | 'v' | 'i' | 'I' | 'C'
448+
| 'a'
449+
{ true }
400450
}
401451
}
402452

@@ -434,6 +484,7 @@ fn item_family_to_str(fam: char) -> str {
434484
'v' { ret "enum"; }
435485
'i' { ret "impl"; }
436486
'I' { ret "iface"; }
487+
'C' { ret "class"; }
437488
}
438489
}
439490

src/rustc/metadata/encoder.rs

Lines changed: 122 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,23 @@ fn encode_native_module_item_paths(ebml_w: ebml::writer, nmod: native_mod,
7676
}
7777
}
7878

79+
fn encode_class_item_paths(ebml_w: ebml::writer,
80+
items: [@class_item], path: [str], &index: [entry<str>]) {
81+
for it in items {
82+
alt it.node.privacy {
83+
priv { cont; }
84+
pub {
85+
let (id, ident) = alt it.node.decl {
86+
instance_var(v, _, _, vid) { (vid, v) }
87+
class_method(it) { (it.id, it.ident) }
88+
};
89+
add_to_index(ebml_w, path, index, ident);
90+
encode_named_def_id(ebml_w, ident, local_def(id));
91+
}
92+
}
93+
}
94+
}
95+
7996
fn encode_module_item_paths(ebml_w: ebml::writer, ecx: @encode_ctxt,
8097
module: _mod, path: [str], &index: [entry<str>]) {
8198
// FIXME factor out add_to_index/start/encode_name/encode_def_id/end ops
@@ -128,8 +145,20 @@ fn encode_module_item_paths(ebml_w: ebml::writer, ecx: @encode_ctxt,
128145
encode_def_id(ebml_w, local_def(it.id));
129146
ebml_w.end_tag();
130147
}
131-
item_class(_,_,_) {
132-
fail "encode: implement item_class";
148+
item_class(tps,items,ctor) {
149+
add_to_index(ebml_w, path, index, it.ident);
150+
ebml_w.start_tag(tag_paths_data_item);
151+
encode_name(ebml_w, it.ident);
152+
encode_def_id(ebml_w, local_def(it.id));
153+
ebml_w.end_tag();
154+
ebml_w.start_tag(tag_paths);
155+
/* a bit confused -- adding the same ident twice
156+
(once for class, once for ctor) */
157+
add_to_index(ebml_w, path, index, it.ident);
158+
encode_named_def_id(ebml_w, it.ident, local_def(ctor.node.id));
159+
encode_class_item_paths(ebml_w, items, path + [it.ident],
160+
index);
161+
ebml_w.end_tag();
133162
}
134163
item_enum(variants, tps) {
135164
add_to_index(ebml_w, path, index, it.ident);
@@ -312,13 +341,80 @@ fn encode_info_for_mod(ecx: @encode_ctxt, ebml_w: ebml::writer, md: _mod,
312341
}
313342
}
314343
}
315-
_ { ecx.ccx.tcx.sess.bug("encode_info_for_mod: \
316-
undocumented invariant"); }
344+
_ { ecx.ccx.tcx.sess.bug(#fmt("encode_info_for_mod: empty impl_map \
345+
entry for %?", path)); }
317346
}
318347
encode_path(ebml_w, path, ast_map::path_mod(name));
319348
ebml_w.end_tag();
320349
}
321350

351+
fn encode_info_for_class(ecx: @encode_ctxt, ebml_w: ebml::writer,
352+
id: node_id, path: ast_map::path, name: ident,
353+
tps: [ty_param], items: [@class_item]) {
354+
let tcx = ecx.ccx.tcx;
355+
encode_def_id(ebml_w, local_def(id));
356+
encode_family(ebml_w, 'C');
357+
encode_type_param_bounds(ebml_w, ecx, tps);
358+
encode_type(ecx, ebml_w, node_id_to_type(tcx, id));
359+
encode_name(ebml_w, name);
360+
361+
for ci in items {
362+
alt ci.node.privacy {
363+
pub {
364+
ebml_w.start_tag(tag_items_class_member); // ???
365+
alt ci.node.decl {
366+
instance_var(nm, _, _, id) {
367+
#debug("encode_info_for_class: doing %s", nm);
368+
encode_family(ebml_w, 'g');
369+
encode_name(ebml_w, nm);
370+
encode_type(ecx, ebml_w, node_id_to_type(tcx, id));
371+
/* TODO: mutability */
372+
encode_def_id(ebml_w, local_def(id));
373+
}
374+
class_method(it) {
375+
encode_family(ebml_w, 'h');
376+
encode_name(ebml_w, it.ident);
377+
alt it.node {
378+
item_fn(fdecl, tps, _) {
379+
encode_info_for_fn(ecx, ebml_w, it.id, it.ident,
380+
path, none, tps, fdecl);
381+
}
382+
_ { fail; /* TODO */ }
383+
}
384+
}
385+
}
386+
ebml_w.end_tag();
387+
}
388+
priv {
389+
/* don't export it, then! */
390+
}
391+
}
392+
}
393+
}
394+
395+
fn encode_info_for_fn(ecx: @encode_ctxt, ebml_w: ebml::writer,
396+
id: node_id, ident: ident, path: ast_map::path,
397+
item: option<@item>, tps: [ty_param], decl: fn_decl) {
398+
ebml_w.start_tag(tag_items_data_item);
399+
encode_def_id(ebml_w, local_def(id));
400+
encode_family(ebml_w, purity_fn_family(decl.purity));
401+
encode_type_param_bounds(ebml_w, ecx, tps);
402+
let its_ty = node_id_to_type(ecx.ccx.tcx, id);
403+
#debug("fn name = %s ty = %s", ident,
404+
util::ppaux::ty_to_str(ecx.ccx.tcx, its_ty));
405+
encode_type(ecx, ebml_w, its_ty);
406+
encode_path(ebml_w, path, ast_map::path_name(ident));
407+
alt item {
408+
some(it) {
409+
astencode::encode_inlined_item(ecx, ebml_w, path, ii_item(it));
410+
}
411+
none {
412+
encode_symbol(ecx, ebml_w, id);
413+
}
414+
}
415+
ebml_w.end_tag();
416+
}
417+
322418
fn purity_fn_family(p: purity) -> char {
323419
alt p {
324420
unsafe_fn { 'u' }
@@ -404,8 +500,13 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
404500
encode_enum_variant_info(ecx, ebml_w, item.id, variants,
405501
path, index, tps);
406502
}
407-
item_class(_,_,_) {
408-
fail "encode: implement item_class";
503+
item_class(tps,items,_) {
504+
/* We're not forgetting about the ctor here! It gets
505+
encoded elsewhere */
506+
ebml_w.start_tag(tag_items_data_item);
507+
encode_info_for_class(ecx, ebml_w, item.id, path, item.ident,
508+
tps, items);
509+
ebml_w.end_tag();
409510
}
410511
item_res(_, tps, _, _, ctor_id) {
411512
let fn_ty = node_id_to_type(tcx, ctor_id);
@@ -539,6 +640,21 @@ fn encode_info_for_items(ecx: @encode_ctxt, ebml_w: ebml::writer,
539640
ast_map::node_item(_, pt) {
540641
encode_info_for_item(ecx, ebml_w, i, index, *pt);
541642
}
643+
/* TODO: encode info for class items! */
644+
/* encode ctor, then encode items */
645+
ast_map::node_ctor(i, path) {
646+
alt i.node {
647+
item_class(tps, _, ctor) {
648+
#debug("class, encoding a fn: %d", ctor.node.id);
649+
/* this is assuming that ctors aren't inlined...
650+
probably shouldn't assume that */
651+
encode_info_for_fn(ecx, ebml_w, ctor.node.id, i.ident,
652+
*path, none, tps, ctor.node.dec)
653+
}
654+
_ { /* TODO: should handle item_res, probably */ }
655+
}
656+
}
657+
542658
}
543659
},
544660
visit_native_item: {|ni, cx, v|

src/rustc/metadata/tydecode.rs

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import syntax::ast_util::respan;
77
import middle::ty;
88
import std::map::hashmap;
99

10-
export parse_ty_data, parse_def_id;
10+
export parse_ty_data, parse_def_id, parse_ident;
1111
export parse_bounds_data;
1212

1313
// Compact string representation for ty::t values. API ty_str &
@@ -303,6 +303,17 @@ fn parse_ty(st: @pstate, conv: conv_did) -> ty::t {
303303
ty::mk_with_id(st.tcx, inner, def)
304304
}
305305
'B' { ty::mk_opaque_box(st.tcx) }
306+
'a' {
307+
#debug("saw a class");
308+
assert (next(st) == '[');
309+
#debug("saw a [");
310+
let did = parse_def(st, conv);
311+
#debug("parsed a def_id %?", did);
312+
let params: [ty::t] = [];
313+
while peek(st) != ']' { params += [parse_ty(st, conv)]; }
314+
assert (next(st) == ']');
315+
ret ty::mk_class(st.tcx, did, params);
316+
}
306317
c { #error("unexpected char in type string: %c", c); fail;}
307318
}
308319
}
@@ -387,8 +398,18 @@ fn parse_def_id(buf: [u8]) -> ast::def_id {
387398
for b: u8 in crate_part { crate_part_vec += [b]; }
388399
for b: u8 in def_part { def_part_vec += [b]; }
389400

390-
let crate_num = option::get(uint::parse_buf(crate_part_vec, 10u)) as int;
391-
let def_num = option::get(uint::parse_buf(def_part_vec, 10u)) as int;
401+
let crate_num = alt uint::parse_buf(crate_part_vec, 10u) {
402+
some(cn) { cn as int }
403+
none { fail (#fmt("internal error: parse_def_id: error parsing %? \
404+
as crate",
405+
crate_part_vec)); }
406+
};
407+
let def_num = alt uint::parse_buf(def_part_vec, 10u) {
408+
some(dn) { dn as int }
409+
none { fail (#fmt("internal error: parse_def_id: error parsing %? \
410+
as id",
411+
def_part_vec)); }
412+
};
392413
ret {crate: crate_num, node: def_num};
393414
}
394415

src/rustc/metadata/tyencode.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -214,10 +214,15 @@ fn enc_sty(w: io::writer, cx: @ctxt, st: ty::sty) {
214214
}
215215
ty::ty_opaque_box { w.write_char('B'); }
216216
ty::ty_class(def, tys) {
217-
w.write_str("c[");
218-
w.write_str(cx.ds(def));
219-
w.write_char('|');
217+
#debug("~~~~ %s", "a[");
218+
w.write_str("a[");
219+
let s = cx.ds(def);
220+
#debug("~~~~ %s", s);
221+
w.write_str(s);
222+
#debug("~~~~ %s", "|");
223+
w.write_str("|");
220224
for t: ty::t in tys { enc_ty(w, cx, t); }
225+
#debug("~~~~ %s", "]");
221226
w.write_char(']');
222227
}
223228
}

0 commit comments

Comments
 (0)