methods work
Cross-crate method calls don't work yet. Added run-pass/class-method-cross-crate to test that, but it's xfailed References to fields within methods don't work yet. Added run-pass/class-methods to test that, but it's also xfailed
This commit is contained in:
parent
3e47442471
commit
30c272cb3a
10 changed files with 162 additions and 39 deletions
|
|
@ -13,6 +13,7 @@ import std::map::hashmap;
|
|||
|
||||
export get_symbol;
|
||||
export get_class_fields;
|
||||
// export get_class_method_ids;
|
||||
export get_field_type;
|
||||
export get_type_param_count;
|
||||
export lookup_defs;
|
||||
|
|
@ -127,9 +128,17 @@ fn get_iface_methods(tcx: ty::ctxt, def: ast::def_id) -> @[ty::method] {
|
|||
fn get_class_fields(tcx: ty::ctxt, def: ast::def_id) -> [ty::field_ty] {
|
||||
let cstore = tcx.sess.cstore;
|
||||
let cdata = cstore::get_crate_data(cstore, def.crate);
|
||||
decoder::get_class_fields(tcx, cdata, def.node)
|
||||
decoder::get_class_fields(cdata, def.node)
|
||||
}
|
||||
|
||||
/*
|
||||
fn get_class_method_ids(tcx: ty::ctxt, def: ast::def_id) -> [ty::field_ty] {
|
||||
let cstore = tcx.sess.cstore;
|
||||
let cdata = cstore::get_crate_data(cstore, def.crate);
|
||||
decoder::get_class_method_ids(cdata, def.node)
|
||||
}
|
||||
*/
|
||||
|
||||
fn get_type(tcx: ty::ctxt, def: ast::def_id) -> ty::ty_param_bounds_and_ty {
|
||||
let cstore = tcx.sess.cstore;
|
||||
let cdata = cstore::get_crate_data(cstore, def.crate);
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import middle::trans::common::maps;
|
|||
import util::ppaux::ty_to_str;
|
||||
|
||||
export get_class_fields;
|
||||
// export get_class_method_ids;
|
||||
export get_symbol;
|
||||
export get_enum_variants;
|
||||
export get_type;
|
||||
|
|
@ -113,7 +114,7 @@ fn item_parent_item(d: ebml::doc) -> option<ast::def_id> {
|
|||
found
|
||||
}
|
||||
|
||||
fn class_field_id(d: ebml::doc, cdata: cmd) -> ast::def_id {
|
||||
fn class_member_id(d: ebml::doc, cdata: cmd) -> ast::def_id {
|
||||
let tagdoc = ebml::get_doc(d, tag_def_id);
|
||||
ret translate_def_id(cdata, parse_def_id(ebml::doc_data(tagdoc)));
|
||||
}
|
||||
|
|
@ -408,27 +409,36 @@ fn get_iface_methods(cdata: cmd, id: ast::node_id, tcx: ty::ctxt)
|
|||
@result
|
||||
}
|
||||
|
||||
/* Take a node ID for a class, return a vector of the class's
|
||||
field names/IDs */
|
||||
fn get_class_fields(tcx: ty::ctxt,
|
||||
cdata: cmd, id: ast::node_id) -> [ty::field_ty] {
|
||||
// Helper function that gets either fields or methods
|
||||
fn get_class_members(cdata: cmd, id: ast::node_id,
|
||||
family: char) -> [ty::field_ty] {
|
||||
let data = cdata.data;
|
||||
let item = lookup_item(id, data), result = [];
|
||||
ebml::tagged_docs(item, tag_items_data_item) {|an_item|
|
||||
let fam = item_family(an_item);
|
||||
alt fam {
|
||||
'g' {
|
||||
let name = item_name(an_item);
|
||||
let _ty = doc_type(an_item, tcx, cdata);
|
||||
let did = class_field_id(an_item, cdata);
|
||||
result += [{ident: name, id: did}];
|
||||
}
|
||||
_ { /* this only handles fields */}
|
||||
if item_family(an_item) == family {
|
||||
let name = item_name(an_item);
|
||||
let did = class_member_id(an_item, cdata);
|
||||
result += [{ident: name, id: did}];
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
|
||||
/* Take a node ID for a class, return a vector of the class's
|
||||
field names/IDs */
|
||||
fn get_class_fields(cdata: cmd, id: ast::node_id) -> [ty::field_ty] {
|
||||
get_class_members(cdata, id, 'g')
|
||||
}
|
||||
|
||||
/*
|
||||
/* Take a node ID for a class, return a vector of the class's
|
||||
method names/IDs */
|
||||
fn get_class_method_ids(cdata: cmd, id: ast::node_id) -> [ty::field_ty] {
|
||||
get_class_members(cdata, id, 'h')
|
||||
}
|
||||
*/
|
||||
|
||||
fn family_has_type_params(fam_ch: char) -> bool {
|
||||
alt check fam_ch {
|
||||
'c' | 'T' | 'm' | 'n' | 'g' | 'h' { false }
|
||||
|
|
|
|||
|
|
@ -4194,7 +4194,10 @@ fn trans_item(ccx: @crate_ctxt, item: ast::item) {
|
|||
trans_fn(ccx, *path + [path_name(item.ident)], ctor.node.dec,
|
||||
ctor_body__, llctor_decl, no_self,
|
||||
none, ctor.node.id, some(rslt_expr));
|
||||
// TODO: translate methods!
|
||||
// Translate methods
|
||||
let (_, ms) = ast_util::split_class_items(items);
|
||||
// not sure how this is going to work what with "self" and fields
|
||||
impl::trans_impl(ccx, *path, item.ident, ms, tps);
|
||||
}
|
||||
_ {/* fall through */ }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import session::session;
|
|||
import syntax::ast;
|
||||
import syntax::ast::*;
|
||||
import syntax::ast_util;
|
||||
import syntax::ast_util::{is_local, split_class_items};
|
||||
import syntax::codemap::span;
|
||||
import metadata::csearch;
|
||||
import util::common::*;
|
||||
|
|
@ -41,6 +42,7 @@ export get_element_type;
|
|||
export is_binopable;
|
||||
export is_pred_ty;
|
||||
export lookup_class_fields;
|
||||
export lookup_class_method_by_name;
|
||||
export lookup_field_type;
|
||||
export lookup_item_type;
|
||||
export method;
|
||||
|
|
@ -2523,7 +2525,7 @@ fn lookup_field_type(tcx: ctxt, class_id: def_id, id: def_id) -> ty::t {
|
|||
}
|
||||
}
|
||||
|
||||
// Look up the list of item types for a given class
|
||||
// Look up the list of field names and IDs for a given class
|
||||
// Fails if the id is not bound to a class.
|
||||
fn lookup_class_fields(cx: ctxt, did: ast::def_id) -> [field_ty] {
|
||||
if did.crate == ast::local_crate {
|
||||
|
|
@ -2544,7 +2546,41 @@ fn lookup_class_fields(cx: ctxt, did: ast::def_id) -> [field_ty] {
|
|||
}
|
||||
}
|
||||
|
||||
// must be called after typechecking?
|
||||
// Look up the list of method names and IDs for a given class
|
||||
// Fails if the id is not bound to a class.
|
||||
fn lookup_class_method_ids(cx: ctxt, did: ast::def_id)
|
||||
: is_local(did) -> [{name: ident, id: node_id}] {
|
||||
alt cx.items.find(did.node) {
|
||||
some(ast_map::node_item(@{node: item_class(_,items,_), _}, _)) {
|
||||
let (_,ms) = split_class_items(items);
|
||||
vec::map(ms, {|m| {name: m.ident, id: m.id}})
|
||||
}
|
||||
_ {
|
||||
cx.sess.bug("lookup_class_method_ids: id not bound to a class");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Given a class def_id and a method name, return the method's
|
||||
def_id. Needed so we can do static dispatch for methods */
|
||||
fn lookup_class_method_by_name(cx:ctxt, did: ast::def_id, name: ident,
|
||||
sp: span) ->
|
||||
def_id {
|
||||
if check is_local(did) {
|
||||
let ms = lookup_class_method_ids(cx, did);
|
||||
for m in ms {
|
||||
if m.name == name {
|
||||
ret ast_util::local_def(m.id);
|
||||
}
|
||||
}
|
||||
cx.sess.span_fatal(sp, #fmt("Class doesn't have a method named %s",
|
||||
name));
|
||||
}
|
||||
else {
|
||||
csearch::get_impl_method(cx.sess.cstore, did, name)
|
||||
}
|
||||
}
|
||||
|
||||
fn class_field_tys(items: [@class_item]) -> [field_ty] {
|
||||
let rslt = [];
|
||||
for it in items {
|
||||
|
|
|
|||
|
|
@ -893,11 +893,20 @@ mod collect {
|
|||
}
|
||||
}
|
||||
fn ensure_iface_methods(tcx: ty::ctxt, id: ast::node_id) {
|
||||
fn store_methods<T>(tcx: ty::ctxt, id: ast::node_id,
|
||||
stuff: [T], f: fn@(T) -> ty::method) {
|
||||
ty::store_iface_methods(tcx, id, @vec::map(stuff, f));
|
||||
}
|
||||
|
||||
alt check tcx.items.get(id) {
|
||||
ast_map::node_item(@{node: ast::item_iface(_, ms), _}, _) {
|
||||
ty::store_iface_methods(tcx, id, @vec::map(ms, {|m|
|
||||
ty_of_ty_method(tcx, m_collect, m)
|
||||
}));
|
||||
store_methods::<ast::ty_method>(tcx, id, ms, {|m|
|
||||
ty_of_ty_method(tcx, m_collect, m)});
|
||||
}
|
||||
ast_map::node_item(@{node: ast::item_class(_,its,_), _}, _) {
|
||||
let (_,ms) = split_class_items(its);
|
||||
store_methods::<@ast::method>(tcx, id, ms, {|m|
|
||||
ty_of_method(tcx, m_collect, m)});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1038,13 +1047,17 @@ mod collect {
|
|||
write_ty(tcx, ctor.node.id, t_ctor);
|
||||
tcx.tcache.insert(local_def(ctor.node.id),
|
||||
{bounds: tpt.bounds, ty: t_ctor});
|
||||
ensure_iface_methods(tcx, it.id);
|
||||
/* FIXME: check for proper public/privateness */
|
||||
// Write the type of each of the members
|
||||
let (fields, methods) = split_class_items(members);
|
||||
for f in fields {
|
||||
convert_class_item(tcx, f);
|
||||
}
|
||||
convert_methods(tcx, methods, @[], none);
|
||||
let selfty = ty::mk_class(tcx, local_def(it.id),
|
||||
mk_ty_params(tcx, tps).params);
|
||||
// The selfty is just the class type
|
||||
convert_methods(tcx, methods, @[], some(selfty));
|
||||
}
|
||||
_ {
|
||||
// This call populates the type cache with the converted type
|
||||
|
|
@ -1854,13 +1867,13 @@ fn lookup_method(fcx: @fn_ctxt, expr: @ast::expr, node_id: ast::node_id,
|
|||
}
|
||||
}
|
||||
|
||||
enum method_parent {
|
||||
cls(ast::def_id),
|
||||
enum method_kind {
|
||||
cls(ast::def_id), // *method* id (in both cases)
|
||||
an_iface(ast::def_id)
|
||||
}
|
||||
|
||||
fn lookup_method_inner_(tcx: ty::ctxt, ms: [ty::method],
|
||||
tps: [ty::t], parent: method_parent, name: ast::ident, sp: span)
|
||||
tps: [ty::t], parent: method_kind, name: ast::ident, sp: span)
|
||||
-> option<{method_ty: ty::t, n_tps: uint, substs: [ty::t],
|
||||
origin: method_origin, self_sub: option<self_subst>}> {
|
||||
#debug("lookup_method_inner_: %? %? %s", ms, parent, name);
|
||||
|
|
@ -1878,13 +1891,19 @@ fn lookup_method_inner_(tcx: ty::ctxt, ms: [ty::method],
|
|||
boxed iface");
|
||||
}
|
||||
ret some({method_ty: fty,
|
||||
n_tps: vec::len(*m.tps),
|
||||
substs: tps,
|
||||
origin: alt parent {
|
||||
cls(did) { method_static(did) }
|
||||
an_iface(did) { method_iface(did, i) }
|
||||
},
|
||||
self_sub: none});
|
||||
n_tps: vec::len(*m.tps),
|
||||
substs: tps,
|
||||
origin: alt parent {
|
||||
cls(parent_id) {
|
||||
// look up method named <name>
|
||||
// its id is did
|
||||
let m_declared = ty::lookup_class_method_by_name(tcx,
|
||||
parent_id, name, sp);
|
||||
method_static(m_declared)
|
||||
}
|
||||
an_iface(did) { method_iface(did, i) }
|
||||
},
|
||||
self_sub: none});
|
||||
}
|
||||
i += 1u;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,9 @@ fn path_name(p: @path) -> str { path_name_i(p.node.idents) }
|
|||
|
||||
fn path_name_i(idents: [ident]) -> str { str::connect(idents, "::") }
|
||||
|
||||
fn local_def(id: node_id) -> def_id { ret {crate: local_crate, node: id}; }
|
||||
fn local_def(id: node_id) -> def_id { {crate: local_crate, node: id} }
|
||||
|
||||
pure fn is_local(did: ast::def_id) -> bool { did.crate == local_crate }
|
||||
|
||||
fn stmt_id(s: stmt) -> node_id {
|
||||
alt s.node {
|
||||
|
|
|
|||
15
src/test/auxiliary/cci_class_2.rs
Normal file
15
src/test/auxiliary/cci_class_2.rs
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
mod kitties {
|
||||
|
||||
class cat {
|
||||
priv {
|
||||
let mutable meows : uint;
|
||||
}
|
||||
|
||||
let how_hungry : int;
|
||||
|
||||
new(in_x : uint, in_y : int) { meows = in_x; how_hungry = in_y; }
|
||||
|
||||
fn speak() {}
|
||||
}
|
||||
|
||||
}
|
||||
13
src/test/run-pass/class-method-cross-crate.rs
Normal file
13
src/test/run-pass/class-method-cross-crate.rs
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
// xfail-test
|
||||
// xfail-fast
|
||||
// aux-build:cci_class_2.rs
|
||||
use cci_class;
|
||||
import cci_class::kitties::*;
|
||||
|
||||
fn main() {
|
||||
let nyan : cat = cat(52u, 99);
|
||||
let kitty = cat(1000u, 2);
|
||||
assert(nyan.how_hungry == 99);
|
||||
assert(kitty.how_hungry == 2);
|
||||
nyan.speak();
|
||||
}
|
||||
22
src/test/run-pass/class-methods.rs
Normal file
22
src/test/run-pass/class-methods.rs
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
// xfail-test
|
||||
class cat {
|
||||
priv {
|
||||
let mutable meows : uint;
|
||||
}
|
||||
|
||||
let how_hungry : int;
|
||||
|
||||
new(in_x : uint, in_y : int) { meows = in_x; how_hungry = in_y; }
|
||||
|
||||
fn speak() { meows += 1u; }
|
||||
fn meow_count() -> uint { meows }
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let nyan : cat = cat(52u, 99);
|
||||
let kitty = cat(1000u, 2);
|
||||
assert(nyan.how_hungry == 99);
|
||||
assert(kitty.how_hungry == 2);
|
||||
nyan.speak();
|
||||
assert(nyan.meow_count() == 53u);
|
||||
}
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
// xfail-test
|
||||
class cat {
|
||||
priv {
|
||||
let mutable meows : uint;
|
||||
|
|
@ -9,10 +8,6 @@ class cat {
|
|||
new(in_x : uint, in_y : int) { meows = in_x; how_hungry = in_y; }
|
||||
|
||||
fn speak() {}
|
||||
/*
|
||||
fn speak() { meows += 1u; }
|
||||
fn meow_count() -> uint { meows }
|
||||
*/
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
|
@ -21,5 +16,4 @@ fn main() {
|
|||
assert(nyan.how_hungry == 99);
|
||||
assert(kitty.how_hungry == 2);
|
||||
nyan.speak();
|
||||
// assert(nyan.meow_count() == 53u);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue