Preliminary groundwork for intrinsic module, reflection interface.
This commit is contained in:
parent
664b82a6b7
commit
c23d6a50d7
|
@ -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);
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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:
|
||||
//
|
|
@ -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,
|
||||
|
|
|
@ -63,6 +63,7 @@ mod ext {
|
|||
mod simplext;
|
||||
mod concat_idents;
|
||||
mod ident_to_str;
|
||||
mod include;
|
||||
mod log_syntax;
|
||||
mod auto_serialize;
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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 }
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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 + "`");
|
||||
|
|
|
@ -76,6 +76,7 @@ mod front {
|
|||
mod config;
|
||||
mod test;
|
||||
mod core_inject;
|
||||
mod intrinsic_inject;
|
||||
}
|
||||
|
||||
mod back {
|
||||
|
|
Loading…
Reference in New Issue