Skip to content

Commit b06dc88

Browse files
committed
Class methods WIP
In particular, use the ast::method type to represent a class method, and try to reuse as much iface code as possible. (This makes sense now since I'll be allowing polymorphic class methods.)
1 parent 855c99e commit b06dc88

File tree

17 files changed

+384
-259
lines changed

17 files changed

+384
-259
lines changed

src/rustc/driver/session.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,14 @@ impl session for session {
110110
}
111111
}
112112

113+
// Seems out of place, but it uses session, so I'm putting it here
114+
fn expect<T: copy>(sess: session, opt: option<T>, msg: fn() -> str) -> T {
115+
alt opt {
116+
some(t) { t }
117+
none { sess.bug(msg()); }
118+
}
119+
}
120+
113121
fn building_library(req_crate_type: crate_type, crate: @ast::crate,
114122
testing: bool) -> bool {
115123
alt req_crate_type {

src/rustc/metadata/csearch.rs

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
11
// Searching for information from the cstore
22

3+
import std::{ebml};
34
import syntax::ast;
45
import syntax::ast_util;
56
import middle::{ty, ast_map};
67
import option::{some, none};
78
import driver::session;
9+
import driver::session::expect;
810
import middle::trans::common::maps;
11+
import common::*;
912
import std::map::hashmap;
1013

1114
export get_symbol;
12-
export get_class_items;
15+
export get_class_fields;
16+
export get_field_type;
1317
export get_type_param_count;
1418
export lookup_defs;
1519
export lookup_method_purity;
@@ -120,10 +124,10 @@ fn get_iface_methods(tcx: ty::ctxt, def: ast::def_id) -> @[ty::method] {
120124
decoder::get_iface_methods(cdata, def.node, tcx)
121125
}
122126

123-
fn get_class_items(tcx: ty::ctxt, def: ast::def_id) -> [@ty::class_item_ty] {
127+
fn get_class_fields(tcx: ty::ctxt, def: ast::def_id) -> [ty::field_ty] {
124128
let cstore = tcx.sess.cstore;
125129
let cdata = cstore::get_crate_data(cstore, def.crate);
126-
decoder::get_class_items(cdata, def.node, tcx)
130+
decoder::get_class_fields(tcx, cdata, def.node)
127131
}
128132

129133
fn get_type(tcx: ty::ctxt, def: ast::def_id) -> ty::ty_param_bounds_and_ty {
@@ -132,6 +136,27 @@ fn get_type(tcx: ty::ctxt, def: ast::def_id) -> ty::ty_param_bounds_and_ty {
132136
decoder::get_type(cdata, def.node, tcx)
133137
}
134138

139+
/* FIXME: Refactor */
140+
fn get_field_type(tcx: ty::ctxt, class_id: ast::def_id,
141+
def: ast::def_id) -> ty::ty_param_bounds_and_ty {
142+
let cstore = tcx.sess.cstore;
143+
let cdata = cstore::get_crate_data(cstore, class_id.crate);
144+
let all_items = ebml::get_doc(ebml::doc(cdata.data), tag_items);
145+
#debug("Looking up %?", class_id);
146+
let class_doc = expect(tcx.sess,
147+
decoder::maybe_find_item(class_id.node, all_items),
148+
{|| #fmt("get_field_type: class ID %? not found",
149+
class_id)});
150+
#debug("looking up %? : %?", def, class_doc);
151+
let the_field = expect(tcx.sess,
152+
decoder::maybe_find_item(def.node, class_doc),
153+
{|| #fmt("get_field_type: in class %?, field ID %? not found",
154+
class_id, def)});
155+
#debug("got field data %?", the_field);
156+
let ty = decoder::item_type(def, the_field, tcx, cdata);
157+
ret {bounds: @[], ty: ty};
158+
}
159+
135160
fn get_impl_iface(tcx: ty::ctxt, def: ast::def_id)
136161
-> option<ty::t> {
137162
let cstore = tcx.sess.cstore;

src/rustc/metadata/decoder.rs

Lines changed: 19 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@ import tydecode::{parse_ty_data, parse_def_id, parse_bounds_data,
1414
import syntax::print::pprust;
1515
import cmd=cstore::crate_metadata;
1616
import middle::trans::common::maps;
17+
import util::ppaux::ty_to_str;
1718

18-
export get_class_items;
19+
export get_class_fields;
1920
export get_symbol;
2021
export get_enum_variants;
2122
export get_type;
@@ -35,6 +36,8 @@ export get_impls_for_mod;
3536
export get_iface_methods;
3637
export get_crate_module_paths;
3738
export get_item_path;
39+
export maybe_find_item; // sketchy
40+
export item_type; // sketchy
3841
export maybe_get_item_ast;
3942
export item_is_intrinsic;
4043

@@ -110,9 +113,9 @@ fn item_parent_item(d: ebml::doc) -> option<ast::def_id> {
110113
found
111114
}
112115

113-
fn class_field_id(d: ebml::doc) -> ast::def_id {
116+
fn class_field_id(d: ebml::doc, cdata: cmd) -> ast::def_id {
114117
let tagdoc = ebml::get_doc(d, tag_def_id);
115-
ret parse_def_id(ebml::doc_data(tagdoc));
118+
ret translate_def_id(cdata, parse_def_id(ebml::doc_data(tagdoc)));
116119
}
117120

118121
fn variant_disr_val(d: ebml::doc) -> option<int> {
@@ -406,37 +409,26 @@ fn get_iface_methods(cdata: cmd, id: ast::node_id, tcx: ty::ctxt)
406409
}
407410

408411
/* Take a node ID for a class, return a vector of the class's
409-
member types */
410-
fn get_class_items(cdata: cmd, id: ast::node_id, tcx: ty::ctxt)
411-
-> [@ty::class_item_ty] {
412+
field names/IDs */
413+
fn get_class_fields(tcx: ty::ctxt,
414+
cdata: cmd, id: ast::node_id) -> [ty::field_ty] {
412415
let data = cdata.data;
413416
let item = lookup_item(id, data), result = [];
414-
#debug("get_class_items: %s", item_name(item));
415-
#debug("item: %?", item);
416-
// right tag?
417-
ebml::tagged_docs(item, tag_items_class_member) {|an_item|
417+
ebml::tagged_docs(item, tag_items_data_item) {|an_item|
418418
let fam = item_family(an_item);
419-
let decl = alt check fam {
420-
'g' {
421-
let name = item_name(an_item);
422-
#debug("why hello there! %s", name);
423-
let ty = doc_type(an_item, tcx, cdata);
424-
let did = class_field_id(an_item);
425-
{ident: name,
426-
id: did.node,
427-
contents: ty::var_ty(ty)}
428-
}
429-
_ {
430-
fail; // FIXME
431-
}
432-
};
433-
result += [@decl];
419+
alt fam {
420+
'g' {
421+
let name = item_name(an_item);
422+
let _ty = doc_type(an_item, tcx, cdata);
423+
let did = class_field_id(an_item, cdata);
424+
result += [{ident: name, id: did}];
425+
}
426+
_ { /* this only handles fields */}
427+
}
434428
}
435429
result
436430
}
437431

438-
439-
440432
fn family_has_type_params(fam_ch: char) -> bool {
441433
alt check fam_ch {
442434
'c' | 'T' | 'm' | 'n' | 'g' | 'h' { false }

src/rustc/metadata/encoder.rs

Lines changed: 93 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,8 @@ fn encode_class_item_paths(ebml_w: ebml::writer,
8282
priv { cont; }
8383
pub {
8484
let (id, ident) = alt it.node.decl {
85-
instance_var(v, _, _, vid) { (vid, v) }
86-
class_method(it) { (it.id, it.ident) }
85+
instance_var(v, _, _, vid) { (vid, v) }
86+
class_method(it) { (it.id, it.ident) }
8787
};
8888
add_to_index(ebml_w, path, index, ident);
8989
encode_named_def_id(ebml_w, ident, local_def(id));
@@ -145,18 +145,18 @@ fn encode_module_item_paths(ebml_w: ebml::writer, ecx: @encode_ctxt,
145145
ebml_w.end_tag();
146146
}
147147
item_class(tps,items,ctor) {
148-
add_to_index(ebml_w, path, index, it.ident);
149-
ebml_w.start_tag(tag_paths_data_item);
150-
encode_name(ebml_w, it.ident);
151-
encode_def_id(ebml_w, local_def(it.id));
152-
ebml_w.end_tag();
153-
ebml_w.start_tag(tag_paths);
154-
add_to_index(ebml_w, path, index, it.ident);
155-
#debug("ctor id: %d", ctor.node.id);
156-
encode_named_def_id(ebml_w, it.ident, local_def(ctor.node.id));
157-
encode_class_item_paths(ebml_w, items, path + [it.ident],
148+
add_to_index(ebml_w, path, index, it.ident);
149+
ebml_w.start_tag(tag_paths_data_item);
150+
encode_name(ebml_w, it.ident);
151+
encode_def_id(ebml_w, local_def(it.id));
152+
ebml_w.end_tag();
153+
ebml_w.start_tag(tag_paths);
154+
add_to_index(ebml_w, path, index, it.ident);
155+
#debug("ctor id: %d", ctor.node.id);
156+
encode_named_def_id(ebml_w, it.ident, local_def(ctor.node.id));
157+
encode_class_item_paths(ebml_w, items, path + [it.ident],
158158
index);
159-
ebml_w.end_tag();
159+
ebml_w.end_tag();
160160
}
161161
item_enum(variants, tps) {
162162
add_to_index(ebml_w, path, index, it.ident);
@@ -252,7 +252,12 @@ fn encode_type(ecx: @encode_ctxt, ebml_w: ebml::writer, typ: ty::t) {
252252

253253
fn encode_symbol(ecx: @encode_ctxt, ebml_w: ebml::writer, id: node_id) {
254254
ebml_w.start_tag(tag_items_data_item_symbol);
255-
ebml_w.writer.write(str::bytes(ecx.ccx.item_symbols.get(id)));
255+
let sym = alt ecx.ccx.item_symbols.find(id) {
256+
some(x) { x }
257+
none { ecx.ccx.tcx.sess.bug(#fmt("encode_symbol: \
258+
id not found %d", id)); }
259+
};
260+
ebml_w.writer.write(str::bytes(sym));
256261
ebml_w.end_tag();
257262
}
258263

@@ -346,43 +351,53 @@ fn encode_info_for_mod(ecx: @encode_ctxt, ebml_w: ebml::writer, md: _mod,
346351
ebml_w.end_tag();
347352
}
348353

354+
/* Returns an index of items in this class */
349355
fn encode_info_for_class(ecx: @encode_ctxt, ebml_w: ebml::writer,
350356
id: node_id, path: ast_map::path, name: ident,
351-
tps: [ty_param], items: [@class_item]) {
357+
tps: [ty_param], items: [@class_item])
358+
-> [entry<int>] {
359+
let index = @mutable [];
360+
352361
let tcx = ecx.ccx.tcx;
353362
encode_def_id(ebml_w, local_def(id));
354363
encode_family(ebml_w, 'C');
355364
encode_type_param_bounds(ebml_w, ecx, tps);
356365
encode_type(ecx, ebml_w, node_id_to_type(tcx, id));
357366
encode_name(ebml_w, name);
367+
encode_path(ebml_w, path, ast_map::path_name(name));
358368

359369
for ci in items {
360-
/* We encode both private and public fields -- need to include
361-
private fields to get the offsets right */
362-
ebml_w.start_tag(tag_items_class_member);
363-
alt ci.node.decl {
364-
instance_var(nm, _, _, id) {
365-
#debug("encode_info_for_class: doing %s %d", nm, id);
366-
encode_family(ebml_w, 'g');
367-
encode_name(ebml_w, nm);
368-
encode_type(ecx, ebml_w, node_id_to_type(tcx, id));
369-
/* TODO: mutability */
370-
encode_def_id(ebml_w, local_def(id));
371-
}
372-
class_method(it) {
373-
encode_family(ebml_w, 'h');
374-
encode_name(ebml_w, it.ident);
375-
alt it.node {
376-
item_fn(fdecl, tps, _) {
377-
encode_info_for_fn(ecx, ebml_w, it.id, it.ident,
378-
path, none, tps, fdecl);
379-
}
380-
_ { fail; /* TODO */ }
381-
}
382-
}
383-
}
384-
ebml_w.end_tag();
370+
/* We encode both private and public fields -- need to include
371+
private fields to get the offsets right */
372+
alt ci.node.decl {
373+
instance_var(nm, _, _, id) {
374+
*index += [{val: id, pos: ebml_w.writer.tell()}];
375+
ebml_w.start_tag(tag_items_data_item);
376+
#debug("encode_info_for_class: doing %s %d", nm, id);
377+
encode_family(ebml_w, 'g');
378+
encode_name(ebml_w, nm);
379+
encode_path(ebml_w, path, ast_map::path_name(nm));
380+
encode_type(ecx, ebml_w, node_id_to_type(tcx, id));
381+
/* TODO: mutability */
382+
encode_def_id(ebml_w, local_def(id));
383+
}
384+
class_method(m) {
385+
*index += [{val: m.id, pos: ebml_w.writer.tell()}];
386+
ebml_w.start_tag(tag_items_data_item);
387+
encode_family(ebml_w, 'h');
388+
encode_name(ebml_w, m.ident);
389+
let impl_path = path + [ast_map::path_name(m.ident)];
390+
/*
391+
Recall methods are (currently) monomorphic, and we don't
392+
repeat the class's ty params in the method decl
393+
*/
394+
encode_info_for_method(ecx, ebml_w, impl_path,
395+
should_inline(m.attrs), id, m, []);
396+
}
397+
}
398+
ebml_w.end_tag();
385399
}
400+
*index
386401
}
387402

388403
fn encode_info_for_fn(ecx: @encode_ctxt, ebml_w: ebml::writer,
@@ -408,6 +423,28 @@ fn encode_info_for_fn(ecx: @encode_ctxt, ebml_w: ebml::writer,
408423
ebml_w.end_tag();
409424
}
410425

426+
fn encode_info_for_method(ecx: @encode_ctxt, ebml_w: ebml::writer,
427+
impl_path: ast_map::path, should_inline: bool,
428+
parent_id: node_id,
429+
m: @method, all_tps: [ty_param]) {
430+
#debug("encode_info_for_method: %d %s", m.id, m.ident);
431+
ebml_w.start_tag(tag_items_data_item);
432+
encode_def_id(ebml_w, local_def(m.id));
433+
encode_family(ebml_w, purity_fn_family(m.decl.purity));
434+
encode_type_param_bounds(ebml_w, ecx, all_tps);
435+
encode_type(ecx, ebml_w, node_id_to_type(ecx.ccx.tcx, m.id));
436+
encode_name(ebml_w, m.ident);
437+
encode_path(ebml_w, impl_path, ast_map::path_name(m.ident));
438+
if all_tps.len() > 0u || should_inline {
439+
astencode::encode_inlined_item(
440+
ecx, ebml_w, impl_path,
441+
ii_method(local_def(parent_id), m));
442+
} else {
443+
encode_symbol(ecx, ebml_w, m.id);
444+
}
445+
ebml_w.end_tag();
446+
}
447+
411448
fn purity_fn_family(p: purity) -> char {
412449
alt p {
413450
unsafe_fn { 'u' }
@@ -417,15 +454,17 @@ fn purity_fn_family(p: purity) -> char {
417454
}
418455
}
419456

420-
fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
421-
index: @mutable [entry<int>], path: ast_map::path) {
422457

423-
fn should_inline(attrs: [attribute]) -> bool {
424-
alt attr::find_inline_attr(attrs) {
425-
attr::ia_none { false }
426-
attr::ia_hint | attr::ia_always { true }
427-
}
458+
fn should_inline(attrs: [attribute]) -> bool {
459+
alt attr::find_inline_attr(attrs) {
460+
attr::ia_none { false }
461+
attr::ia_hint | attr::ia_always { true }
428462
}
463+
}
464+
465+
466+
fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
467+
index: @mutable [entry<int>], path: ast_map::path) {
429468

430469
let tcx = ecx.ccx.tcx;
431470
let must_write = alt item.node { item_enum(_, _) { true } _ { false } };
@@ -494,11 +533,12 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
494533
path, index, tps);
495534
}
496535
item_class(tps,items,ctor) {
497-
/* We're not forgetting about the ctor here! It gets
498-
encoded elsewhere */
499536
ebml_w.start_tag(tag_items_data_item);
500-
encode_info_for_class(ecx, ebml_w, item.id, path, item.ident,
501-
tps, items);
537+
let idx = encode_info_for_class(ecx, ebml_w, item.id, path,
538+
item.ident, tps, items);
539+
/* each class must have its own index */
540+
let bkts = create_index(idx, hash_node_id);
541+
encode_index(ebml_w, bkts, write_int);
502542
ebml_w.end_tag();
503543
}
504544
item_res(_, tps, _, _, ctor_id) {
@@ -553,21 +593,8 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
553593
let impl_path = path + [ast_map::path_name(item.ident)];
554594
for m in methods {
555595
*index += [{val: m.id, pos: ebml_w.writer.tell()}];
556-
ebml_w.start_tag(tag_items_data_item);
557-
encode_def_id(ebml_w, local_def(m.id));
558-
encode_family(ebml_w, purity_fn_family(m.decl.purity));
559-
encode_type_param_bounds(ebml_w, ecx, tps + m.tps);
560-
encode_type(ecx, ebml_w, node_id_to_type(tcx, m.id));
561-
encode_name(ebml_w, m.ident);
562-
encode_path(ebml_w, impl_path, ast_map::path_name(m.ident));
563-
if tps.len() > 0u || m.tps.len() > 0u || should_inline(m.attrs) {
564-
astencode::encode_inlined_item(
565-
ecx, ebml_w, impl_path,
566-
ii_method(local_def(item.id), m));
567-
} else {
568-
encode_symbol(ecx, ebml_w, m.id);
569-
}
570-
ebml_w.end_tag();
596+
encode_info_for_method(ecx, ebml_w, impl_path,
597+
should_inline(m.attrs), item.id, m, tps + m.tps);
571598
}
572599
}
573600
item_iface(tps, ms) {

0 commit comments

Comments
 (0)