Skip to content

Commit c23d6a5

Browse files
committed
Preliminary groundwork for intrinsic module, reflection interface.
1 parent 664b82a commit c23d6a5

File tree

11 files changed

+291
-0
lines changed

11 files changed

+291
-0
lines changed

src/librustsyntax/codemap.rs

+6
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export mk_substr_filename;
1212
export lookup_char_pos;
1313
export adjust_span;
1414
export span_to_str;
15+
export span_to_filename;
1516
export span_to_lines;
1617
export file_lines;
1718
export get_line;
@@ -170,6 +171,11 @@ fn span_to_str(sp: span, cm: codemap) -> str {
170171

171172
type file_lines = {file: filemap, lines: [uint]};
172173

174+
fn span_to_filename(sp: span, cm: codemap::codemap) -> filename {
175+
let lo = lookup_char_pos(cm, sp.lo);
176+
ret lo.file.name;
177+
}
178+
173179
fn span_to_lines(sp: span, cm: codemap::codemap) -> @file_lines {
174180
let lo = lookup_char_pos(cm, sp.lo);
175181
let hi = lookup_char_pos(cm, sp.hi);

src/librustsyntax/ext/base.rs

+2
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ fn syntax_expander_table() -> hashmap<str, syntax_extension> {
3131
syntax_expanders.insert("auto_serialize",
3232
item_decorator(ext::auto_serialize::expand));
3333
syntax_expanders.insert("env", builtin(ext::env::expand_syntax_ext));
34+
syntax_expanders.insert("include_str",
35+
builtin(ext::include::str::expand_syntax_ext));
3436
syntax_expanders.insert("macro",
3537
macro_defining(ext::simplext::add_new_extension));
3638
syntax_expanders.insert("concat_idents",

src/librustsyntax/ext/include.rs

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* The compiler code necessary to support the #include and #include_str
3+
* extensions. Eventually this should all get sucked into either the compiler
4+
* syntax extension plugin interface.
5+
*/
6+
7+
import diagnostic::span_handler;
8+
import base::*;
9+
export str;
10+
11+
// FIXME: implement plain #include, restarting the parser on the included
12+
// file. Currently only implement #include_str.
13+
14+
mod str {
15+
fn expand_syntax_ext(cx: ext_ctxt, sp: codemap::span, arg: ast::mac_arg,
16+
_body: ast::mac_body) -> @ast::expr {
17+
let arg = get_mac_arg(cx,sp,arg);
18+
let args: [@ast::expr] =
19+
alt arg.node {
20+
ast::expr_vec(elts, _) { elts }
21+
_ {
22+
cx.span_fatal(sp, "#include_str requires arguments \
23+
of the form `[...]`.")
24+
}
25+
};
26+
if vec::len::<@ast::expr>(args) != 1u {
27+
cx.span_fatal(sp, "malformed #include_str call");
28+
}
29+
let mut path = expr_to_str(cx, args[0], "#include_str requires \
30+
a string");
31+
32+
// NB: relative paths are resolved relative to the compilation unit
33+
if !path::path_is_absolute(path) {
34+
let cu = codemap::span_to_filename(sp, cx.codemap());
35+
let dir = path::dirname(cu);
36+
path = path::connect(dir, path);
37+
}
38+
39+
alt io::read_whole_file_str(path) {
40+
result::ok(src) { ret make_new_str(cx, sp, src); }
41+
result::err(e) {
42+
cx.parse_sess().span_diagnostic.handler().fatal(e)
43+
}
44+
}
45+
}
46+
}
47+
48+
fn make_new_str(cx: ext_ctxt, sp: codemap::span, s: str) -> @ast::expr {
49+
ret make_new_lit(cx, sp, ast::lit_str(s));
50+
}
51+
//
52+
// Local Variables:
53+
// mode: rust
54+
// fill-column: 78;
55+
// indent-tabs-mode: nil
56+
// c-basic-offset: 4
57+
// buffer-file-coding-system: utf-8-unix
58+
// End:
59+
//

src/librustsyntax/parse.rs

+12
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export parse_crate_from_file;
88
export parse_crate_from_crate_file;
99
export parse_crate_from_source_str;
1010
export parse_expr_from_source_str;
11+
export parse_item_from_source_str;
1112
export parse_from_source_str;
1213

1314
import parser::parser;
@@ -93,6 +94,17 @@ fn parse_expr_from_source_str(name: str, source: @str, cfg: ast::crate_cfg,
9394
ret r;
9495
}
9596

97+
fn parse_item_from_source_str(name: str, source: @str, cfg: ast::crate_cfg,
98+
+attrs: [ast::attribute], vis: ast::visibility,
99+
sess: parse_sess) -> option<@ast::item> {
100+
let p = new_parser_from_source_str(
101+
sess, cfg, name, codemap::fss_none, source);
102+
let r = parser::parse_item(p, attrs, vis);
103+
sess.chpos = p.reader.chpos;
104+
sess.byte_pos = sess.byte_pos + p.reader.pos;
105+
ret r;
106+
}
107+
96108
fn parse_from_source_str<T>(f: fn (p: parser) -> T,
97109
name: str, ss: codemap::file_substr,
98110
source: @str, cfg: ast::crate_cfg,

src/librustsyntax/rustsyntax.rc

+1
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ mod ext {
6363
mod simplext;
6464
mod concat_idents;
6565
mod ident_to_str;
66+
mod include;
6667
mod log_syntax;
6768
mod auto_serialize;
6869
}

src/rustc/driver/driver.rs

+4
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,10 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg,
148148

149149
if upto == cu_expand { ret {crate: crate, tcx: none}; }
150150

151+
crate =
152+
time(time_passes, "intrinsic injection",
153+
bind front::intrinsic_inject::inject_intrinsic(sess, crate));
154+
151155
crate =
152156
time(time_passes, "core injection",
153157
bind front::core_inject::maybe_inject_libcore_ref(sess, crate));

src/rustc/front/intrinsic.rs

+140
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
// NB: this file is #include_str'ed into the compiler, re-parsed
2+
// and injected into each crate the compiler builds. Keep it small.
3+
4+
mod intrinsic {
5+
6+
// import rusti::visit_ty;
7+
// import rusti::visit_val;
8+
// import rusti::visit_val_pair;
9+
10+
export ty_visitor, val_visitor, val_pair_visitor;
11+
12+
fn macros() {
13+
// Present for side-effect of defining intrinsic macros.
14+
#macro([#error[f, ...], log(core::error, #fmt[f, ...])]);
15+
#macro([#warn[f, ...], log(core::warn, #fmt[f, ...])]);
16+
#macro([#info[f, ...], log(core::info, #fmt[f, ...])]);
17+
#macro([#debug[f, ...], log(core::debug, #fmt[f, ...])]);
18+
}
19+
20+
iface ty_visitor {
21+
fn visit_nil();
22+
fn visit_bool();
23+
24+
fn visit_int();
25+
fn visit_i8();
26+
fn visit_i16();
27+
fn visit_i32();
28+
fn visit_i64();
29+
30+
fn visit_uint();
31+
fn visit_u8();
32+
fn visit_u16();
33+
fn visit_u32();
34+
fn visit_u64();
35+
36+
fn visit_float();
37+
fn visit_f32();
38+
fn visit_f64();
39+
fn visit_str();
40+
41+
fn visit_vec(cells_mut: bool,
42+
visit_cell: fn(uint, self));
43+
44+
fn visit_box(inner_mut: bool,
45+
visit_inner: fn(self));
46+
47+
fn visit_uniq(inner_mut: bool,
48+
visit_inner: fn(self));
49+
50+
fn visit_ptr(inner_mut: bool,
51+
visit_inner: fn(self));
52+
53+
fn visit_rptr(inner_mut: bool,
54+
visit_inner: fn(self));
55+
56+
fn visit_rec(n_fields: uint,
57+
field_name: fn(uint) -> str/&,
58+
field_mut: fn(uint) -> bool,
59+
visit_field: fn(uint, self));
60+
fn visit_tup(n_fields: uint,
61+
visit_field: fn(uint, self));
62+
fn visit_enum(n_variants: uint,
63+
variant: uint,
64+
variant_name: fn(uint) -> str/&,
65+
visit_variant: fn(uint, self));
66+
}
67+
68+
iface val_visitor {
69+
70+
// Basic types we can visit directly.
71+
fn visit_nil();
72+
fn visit_bool(b: &bool);
73+
74+
fn visit_int(i: &int);
75+
fn visit_i8(i: &i8);
76+
fn visit_i16(i: &i16);
77+
fn visit_i32(i: &i32);
78+
fn visit_i64(i: &i64);
79+
80+
fn visit_uint(u: &uint);
81+
fn visit_u8(i: &i8);
82+
fn visit_u16(i: &i16);
83+
fn visit_u32(i: &i32);
84+
fn visit_u64(i: &i64);
85+
86+
fn visit_float(f: &float);
87+
fn visit_f32(f: &f32);
88+
fn visit_f64(f: &f64);
89+
90+
// Vecs and strs we can provide a stub view of.
91+
fn visit_str(repr: &vec::unsafe::vec_repr,
92+
visit_cell: fn(uint,self));
93+
94+
fn visit_vec(repr: &vec::unsafe::vec_repr,
95+
cells_mut: bool,
96+
visit_cell: fn(uint, self));
97+
98+
fn visit_box(mem: *u8,
99+
inner_mut: bool,
100+
visit_inner: fn(self));
101+
102+
fn visit_uniq(mem: *u8,
103+
inner_mut: bool,
104+
visit_inner: fn(self));
105+
106+
fn visit_ptr(mem: *u8,
107+
inner_mut: bool,
108+
visit_inner: fn(self));
109+
110+
fn visit_rptr(mem: *u8,
111+
inner_mut: bool,
112+
visit_inner: fn(self));
113+
114+
// Aggregates we can't really provide anything useful for
115+
// beyond a *u8. You really have to know what you're doing.
116+
fn visit_rec(mem: *u8,
117+
n_fields: uint,
118+
field_name: fn(uint) -> str/&,
119+
field_mut: fn(uint) -> bool,
120+
visit_field: fn(uint, self));
121+
fn visit_tup(mem: *u8,
122+
n_fields: uint,
123+
visit_field: fn(uint, self));
124+
fn visit_enum(mem: *u8,
125+
n_variants: uint,
126+
variant: uint,
127+
variant_name: fn(uint) -> str/&,
128+
visit_variant: fn(uint, self));
129+
}
130+
131+
iface val_pair_visitor {
132+
}
133+
134+
#[abi = "rust-intrinsic"]
135+
native mod rusti {
136+
// fn visit_ty<T,V:ty_visitor>(tv: V);
137+
// fn visit_val<T,V:val_visitor>(v: &T, vv: V);
138+
// fn visit_val_pair<T,V:val_pair_visitor>(a: &T, b: &T, vpv: &V);
139+
}
140+
}

src/rustc/front/intrinsic_inject.rs

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import driver::session::session;
2+
import syntax::parse;
3+
import syntax::ast;
4+
5+
export inject_intrinsic;
6+
7+
fn inject_intrinsic(sess: session,
8+
crate: @ast::crate) -> @ast::crate {
9+
10+
// FIXME: upgrade this to #include_str("intrinsic.rs");
11+
let intrinsic_module = @"mod intrinsic { }";
12+
13+
let item = parse::parse_item_from_source_str("intrinsic",
14+
intrinsic_module,
15+
sess.opts.cfg,
16+
[], ast::public,
17+
sess.parse_sess);
18+
let item =
19+
alt item {
20+
some(i) { i }
21+
none {
22+
sess.fatal("no item found in intrinsic module");
23+
}
24+
};
25+
26+
let items = [item] + crate.node.module.items;
27+
28+
ret @{node: {module: { items: items with crate.node.module }
29+
with crate.node} with *crate }
30+
}

src/rustc/middle/trans/native.rs

+23
Original file line numberDiff line numberDiff line change
@@ -834,6 +834,29 @@ fn trans_intrinsic(ccx: @crate_ctxt, decl: ValueRef, item: @ast::native_item,
834834
Store(bcx, C_bool(ty::type_needs_drop(ccx.tcx, tp_ty)),
835835
fcx.llretptr);
836836
}
837+
"visit_ty" {
838+
let vp_ty = substs.tys[1], _llvp_ty = type_of::type_of(ccx, vp_ty);
839+
let visitor = get_param(decl, first_real_arg);
840+
// FIXME: implement a proper iface-call. Nontrivial.
841+
Call(bcx, visitor, []);
842+
}
843+
844+
"visit_val" {
845+
let vp_ty = substs.tys[1], _llvp_ty = type_of::type_of(ccx, vp_ty);
846+
let val = get_param(decl, first_real_arg);
847+
let visitor = get_param(decl, first_real_arg + 1u);
848+
// FIXME: implement a proper iface-call. Nontrivial.
849+
Call(bcx, visitor, [val]);
850+
}
851+
852+
"visit_val_pair" {
853+
let vp_ty = substs.tys[1], _llvp_ty = type_of::type_of(ccx, vp_ty);
854+
let a = get_param(decl, first_real_arg);
855+
let b = get_param(decl, first_real_arg + 1u);
856+
let visitor = get_param(decl, first_real_arg + 2u);
857+
// FIXME: implement a proper iface-call. Nontrivial.
858+
Call(bcx, visitor, [a, b]);
859+
}
837860
}
838861
build_return(bcx);
839862
finish_fn(fcx, lltop);

src/rustc/middle/typeck.rs

+13
Original file line numberDiff line numberDiff line change
@@ -2072,6 +2072,19 @@ fn check_intrinsic_type(ccx: @crate_ctxt, it: @ast::native_item) {
20722072
"addr_of" { (1u, [arg(ast::by_ref, param(ccx, 0u))],
20732073
ty::mk_imm_ptr(tcx, param(ccx, 0u))) }
20742074
"needs_drop" { (1u, [], ty::mk_bool(tcx)) }
2075+
2076+
"visit_ty" { (2u, [arg(ast::by_ref, param(ccx, 1u))],
2077+
ty::mk_nil(tcx)) }
2078+
2079+
"visit_val" { (2u, [arg(ast::by_ref, param(ccx, 0u)),
2080+
arg(ast::by_ref, param(ccx, 1u))],
2081+
ty::mk_nil(tcx)) }
2082+
2083+
"visit_val_pair" { (2u, [arg(ast::by_ref, param(ccx, 0u)),
2084+
arg(ast::by_ref, param(ccx, 0u)),
2085+
arg(ast::by_ref, param(ccx, 1u))],
2086+
ty::mk_nil(tcx)) }
2087+
20752088
other {
20762089
tcx.sess.span_err(it.span, "unrecognized intrinsic function: `" +
20772090
other + "`");

src/rustc/rustc.rc

+1
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ mod front {
7676
mod config;
7777
mod test;
7878
mod core_inject;
79+
mod intrinsic_inject;
7980
}
8081

8182
mod back {

0 commit comments

Comments
 (0)