]> git.lizzy.rs Git - rust.git/commitdiff
methods work
authorTim Chevalier <chevalier@alum.wellesley.edu>
Wed, 21 Mar 2012 19:42:34 +0000 (12:42 -0700)
committerTim Chevalier <chevalier@alum.wellesley.edu>
Wed, 21 Mar 2012 20:53:21 +0000 (13:53 -0700)
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

src/rustc/metadata/csearch.rs
src/rustc/metadata/decoder.rs
src/rustc/middle/trans/base.rs
src/rustc/middle/ty.rs
src/rustc/middle/typeck.rs
src/rustc/syntax/ast_util.rs
src/test/auxiliary/cci_class_2.rs [new file with mode: 0644]
src/test/run-pass/class-method-cross-crate.rs [new file with mode: 0644]
src/test/run-pass/class-methods.rs [new file with mode: 0644]
src/test/run-pass/classes-simple-method.rs

index 1d8965897ad4feef39ddfd73819e26c45d696225..58192a8f163b6d7a1058fdb8bf7779867bfa63b5 100644 (file)
@@ -13,6 +13,7 @@
 
 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);
index 8916d32d3937a92206e5ab8a5f8db5ae7c490ed2..f4e213e5157157a001b7108b3f612670b15c2435 100644 (file)
@@ -17,6 +17,7 @@
 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 }
index c0dbdc962104b0ee9d7ebf8ad32d96eb3f7f3e4c..648ac24208a576b3ec56b19131fc8992e4ac87bb 100644 (file)
@@ -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 */ }
     }
index 4666487a238f1ebaa1faf52eb6cdd6e2f1235713..47e60cc530b829884758f56460ac7afb7954a8c7 100644 (file)
@@ -6,6 +6,7 @@
 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 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 {
index e55656d2b2f161e191f972ee0a89271acd1fb90d..eb4f87c824fd8f3bf92dcdc899604b41c4ba9321 100644 (file)
@@ -893,11 +893,20 @@ fn get_enum_variant_types(tcx: ty::ctxt, enum_ty: ty::t,
         }
     }
     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 @@ fn convert(tcx: ty::ctxt, it: @ast::item) {
               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;
     }
index 5625fecb95399db426dc016c23b8c036c1de811f..7af080a2535e1016742116c4a6e38d0195105ad3 100644 (file)
@@ -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 {
diff --git a/src/test/auxiliary/cci_class_2.rs b/src/test/auxiliary/cci_class_2.rs
new file mode 100644 (file)
index 0000000..50a5bf1
--- /dev/null
@@ -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() {}
+}
+
+}
diff --git a/src/test/run-pass/class-method-cross-crate.rs b/src/test/run-pass/class-method-cross-crate.rs
new file mode 100644 (file)
index 0000000..1d79fa3
--- /dev/null
@@ -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();
+}
diff --git a/src/test/run-pass/class-methods.rs b/src/test/run-pass/class-methods.rs
new file mode 100644 (file)
index 0000000..e9587b7
--- /dev/null
@@ -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);
+}
index 2c7c2c7c480d944c59f55466fc94ea93e43f67c2..62084958d5a17e6d0d384f671c95c647757cb41f 100644 (file)
@@ -1,4 +1,3 @@
-// xfail-test
 class cat {
   priv {
     let mutable meows : uint;
@@ -9,10 +8,6 @@
   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);
 }