export get_symbol;
export get_class_fields;
+// export get_class_method_ids;
export get_field_type;
export get_type_param_count;
export lookup_defs;
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);
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;
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)));
}
@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 }
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 */ }
}
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::*;
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;
}
}
-// 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 {
}
}
-// 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 {
}
}
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)});
}
}
}
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
}
}
-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);
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;
}
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 {
--- /dev/null
+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() {}
+}
+
+}
--- /dev/null
+// 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();
+}
--- /dev/null
+// 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);
+}
-// xfail-test
class cat {
priv {
let mutable meows : uint;
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() {
assert(nyan.how_hungry == 99);
assert(kitty.how_hungry == 2);
nyan.speak();
- // assert(nyan.meow_count() == 53u);
}