about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGraydon Hoare <graydon@mozilla.com>2012-06-08 13:26:06 -0700
committerGraydon Hoare <graydon@mozilla.com>2012-06-08 13:26:15 -0700
commitdc94ccc4a4060e97389cd2cfd8a8cdb25668a3b1 (patch)
tree92330428401a84979b04a4baac03837157f99002
parent7a74545e9717ab0e85ab154e06810007b1de602f (diff)
downloadrust-dc94ccc4a4060e97389cd2cfd8a8cdb25668a3b1.tar.gz
rust-dc94ccc4a4060e97389cd2cfd8a8cdb25668a3b1.zip
More work on reflect, only missing enum and class substructures.
-rw-r--r--src/rustc/front/intrinsic.rs37
-rw-r--r--src/rustc/middle/trans/common.rs5
-rw-r--r--src/rustc/middle/trans/reflect.rs110
-rw-r--r--src/rustc/middle/trans/tvec.rs3
-rw-r--r--src/test/run-pass/reflect-visit-type.rs37
5 files changed, 183 insertions, 9 deletions
diff --git a/src/rustc/front/intrinsic.rs b/src/rustc/front/intrinsic.rs
index 4f24f9dccf2..cac3b4f5416 100644
--- a/src/rustc/front/intrinsic.rs
+++ b/src/rustc/front/intrinsic.rs
@@ -54,6 +54,43 @@ mod intrinsic {
         fn visit_leave_evec_slice(mtbl: uint) -> bool;
         fn visit_enter_evec_fixed(mtbl: uint, sz: uint) -> bool;
         fn visit_leave_evec_fixed(mtbl: uint, sz: uint) -> bool;
+
+        fn visit_enter_rec(n_fields: uint) -> bool;
+        fn visit_enter_rec_field(mtbl: uint, i: uint
+                                 /*, name: str/& */) -> bool;
+        fn visit_leave_rec_field(mtbl: uint, i: uint
+                                 /*, name: str/& */) -> bool;
+        fn visit_leave_rec(n_fields: uint) -> bool;
+
+        fn visit_enter_tup(n_fields: uint) -> bool;
+        fn visit_enter_tup_field(i: uint) -> bool;
+        fn visit_leave_tup_field(i: uint) -> bool;
+        fn visit_leave_tup(n_fields: uint) -> bool;
+
+        fn visit_enter_fn(purity: uint, proto: uint,
+                          n_inputs: uint, retstyle: uint) -> bool;
+        fn visit_enter_fn_input(i: uint, mode: uint) -> bool;
+        fn visit_leave_fn_input(i: uint, mode: uint) -> bool;
+        fn visit_enter_fn_output(retstyle: uint) -> bool;
+        fn visit_leave_fn_output(retstyle: uint) -> bool;
+        fn visit_leave_fn(purity: uint, proto: uint,
+                          n_inputs: uint, retstyle: uint) -> bool;
+
+        fn visit_class() -> bool;
+        fn visit_enum() -> bool;
+
+        fn visit_iface() -> bool;
+        fn visit_enter_res() -> bool;
+        fn visit_leave_res() -> bool;
+        fn visit_var() -> bool;
+        fn visit_var_integral() -> bool;
+        fn visit_param(i: uint) -> bool;
+        fn visit_self() -> bool;
+        fn visit_type() -> bool;
+        fn visit_opaque_box() -> bool;
+        fn visit_enter_constr() -> bool;
+        fn visit_leave_constr() -> bool;
+        fn visit_closure_ptr(ck: uint) -> bool;
     }
 
     #[abi = "rust-intrinsic"]
diff --git a/src/rustc/middle/trans/common.rs b/src/rustc/middle/trans/common.rs
index 3bd4838d220..da650eea792 100644
--- a/src/rustc/middle/trans/common.rs
+++ b/src/rustc/middle/trans/common.rs
@@ -815,6 +815,11 @@ fn C_cstr(cx: @crate_ctxt, s: str) -> ValueRef {
     ret g;
 }
 
+fn C_estr_slice(cx: @crate_ctxt, s: str) -> ValueRef {
+    let cs = llvm::LLVMConstPointerCast(C_cstr(cx, s), T_ptr(T_i8()));
+    C_struct([cs, C_uint(cx, str::len(s) + 1u /* +1 for null */)])
+}
+
 // Returns a Plain Old LLVM String:
 fn C_postr(s: str) -> ValueRef {
     ret str::as_c_str(s) {|buf|
diff --git a/src/rustc/middle/trans/reflect.rs b/src/rustc/middle/trans/reflect.rs
index cf929353ab4..12b1d28dbc9 100644
--- a/src/rustc/middle/trans/reflect.rs
+++ b/src/rustc/middle/trans/reflect.rs
@@ -42,12 +42,15 @@ impl methods for reflector {
                              abi::tydesc_field_visit_glue);
     }
 
+    fn bracketed_t(bracket_name: str, t: ty::t, extra: [ValueRef]) {
+        self.visit("enter_" + bracket_name, extra);
+        self.visit_tydesc(t);
+        self.visit("leave_" + bracket_name, extra);
+    }
+
     fn bracketed_mt(bracket_name: str, mt: ty::mt, extra: [ValueRef]) {
-        self.visit("enter_" + bracket_name,
-                   [self.c_uint(mt.mutbl as uint)] + extra);
-        self.visit_tydesc(mt.ty);
-        self.visit("leave_" + bracket_name,
-                   [self.c_uint(mt.mutbl as uint)] + extra);
+        self.bracketed_t(bracket_name, mt.ty,
+                         [self.c_uint(mt.mutbl as uint)] + extra);
     }
 
     fn vstore_name_and_extra(vstore: ty::vstore,
@@ -67,6 +70,10 @@ impl methods for reflector {
     // Entrypoint
     fn visit_ty(t: ty::t) {
 
+        let bcx = self.bcx;
+        #debug("reflect::visit_ty %s",
+               ty_to_str(bcx.ccx().tcx, t));
+
         alt ty::get(t).struct {
           ty::ty_bot { self.leaf("bot") }
           ty::ty_nil { self.leaf("nil") }
@@ -103,8 +110,97 @@ impl methods for reflector {
           ty::ty_ptr(mt) { self.bracketed_mt("ptr", mt, []) }
           ty::ty_rptr(_, mt) { self.bracketed_mt("rptr", mt, []) }
 
-          // FIXME: finish these.
-          _ { self.visit("bot", []) }
+          ty::ty_rec(fields) {
+            self.visit("enter_rec", [self.c_uint(vec::len(fields))]);
+            for fields.eachi {|i, field|
+                self.bracketed_mt("rec_field", field.mt,
+                                  [self.c_uint(i)
+                                   /*
+                                   FIXME: doesn't work presently.
+                                   C_estr_slice(self.bcx.ccx(),
+                                                field.ident)
+                                   */
+                                  ]);
+            }
+            self.visit("leave_rec", [self.c_uint(vec::len(fields))]);
+          }
+
+          ty::ty_tup(tys) {
+            self.visit("enter_tup", [self.c_uint(vec::len(tys))]);
+            for tys.eachi {|i, t|
+                self.bracketed_t("tup_field", t, [self.c_uint(i)]);
+            }
+            self.visit("leave_tup", [self.c_uint(vec::len(tys))]);
+          }
+
+          // FIXME: fetch constants out of intrinsic:: for the numbers.
+          ty::ty_fn(fty) {
+            let pureval = alt fty.purity {
+              ast::pure_fn { 0u }
+              ast::unsafe_fn { 1u }
+              ast::impure_fn { 2u }
+              ast::crust_fn { 3u }
+            };
+            let protoval = alt fty.proto {
+              ast::proto_bare { 0u }
+              ast::proto_any { 1u }
+              ast::proto_uniq { 2u }
+              ast::proto_box { 3u }
+              ast::proto_block { 4u }
+            };
+            let retval = alt fty.ret_style {
+              ast::noreturn { 0u }
+              ast::return_val { 1u }
+            };
+            let extra = [self.c_uint(pureval),
+                         self.c_uint(protoval),
+                         self.c_uint(vec::len(fty.inputs)),
+                         self.c_uint(retval)];
+            self.visit("enter_fn", extra);
+            for fty.inputs.eachi {|i, arg|
+                let modeval = alt arg.mode {
+                  ast::infer(_) { 0u }
+                  ast::expl(e) {
+                    alt e {
+                      ast::by_ref { 1u }
+                      ast::by_val { 2u }
+                      ast::by_mutbl_ref { 3u }
+                      ast::by_move { 4u }
+                      ast::by_copy { 5u }
+                    }
+                  }
+                };
+                self.bracketed_t("fn_input", arg.ty,
+                                 [self.c_uint(i),
+                                  self.c_uint(modeval)]);
+            }
+            self.bracketed_t("fn_output", fty.output,
+                             [self.c_uint(retval)]);
+            self.visit("leave_fn", extra);
+          }
+
+          // FIXME: these need substructure-walks
+          ty::ty_class(_, _) { self.leaf("class") }
+          ty::ty_enum(_, _) { self.leaf("enum") }
+
+          // Miscallaneous extra types
+          ty::ty_iface(_, _) { self.leaf("iface") }
+          ty::ty_res(_, t, _) { self.bracketed_t("res", t, []) }
+          ty::ty_var(_) { self.leaf("var") }
+          ty::ty_var_integral(_) { self.leaf("var_integral") }
+          ty::ty_param(n, _) { self.visit("param", [self.c_uint(n)]) }
+          ty::ty_self { self.leaf("self") }
+          ty::ty_type { self.leaf("type") }
+          ty::ty_opaque_box { self.leaf("opaque_box") }
+          ty::ty_constr(t, _) { self.bracketed_t("constr", t, []) }
+          ty::ty_opaque_closure_ptr(ck) {
+            let ckval = alt ck {
+              ty::ck_block { 0u }
+              ty::ck_box { 1u }
+              ty::ck_uniq { 2u }
+            };
+            self.visit("closure_ptr", [self.c_uint(ckval)])
+          }
         }
     }
 }
diff --git a/src/rustc/middle/trans/tvec.rs b/src/rustc/middle/trans/tvec.rs
index e53b5ff4886..fa21927d743 100644
--- a/src/rustc/middle/trans/tvec.rs
+++ b/src/rustc/middle/trans/tvec.rs
@@ -276,8 +276,7 @@ fn trans_estr(bcx: block, s: str, vstore: ast::vstore,
       ast::vstore_slice(_) {
         // "hello"  =>  (*i8, 6u) in llvm
         #debug("trans_estr: slice '%s'", s);
-        let cs = PointerCast(bcx, C_cstr(ccx, s), T_ptr(T_i8()));
-        C_struct([cs, C_uint(ccx, str::len(s) + 1u /* +1 for null */)])
+        C_estr_slice(ccx, s)
       }
 
       ast::vstore_uniq {
diff --git a/src/test/run-pass/reflect-visit-type.rs b/src/test/run-pass/reflect-visit-type.rs
index 7cd373756f7..599e8fd99b7 100644
--- a/src/test/run-pass/reflect-visit-type.rs
+++ b/src/test/run-pass/reflect-visit-type.rs
@@ -79,6 +79,43 @@ impl of intrinsic::ty_visitor for my_visitor {
     fn visit_leave_evec_slice(_mtbl: uint) -> bool { true }
     fn visit_enter_evec_fixed(_mtbl: uint, _sz: uint) -> bool { true }
     fn visit_leave_evec_fixed(_mtbl: uint, _sz: uint) -> bool { true }
+
+    fn visit_enter_rec(_n_fields: uint) -> bool { true }
+    fn visit_enter_rec_field(_mtbl: uint, _i: uint
+                             /*,name: str/&*/) -> bool { true }
+    fn visit_leave_rec_field(_mtbl: uint, _i: uint
+                             /*,name: str/&*/) -> bool { true }
+    fn visit_leave_rec(_n_fields: uint) -> bool { true }
+
+    fn visit_enter_tup(_n_fields: uint) -> bool { true }
+    fn visit_enter_tup_field(_i: uint) -> bool { true }
+    fn visit_leave_tup_field(_i: uint) -> bool { true }
+    fn visit_leave_tup(_n_fields: uint) -> bool { true }
+
+    fn visit_enter_fn(_purity: uint, _proto: uint,
+                      _n_inputs: uint, _retstyle: uint) -> bool { true }
+    fn visit_enter_fn_input(_i: uint, _mode: uint) -> bool { true }
+    fn visit_leave_fn_input(_i: uint, _mode: uint) -> bool { true }
+    fn visit_enter_fn_output(_retstyle: uint) -> bool { true }
+    fn visit_leave_fn_output(_retstyle: uint) -> bool { true }
+    fn visit_leave_fn(_purity: uint, _proto: uint,
+                      _n_inputs: uint, _retstyle: uint) -> bool { true }
+
+    fn visit_class() -> bool { true }
+    fn visit_enum() -> bool { true }
+
+    fn visit_iface() -> bool { true }
+    fn visit_enter_res() -> bool { true }
+    fn visit_leave_res() -> bool { true }
+    fn visit_var() -> bool { true }
+    fn visit_var_integral() -> bool { true }
+    fn visit_param(_i: uint) -> bool { true }
+    fn visit_self() -> bool { true }
+    fn visit_type() -> bool { true }
+    fn visit_opaque_box() -> bool { true }
+    fn visit_enter_constr() -> bool { true }
+    fn visit_leave_constr() -> bool { true }
+    fn visit_closure_ptr(_ck: uint) -> bool { true }
 }
 
 fn main() {