Preliminary groundwork for intrinsic module, reflection interface.

This commit is contained in:
Graydon Hoare 2012-05-10 17:18:04 -07:00
parent 664b82a6b7
commit c23d6a50d7
11 changed files with 291 additions and 0 deletions

View File

@ -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);

View File

@ -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",

View File

@ -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:
//

View File

@ -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,

View File

@ -63,6 +63,7 @@ mod ext {
mod simplext;
mod concat_idents;
mod ident_to_str;
mod include;
mod log_syntax;
mod auto_serialize;
}

View File

@ -148,6 +148,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));

View File

@ -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);
}
}

View File

@ -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 }
}

View File

@ -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);

View File

@ -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 + "`");

View File

@ -76,6 +76,7 @@ mod front {
mod config;
mod test;
mod core_inject;
mod intrinsic_inject;
}
mod back {