about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGraydon Hoare <graydon@mozilla.com>2012-05-10 17:18:04 -0700
committerGraydon Hoare <graydon@mozilla.com>2012-05-10 17:18:04 -0700
commitc23d6a50d786e926d001423f36dc43fe480acbae (patch)
treead2c2fad91816d82340d09c4019961c75611c8b3
parent664b82a6b79f3aea1d8d00c1e5e7e1e89fcaf71a (diff)
downloadrust-c23d6a50d786e926d001423f36dc43fe480acbae.tar.gz
rust-c23d6a50d786e926d001423f36dc43fe480acbae.zip
Preliminary groundwork for intrinsic module, reflection interface.
-rw-r--r--src/librustsyntax/codemap.rs6
-rw-r--r--src/librustsyntax/ext/base.rs2
-rw-r--r--src/librustsyntax/ext/include.rs59
-rw-r--r--src/librustsyntax/parse.rs12
-rw-r--r--src/librustsyntax/rustsyntax.rc1
-rw-r--r--src/rustc/driver/driver.rs4
-rw-r--r--src/rustc/front/intrinsic.rs140
-rw-r--r--src/rustc/front/intrinsic_inject.rs30
-rw-r--r--src/rustc/middle/trans/native.rs23
-rw-r--r--src/rustc/middle/typeck.rs13
-rw-r--r--src/rustc/rustc.rc1
11 files changed, 291 insertions, 0 deletions
diff --git a/src/librustsyntax/codemap.rs b/src/librustsyntax/codemap.rs
index b8579f6733d..e119ae840e6 100644
--- a/src/librustsyntax/codemap.rs
+++ b/src/librustsyntax/codemap.rs
@@ -12,6 +12,7 @@ export mk_substr_filename;
 export lookup_char_pos;
 export adjust_span;
 export span_to_str;
+export span_to_filename;
 export span_to_lines;
 export file_lines;
 export get_line;
@@ -170,6 +171,11 @@ fn span_to_str(sp: span, cm: codemap) -> str {
 
 type file_lines = {file: filemap, lines: [uint]};
 
+fn span_to_filename(sp: span, cm: codemap::codemap) -> filename {
+    let lo = lookup_char_pos(cm, sp.lo);
+    ret lo.file.name;
+}
+
 fn span_to_lines(sp: span, cm: codemap::codemap) -> @file_lines {
     let lo = lookup_char_pos(cm, sp.lo);
     let hi = lookup_char_pos(cm, sp.hi);
diff --git a/src/librustsyntax/ext/base.rs b/src/librustsyntax/ext/base.rs
index a4ca819d6b6..170ba112e31 100644
--- a/src/librustsyntax/ext/base.rs
+++ b/src/librustsyntax/ext/base.rs
@@ -31,6 +31,8 @@ fn syntax_expander_table() -> hashmap<str, syntax_extension> {
     syntax_expanders.insert("auto_serialize",
                             item_decorator(ext::auto_serialize::expand));
     syntax_expanders.insert("env", builtin(ext::env::expand_syntax_ext));
+    syntax_expanders.insert("include_str",
+                            builtin(ext::include::str::expand_syntax_ext));
     syntax_expanders.insert("macro",
                             macro_defining(ext::simplext::add_new_extension));
     syntax_expanders.insert("concat_idents",
diff --git a/src/librustsyntax/ext/include.rs b/src/librustsyntax/ext/include.rs
new file mode 100644
index 00000000000..a31d2835e8a
--- /dev/null
+++ b/src/librustsyntax/ext/include.rs
@@ -0,0 +1,59 @@
+/*
+ * The compiler code necessary to support the #include and #include_str
+ * extensions.  Eventually this should all get sucked into either the compiler
+ * syntax extension plugin interface.
+ */
+
+import diagnostic::span_handler;
+import base::*;
+export str;
+
+// FIXME: implement plain #include, restarting the parser on the included
+// file. Currently only implement #include_str.
+
+mod str {
+    fn expand_syntax_ext(cx: ext_ctxt, sp: codemap::span, arg: ast::mac_arg,
+                         _body: ast::mac_body) -> @ast::expr {
+        let arg = get_mac_arg(cx,sp,arg);
+        let args: [@ast::expr] =
+            alt arg.node {
+              ast::expr_vec(elts, _) { elts }
+              _ {
+                cx.span_fatal(sp, "#include_str requires arguments \
+                                   of the form `[...]`.")
+              }
+            };
+        if vec::len::<@ast::expr>(args) != 1u {
+            cx.span_fatal(sp, "malformed #include_str call");
+        }
+        let mut path = expr_to_str(cx, args[0], "#include_str requires \
+                                                 a string");
+
+        // NB: relative paths are resolved relative to the compilation unit
+        if !path::path_is_absolute(path) {
+            let cu = codemap::span_to_filename(sp, cx.codemap());
+            let dir = path::dirname(cu);
+            path = path::connect(dir, path);
+        }
+
+        alt io::read_whole_file_str(path) {
+          result::ok(src) { ret make_new_str(cx, sp, src); }
+          result::err(e) {
+            cx.parse_sess().span_diagnostic.handler().fatal(e)
+          }
+        }
+    }
+}
+
+fn make_new_str(cx: ext_ctxt, sp: codemap::span, s: str) -> @ast::expr {
+    ret make_new_lit(cx, sp, ast::lit_str(s));
+}
+//
+// Local Variables:
+// mode: rust
+// fill-column: 78;
+// indent-tabs-mode: nil
+// c-basic-offset: 4
+// buffer-file-coding-system: utf-8-unix
+// End:
+//
diff --git a/src/librustsyntax/parse.rs b/src/librustsyntax/parse.rs
index 96fa2dae8b5..ab3fc2072ae 100644
--- a/src/librustsyntax/parse.rs
+++ b/src/librustsyntax/parse.rs
@@ -8,6 +8,7 @@ export parse_crate_from_file;
 export parse_crate_from_crate_file;
 export parse_crate_from_source_str;
 export parse_expr_from_source_str;
+export parse_item_from_source_str;
 export parse_from_source_str;
 
 import parser::parser;
@@ -93,6 +94,17 @@ fn parse_expr_from_source_str(name: str, source: @str, cfg: ast::crate_cfg,
     ret r;
 }
 
+fn parse_item_from_source_str(name: str, source: @str, cfg: ast::crate_cfg,
+                              +attrs: [ast::attribute], vis: ast::visibility,
+                              sess: parse_sess) -> option<@ast::item> {
+    let p = new_parser_from_source_str(
+        sess, cfg, name, codemap::fss_none, source);
+    let r = parser::parse_item(p, attrs, vis);
+    sess.chpos = p.reader.chpos;
+    sess.byte_pos = sess.byte_pos + p.reader.pos;
+    ret r;
+}
+
 fn parse_from_source_str<T>(f: fn (p: parser) -> T,
                             name: str, ss: codemap::file_substr,
                             source: @str, cfg: ast::crate_cfg,
diff --git a/src/librustsyntax/rustsyntax.rc b/src/librustsyntax/rustsyntax.rc
index 2e560eb01c1..293238aac3c 100644
--- a/src/librustsyntax/rustsyntax.rc
+++ b/src/librustsyntax/rustsyntax.rc
@@ -63,6 +63,7 @@ mod ext {
     mod simplext;
     mod concat_idents;
     mod ident_to_str;
+    mod include;
     mod log_syntax;
     mod auto_serialize;
 }
diff --git a/src/rustc/driver/driver.rs b/src/rustc/driver/driver.rs
index 6fb525a1346..7f737403da8 100644
--- a/src/rustc/driver/driver.rs
+++ b/src/rustc/driver/driver.rs
@@ -149,6 +149,10 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg,
     if upto == cu_expand { ret {crate: crate, tcx: none}; }
 
     crate =
+        time(time_passes, "intrinsic injection",
+             bind front::intrinsic_inject::inject_intrinsic(sess, crate));
+
+    crate =
         time(time_passes, "core injection",
              bind front::core_inject::maybe_inject_libcore_ref(sess, crate));
 
diff --git a/src/rustc/front/intrinsic.rs b/src/rustc/front/intrinsic.rs
new file mode 100644
index 00000000000..e389b30715b
--- /dev/null
+++ b/src/rustc/front/intrinsic.rs
@@ -0,0 +1,140 @@
+// NB: this file is #include_str'ed into the compiler, re-parsed
+// and injected into each crate the compiler builds. Keep it small.
+
+mod intrinsic {
+
+    // import rusti::visit_ty;
+    // import rusti::visit_val;
+    // import rusti::visit_val_pair;
+
+    export ty_visitor, val_visitor, val_pair_visitor;
+
+    fn macros() {
+        // Present for side-effect of defining intrinsic macros.
+        #macro([#error[f, ...], log(core::error, #fmt[f, ...])]);
+        #macro([#warn[f, ...], log(core::warn, #fmt[f, ...])]);
+        #macro([#info[f, ...], log(core::info, #fmt[f, ...])]);
+        #macro([#debug[f, ...], log(core::debug, #fmt[f, ...])]);
+    }
+
+    iface ty_visitor {
+        fn visit_nil();
+        fn visit_bool();
+
+        fn visit_int();
+        fn visit_i8();
+        fn visit_i16();
+        fn visit_i32();
+        fn visit_i64();
+
+        fn visit_uint();
+        fn visit_u8();
+        fn visit_u16();
+        fn visit_u32();
+        fn visit_u64();
+
+        fn visit_float();
+        fn visit_f32();
+        fn visit_f64();
+        fn visit_str();
+
+        fn visit_vec(cells_mut: bool,
+                     visit_cell: fn(uint, self));
+
+        fn visit_box(inner_mut: bool,
+                     visit_inner: fn(self));
+
+        fn visit_uniq(inner_mut: bool,
+                      visit_inner: fn(self));
+
+        fn visit_ptr(inner_mut: bool,
+                     visit_inner: fn(self));
+
+        fn visit_rptr(inner_mut: bool,
+                      visit_inner: fn(self));
+
+        fn visit_rec(n_fields: uint,
+                     field_name: fn(uint) -> str/&,
+                     field_mut: fn(uint) -> bool,
+                     visit_field: fn(uint, self));
+        fn visit_tup(n_fields: uint,
+                     visit_field: fn(uint, self));
+        fn visit_enum(n_variants: uint,
+                      variant: uint,
+                      variant_name: fn(uint) -> str/&,
+                      visit_variant: fn(uint, self));
+    }
+
+    iface val_visitor {
+
+        // Basic types we can visit directly.
+        fn visit_nil();
+        fn visit_bool(b: &bool);
+
+        fn visit_int(i: &int);
+        fn visit_i8(i: &i8);
+        fn visit_i16(i: &i16);
+        fn visit_i32(i: &i32);
+        fn visit_i64(i: &i64);
+
+        fn visit_uint(u: &uint);
+        fn visit_u8(i: &i8);
+        fn visit_u16(i: &i16);
+        fn visit_u32(i: &i32);
+        fn visit_u64(i: &i64);
+
+        fn visit_float(f: &float);
+        fn visit_f32(f: &f32);
+        fn visit_f64(f: &f64);
+
+        // Vecs and strs we can provide a stub view of.
+        fn visit_str(repr: &vec::unsafe::vec_repr,
+                     visit_cell: fn(uint,self));
+
+        fn visit_vec(repr: &vec::unsafe::vec_repr,
+                     cells_mut: bool,
+                     visit_cell: fn(uint, self));
+
+        fn visit_box(mem: *u8,
+                     inner_mut: bool,
+                     visit_inner: fn(self));
+
+        fn visit_uniq(mem: *u8,
+                      inner_mut: bool,
+                      visit_inner: fn(self));
+
+        fn visit_ptr(mem: *u8,
+                     inner_mut: bool,
+                     visit_inner: fn(self));
+
+        fn visit_rptr(mem: *u8,
+                      inner_mut: bool,
+                      visit_inner: fn(self));
+
+        // Aggregates we can't really provide anything useful for
+        // beyond a *u8. You really have to know what you're doing.
+        fn visit_rec(mem: *u8,
+                     n_fields: uint,
+                     field_name: fn(uint) -> str/&,
+                     field_mut: fn(uint) -> bool,
+                     visit_field: fn(uint, self));
+        fn visit_tup(mem: *u8,
+                     n_fields: uint,
+                     visit_field: fn(uint, self));
+        fn visit_enum(mem: *u8,
+                      n_variants: uint,
+                      variant: uint,
+                      variant_name: fn(uint) -> str/&,
+                      visit_variant: fn(uint, self));
+    }
+
+    iface val_pair_visitor {
+    }
+
+    #[abi = "rust-intrinsic"]
+    native mod rusti {
+        // fn visit_ty<T,V:ty_visitor>(tv: V);
+        // fn visit_val<T,V:val_visitor>(v: &T, vv: V);
+        // fn visit_val_pair<T,V:val_pair_visitor>(a: &T, b: &T, vpv: &V);
+    }
+}
diff --git a/src/rustc/front/intrinsic_inject.rs b/src/rustc/front/intrinsic_inject.rs
new file mode 100644
index 00000000000..d2eaf2c8955
--- /dev/null
+++ b/src/rustc/front/intrinsic_inject.rs
@@ -0,0 +1,30 @@
+import driver::session::session;
+import syntax::parse;
+import syntax::ast;
+
+export inject_intrinsic;
+
+fn inject_intrinsic(sess: session,
+                    crate: @ast::crate) -> @ast::crate {
+
+    // FIXME: upgrade this to #include_str("intrinsic.rs");
+    let intrinsic_module = @"mod intrinsic { }";
+
+    let item = parse::parse_item_from_source_str("intrinsic",
+                                                 intrinsic_module,
+                                                 sess.opts.cfg,
+                                                 [], ast::public,
+                                                 sess.parse_sess);
+    let item =
+        alt item {
+          some(i) { i }
+          none {
+            sess.fatal("no item found in intrinsic module");
+          }
+        };
+
+    let items = [item] + crate.node.module.items;
+
+    ret @{node: {module: { items: items with crate.node.module }
+                 with crate.node} with *crate }
+}
diff --git a/src/rustc/middle/trans/native.rs b/src/rustc/middle/trans/native.rs
index 77e3a1f3067..4ecbdb7a1c1 100644
--- a/src/rustc/middle/trans/native.rs
+++ b/src/rustc/middle/trans/native.rs
@@ -834,6 +834,29 @@ fn trans_intrinsic(ccx: @crate_ctxt, decl: ValueRef, item: @ast::native_item,
         Store(bcx, C_bool(ty::type_needs_drop(ccx.tcx, tp_ty)),
               fcx.llretptr);
       }
+      "visit_ty" {
+        let vp_ty = substs.tys[1], _llvp_ty = type_of::type_of(ccx, vp_ty);
+        let visitor = get_param(decl, first_real_arg);
+        // FIXME: implement a proper iface-call. Nontrivial.
+        Call(bcx, visitor, []);
+      }
+
+      "visit_val" {
+        let vp_ty = substs.tys[1], _llvp_ty = type_of::type_of(ccx, vp_ty);
+        let val = get_param(decl, first_real_arg);
+        let visitor = get_param(decl, first_real_arg + 1u);
+        // FIXME: implement a proper iface-call. Nontrivial.
+        Call(bcx, visitor, [val]);
+      }
+
+      "visit_val_pair" {
+        let vp_ty = substs.tys[1], _llvp_ty = type_of::type_of(ccx, vp_ty);
+        let a = get_param(decl, first_real_arg);
+        let b = get_param(decl, first_real_arg + 1u);
+        let visitor = get_param(decl, first_real_arg + 2u);
+        // FIXME: implement a proper iface-call. Nontrivial.
+        Call(bcx, visitor, [a, b]);
+      }
     }
     build_return(bcx);
     finish_fn(fcx, lltop);
diff --git a/src/rustc/middle/typeck.rs b/src/rustc/middle/typeck.rs
index 472a4f43e2c..7e132ffbee6 100644
--- a/src/rustc/middle/typeck.rs
+++ b/src/rustc/middle/typeck.rs
@@ -2072,6 +2072,19 @@ fn check_intrinsic_type(ccx: @crate_ctxt, it: @ast::native_item) {
       "addr_of" { (1u, [arg(ast::by_ref, param(ccx, 0u))],
                    ty::mk_imm_ptr(tcx, param(ccx, 0u))) }
       "needs_drop" { (1u, [], ty::mk_bool(tcx)) }
+
+      "visit_ty" { (2u, [arg(ast::by_ref, param(ccx, 1u))],
+                    ty::mk_nil(tcx)) }
+
+      "visit_val" { (2u, [arg(ast::by_ref, param(ccx, 0u)),
+                          arg(ast::by_ref, param(ccx, 1u))],
+                     ty::mk_nil(tcx)) }
+
+      "visit_val_pair" { (2u, [arg(ast::by_ref, param(ccx, 0u)),
+                               arg(ast::by_ref, param(ccx, 0u)),
+                               arg(ast::by_ref, param(ccx, 1u))],
+                          ty::mk_nil(tcx)) }
+
       other {
         tcx.sess.span_err(it.span, "unrecognized intrinsic function: `" +
                           other + "`");
diff --git a/src/rustc/rustc.rc b/src/rustc/rustc.rc
index c50ea26eb15..1f0b7798fe0 100644
--- a/src/rustc/rustc.rc
+++ b/src/rustc/rustc.rc
@@ -76,6 +76,7 @@ mod front {
     mod config;
     mod test;
     mod core_inject;
+    mod intrinsic_inject;
 }
 
 mod back {