Extract metadata::tydecode from metadata::creader
This commit is contained in:
parent
33294c7293
commit
a3a2cc3d98
3 changed files with 400 additions and 387 deletions
|
@ -14,11 +14,6 @@ import middle::trans;
|
|||
import middle::ty;
|
||||
import back::x86;
|
||||
import util::common;
|
||||
import util::common::span;
|
||||
import util::common::respan;
|
||||
import util::common::a_bang;
|
||||
import util::common::a_ty;
|
||||
import util::common::may_begin_ident;
|
||||
import std::str;
|
||||
import std::uint;
|
||||
import std::vec;
|
||||
|
@ -31,6 +26,8 @@ import std::option::some;
|
|||
import std::os;
|
||||
import std::map::hashmap;
|
||||
import defs::*;
|
||||
import tydecode::parse_def_id;
|
||||
import tydecode::parse_ty_data;
|
||||
|
||||
export get_symbol;
|
||||
export get_tag_variants;
|
||||
|
@ -40,368 +37,6 @@ export lookup_defs;
|
|||
export get_type;
|
||||
export list_file_metadata;
|
||||
|
||||
// Type decoding
|
||||
|
||||
// Compact string representation for ty::t values. API ty_str & parse_from_str
|
||||
// (The second has to be authed pure.) Extra parameters are for converting
|
||||
// to/from def_ids in the data buffer. Whatever format you choose should not
|
||||
// contain pipe characters.
|
||||
|
||||
// Callback to translate defs to strs or back:
|
||||
type str_def = fn(str) -> ast::def_id ;
|
||||
|
||||
type pstate =
|
||||
rec(vec[u8] data, int crate, mutable uint pos, uint len, ty::ctxt tcx);
|
||||
|
||||
type ty_or_bang = util::common::ty_or_bang[ty::t];
|
||||
|
||||
fn peek(@pstate st) -> u8 { ret st.data.(st.pos); }
|
||||
|
||||
fn next(@pstate st) -> u8 {
|
||||
auto ch = st.data.(st.pos);
|
||||
st.pos = st.pos + 1u;
|
||||
ret ch;
|
||||
}
|
||||
|
||||
fn parse_ident(@pstate st, str_def sd, char last) -> ast::ident {
|
||||
fn is_last(char b, char c) -> bool {
|
||||
ret c == b;
|
||||
}
|
||||
ret parse_ident_(st, sd, bind is_last(last, _));
|
||||
}
|
||||
|
||||
fn parse_ident_(@pstate st, str_def sd, fn(char) -> bool is_last)
|
||||
-> ast::ident {
|
||||
auto rslt = "";
|
||||
while (! is_last(peek(st) as char)) {
|
||||
rslt += str::unsafe_from_byte(next(st));
|
||||
}
|
||||
ret rslt;
|
||||
}
|
||||
|
||||
|
||||
fn parse_ty_data(vec[u8] data, int crate_num, uint pos, uint len, str_def sd,
|
||||
ty::ctxt tcx) -> ty::t {
|
||||
auto st =
|
||||
@rec(data=data, crate=crate_num, mutable pos=pos, len=len, tcx=tcx);
|
||||
auto result = parse_ty(st, sd);
|
||||
ret result;
|
||||
}
|
||||
|
||||
fn parse_ty_or_bang(@pstate st, str_def sd) -> ty_or_bang {
|
||||
alt (peek(st) as char) {
|
||||
case ('!') { auto ignore = next(st); ret a_bang[ty::t]; }
|
||||
case (_) { ret a_ty[ty::t](parse_ty(st, sd)); }
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_constrs(@pstate st, str_def sd) -> vec[@ty::constr_def] {
|
||||
let vec[@ty::constr_def] rslt = [];
|
||||
alt (peek(st) as char) {
|
||||
case (':') {
|
||||
do {
|
||||
auto ignore = next(st);
|
||||
vec::push(rslt, parse_constr(st, sd));
|
||||
} while (peek(st) as char == ';')
|
||||
}
|
||||
case (_) { }
|
||||
}
|
||||
ret rslt;
|
||||
}
|
||||
|
||||
fn parse_path(@pstate st, str_def sd) -> ast::path {
|
||||
let vec[ast::ident] idents = [];
|
||||
fn is_last(char c) -> bool {
|
||||
ret (c == '(' || c == ':');
|
||||
}
|
||||
idents += [parse_ident_(st, sd, is_last)];
|
||||
while (true) {
|
||||
alt (peek(st) as char) {
|
||||
case (':') {
|
||||
auto ignore = next(st);
|
||||
ignore = next(st);
|
||||
}
|
||||
case (?c) {
|
||||
if (c == '(') {
|
||||
ret respan(rec(lo=0u, hi=0u),
|
||||
rec(idents=idents, types=[]));
|
||||
}
|
||||
else {
|
||||
idents += [parse_ident_(st, sd, is_last)];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fail "parse_path: ill-formed path";
|
||||
}
|
||||
|
||||
fn parse_constr(@pstate st, str_def sd) -> @ty::constr_def {
|
||||
let vec[@ast::constr_arg] args = [];
|
||||
auto sp = rec(lo=0u,hi=0u); // FIXME: use a real span
|
||||
let ast::path pth = parse_path(st, sd);
|
||||
let char ignore = next(st) as char;
|
||||
assert(ignore as char == '(');
|
||||
auto def = parse_def(st, sd);
|
||||
do {
|
||||
alt (peek(st) as char) {
|
||||
case ('*') {
|
||||
st.pos += 1u;
|
||||
args += [@respan(sp, ast::carg_base)];
|
||||
}
|
||||
case (?c) {
|
||||
/* how will we disambiguate between
|
||||
an arg index and a lit argument? */
|
||||
if (c >= '0' && c <= '9') {
|
||||
// FIXME
|
||||
args += [@respan(sp, ast::carg_ident((c as uint) - 48u))];
|
||||
ignore = next(st) as char;
|
||||
}
|
||||
else {
|
||||
log_err("Lit args are unimplemented");
|
||||
fail; // FIXME
|
||||
}
|
||||
/*
|
||||
else {
|
||||
auto lit = parse_lit(st, sd, ',');
|
||||
args += [respan(st.span, ast::carg_lit(lit))];
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
ignore = next(st) as char;
|
||||
} while (ignore == ';');
|
||||
assert(ignore == ')');
|
||||
ret @respan(sp, rec(path=pth, args=args, id=def));
|
||||
}
|
||||
|
||||
fn parse_ty(@pstate st, str_def sd) -> ty::t {
|
||||
alt (next(st) as char) {
|
||||
case ('n') { ret ty::mk_nil(st.tcx); }
|
||||
case ('z') { ret ty::mk_bot(st.tcx); }
|
||||
case ('b') { ret ty::mk_bool(st.tcx); }
|
||||
case ('i') { ret ty::mk_int(st.tcx); }
|
||||
case ('u') { ret ty::mk_uint(st.tcx); }
|
||||
case ('l') { ret ty::mk_float(st.tcx); }
|
||||
case ('M') {
|
||||
alt (next(st) as char) {
|
||||
case ('b') { ret ty::mk_mach(st.tcx, common::ty_u8); }
|
||||
case ('w') { ret ty::mk_mach(st.tcx, common::ty_u16); }
|
||||
case ('l') { ret ty::mk_mach(st.tcx, common::ty_u32); }
|
||||
case ('d') { ret ty::mk_mach(st.tcx, common::ty_u64); }
|
||||
case ('B') { ret ty::mk_mach(st.tcx, common::ty_i8); }
|
||||
case ('W') { ret ty::mk_mach(st.tcx, common::ty_i16); }
|
||||
case ('L') { ret ty::mk_mach(st.tcx, common::ty_i32); }
|
||||
case ('D') { ret ty::mk_mach(st.tcx, common::ty_i64); }
|
||||
case ('f') { ret ty::mk_mach(st.tcx, common::ty_f32); }
|
||||
case ('F') { ret ty::mk_mach(st.tcx, common::ty_f64); }
|
||||
}
|
||||
}
|
||||
case ('c') { ret ty::mk_char(st.tcx); }
|
||||
case ('s') { ret ty::mk_str(st.tcx); }
|
||||
case ('S') { ret ty::mk_istr(st.tcx); }
|
||||
case ('t') {
|
||||
assert (next(st) as char == '[');
|
||||
auto def = parse_def(st, sd);
|
||||
let vec[ty::t] params = [];
|
||||
while (peek(st) as char != ']') { params += [parse_ty(st, sd)]; }
|
||||
st.pos = st.pos + 1u;
|
||||
ret ty::mk_tag(st.tcx, def, params);
|
||||
}
|
||||
case ('p') { ret ty::mk_param(st.tcx, parse_int(st) as uint); }
|
||||
case ('@') { ret ty::mk_box(st.tcx, parse_mt(st, sd)); }
|
||||
case ('*') { ret ty::mk_ptr(st.tcx, parse_mt(st, sd)); }
|
||||
case ('V') { ret ty::mk_vec(st.tcx, parse_mt(st, sd)); }
|
||||
case ('I') { ret ty::mk_ivec(st.tcx, parse_mt(st, sd)); }
|
||||
case ('a') { ret ty::mk_task(st.tcx); }
|
||||
case ('P') { ret ty::mk_port(st.tcx, parse_ty(st, sd)); }
|
||||
case ('C') { ret ty::mk_chan(st.tcx, parse_ty(st, sd)); }
|
||||
case ('T') {
|
||||
assert (next(st) as char == '[');
|
||||
let vec[ty::mt] params = [];
|
||||
while (peek(st) as char != ']') { params += [parse_mt(st, sd)]; }
|
||||
st.pos = st.pos + 1u;
|
||||
ret ty::mk_tup(st.tcx, params);
|
||||
}
|
||||
case ('R') {
|
||||
assert (next(st) as char == '[');
|
||||
let vec[ty::field] fields = [];
|
||||
while (peek(st) as char != ']') {
|
||||
auto name = "";
|
||||
while (peek(st) as char != '=') {
|
||||
name += str::unsafe_from_byte(next(st));
|
||||
}
|
||||
st.pos = st.pos + 1u;
|
||||
fields += [rec(ident=name, mt=parse_mt(st, sd))];
|
||||
}
|
||||
st.pos = st.pos + 1u;
|
||||
ret ty::mk_rec(st.tcx, fields);
|
||||
}
|
||||
case ('F') {
|
||||
auto func = parse_ty_fn(st, sd);
|
||||
ret ty::mk_fn(st.tcx, ast::proto_fn, func._0, func._1, func._2,
|
||||
func._3);
|
||||
}
|
||||
case ('W') {
|
||||
auto func = parse_ty_fn(st, sd);
|
||||
ret ty::mk_fn(st.tcx, ast::proto_iter, func._0, func._1, func._2,
|
||||
func._3);
|
||||
}
|
||||
case ('N') {
|
||||
auto abi;
|
||||
alt (next(st) as char) {
|
||||
case ('r') { abi = ast::native_abi_rust; }
|
||||
case ('i') { abi = ast::native_abi_rust_intrinsic; }
|
||||
case ('c') { abi = ast::native_abi_cdecl; }
|
||||
case ('l') { abi = ast::native_abi_llvm; }
|
||||
}
|
||||
auto func = parse_ty_fn(st, sd);
|
||||
ret ty::mk_native_fn(st.tcx, abi, func._0, func._1);
|
||||
}
|
||||
case ('O') {
|
||||
assert (next(st) as char == '[');
|
||||
let vec[ty::method] methods = [];
|
||||
while (peek(st) as char != ']') {
|
||||
auto proto;
|
||||
alt (next(st) as char) {
|
||||
case ('W') { proto = ast::proto_iter; }
|
||||
case ('F') { proto = ast::proto_fn; }
|
||||
}
|
||||
auto name = "";
|
||||
while (peek(st) as char != '[') {
|
||||
name += str::unsafe_from_byte(next(st));
|
||||
}
|
||||
auto func = parse_ty_fn(st, sd);
|
||||
methods +=
|
||||
[rec(proto=proto,
|
||||
ident=name,
|
||||
inputs=func._0,
|
||||
output=func._1,
|
||||
cf=func._2,
|
||||
constrs=func._3)];
|
||||
}
|
||||
st.pos += 1u;
|
||||
ret ty::mk_obj(st.tcx, methods);
|
||||
}
|
||||
case ('r') {
|
||||
auto def = parse_def(st, sd);
|
||||
auto inner = parse_ty(st, sd);
|
||||
ret ty::mk_res(st.tcx, def, inner);
|
||||
}
|
||||
case ('X') { ret ty::mk_var(st.tcx, parse_int(st)); }
|
||||
case ('E') { ret ty::mk_native(st.tcx); }
|
||||
case ('Y') { ret ty::mk_type(st.tcx); }
|
||||
case ('#') {
|
||||
auto pos = parse_hex(st);
|
||||
assert (next(st) as char == ':');
|
||||
auto len = parse_hex(st);
|
||||
assert (next(st) as char == '#');
|
||||
alt (st.tcx.rcache.find(tup(st.crate, pos, len))) {
|
||||
case (some(?tt)) { ret tt; }
|
||||
case (none) {
|
||||
auto ps = @rec(pos=pos, len=len with *st);
|
||||
auto tt = parse_ty(ps, sd);
|
||||
st.tcx.rcache.insert(tup(st.crate, pos, len), tt);
|
||||
ret tt;
|
||||
}
|
||||
}
|
||||
}
|
||||
case (?c) {
|
||||
log_err "unexpected char in type string: ";
|
||||
log_err c;
|
||||
fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_mt(@pstate st, str_def sd) -> ty::mt {
|
||||
auto mut;
|
||||
alt (peek(st) as char) {
|
||||
case ('m') { next(st); mut = ast::mut; }
|
||||
case ('?') { next(st); mut = ast::maybe_mut; }
|
||||
case (_) { mut = ast::imm; }
|
||||
}
|
||||
ret rec(ty=parse_ty(st, sd), mut=mut);
|
||||
}
|
||||
|
||||
fn parse_def(@pstate st, str_def sd) -> ast::def_id {
|
||||
auto def = "";
|
||||
while (peek(st) as char != '|') {
|
||||
def += str::unsafe_from_byte(next(st));
|
||||
}
|
||||
st.pos = st.pos + 1u;
|
||||
ret sd(def);
|
||||
}
|
||||
|
||||
fn parse_int(@pstate st) -> int {
|
||||
auto n = 0;
|
||||
while (true) {
|
||||
auto cur = peek(st) as char;
|
||||
if (cur < '0' || cur > '9') { break; }
|
||||
st.pos = st.pos + 1u;
|
||||
n *= 10;
|
||||
n += (cur as int) - ('0' as int);
|
||||
}
|
||||
ret n;
|
||||
}
|
||||
|
||||
fn parse_hex(@pstate st) -> uint {
|
||||
auto n = 0u;
|
||||
while (true) {
|
||||
auto cur = peek(st) as char;
|
||||
if ((cur < '0' || cur > '9') && (cur < 'a' || cur > 'f')) { break; }
|
||||
st.pos = st.pos + 1u;
|
||||
n *= 16u;
|
||||
if ('0' <= cur && cur <= '9') {
|
||||
n += (cur as uint) - ('0' as uint);
|
||||
} else { n += 10u + (cur as uint) - ('a' as uint); }
|
||||
}
|
||||
ret n;
|
||||
}
|
||||
|
||||
fn parse_ty_fn(@pstate st, str_def sd) ->
|
||||
tup(vec[ty::arg], ty::t, ast::controlflow, vec[@ty::constr_def]) {
|
||||
assert (next(st) as char == '[');
|
||||
let vec[ty::arg] inputs = [];
|
||||
while (peek(st) as char != ']') {
|
||||
auto mode = ty::mo_val;
|
||||
if (peek(st) as char == '&') {
|
||||
mode = ty::mo_alias(false);
|
||||
st.pos += 1u;
|
||||
if (peek(st) as char == 'm') {
|
||||
mode = ty::mo_alias(true);
|
||||
st.pos += 1u;
|
||||
}
|
||||
}
|
||||
inputs += [rec(mode=mode, ty=parse_ty(st, sd))];
|
||||
}
|
||||
st.pos += 1u; // eat the ']'
|
||||
auto cs = parse_constrs(st, sd);
|
||||
alt (parse_ty_or_bang(st, sd)) {
|
||||
case (a_bang) {
|
||||
ret tup(inputs, ty::mk_bot(st.tcx), ast::noreturn, cs);
|
||||
}
|
||||
case (a_ty(?t)) { ret tup(inputs, t, ast::return, cs); }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Rust metadata parsing
|
||||
fn parse_def_id(vec[u8] buf) -> ast::def_id {
|
||||
auto colon_idx = 0u;
|
||||
auto len = vec::len[u8](buf);
|
||||
while (colon_idx < len && buf.(colon_idx) != ':' as u8) {
|
||||
colon_idx += 1u;
|
||||
}
|
||||
if (colon_idx == len) {
|
||||
log_err "didn't find ':' when parsing def id";
|
||||
fail;
|
||||
}
|
||||
auto crate_part = vec::slice[u8](buf, 0u, colon_idx);
|
||||
auto def_part = vec::slice[u8](buf, colon_idx + 1u, len);
|
||||
auto crate_num = uint::parse_buf(crate_part, 10u) as int;
|
||||
auto def_id = uint::parse_buf(def_part, 10u) as int;
|
||||
ret tup(crate_num, def_id);
|
||||
}
|
||||
|
||||
fn lookup_hash(&ebml::doc d, fn(vec[u8]) -> bool eq_fn, uint hash) ->
|
||||
vec[ebml::doc] {
|
||||
|
@ -516,26 +151,6 @@ fn tag_variant_ids(&ebml::doc item, int this_cnum) -> vec[ast::def_id] {
|
|||
ret ids;
|
||||
}
|
||||
|
||||
fn get_metadata_section(str filename) -> option::t[vec[u8]] {
|
||||
auto b = str::buf(filename);
|
||||
auto mb = llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(b);
|
||||
if (mb as int == 0) { ret option::none[vec[u8]]; }
|
||||
auto of = mk_object_file(mb);
|
||||
auto si = mk_section_iter(of.llof);
|
||||
while (llvm::LLVMIsSectionIteratorAtEnd(of.llof, si.llsi) == False) {
|
||||
auto name_buf = llvm::LLVMGetSectionName(si.llsi);
|
||||
auto name = str::str_from_cstr(name_buf);
|
||||
if (str::eq(name, x86::get_meta_sect_name())) {
|
||||
auto cbuf = llvm::LLVMGetSectionContents(si.llsi);
|
||||
auto csz = llvm::LLVMGetSectionSize(si.llsi);
|
||||
auto cvbuf = cbuf as vec::vbuf;
|
||||
ret option::some[vec[u8]](vec::vec_from_vbuf[u8](cvbuf, csz));
|
||||
}
|
||||
llvm::LLVMMoveToNextSection(si.llsi);
|
||||
}
|
||||
ret option::none[vec[u8]];
|
||||
}
|
||||
|
||||
fn get_exported_metadata(&session::session sess, &str path, &vec[u8] data) ->
|
||||
hashmap[str, str] {
|
||||
auto meta_items =
|
||||
|
@ -653,6 +268,26 @@ fn find_library_crate(&session::session sess, &ast::ident ident,
|
|||
ret none;
|
||||
}
|
||||
|
||||
fn get_metadata_section(str filename) -> option::t[vec[u8]] {
|
||||
auto b = str::buf(filename);
|
||||
auto mb = llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(b);
|
||||
if (mb as int == 0) { ret option::none[vec[u8]]; }
|
||||
auto of = mk_object_file(mb);
|
||||
auto si = mk_section_iter(of.llof);
|
||||
while (llvm::LLVMIsSectionIteratorAtEnd(of.llof, si.llsi) == False) {
|
||||
auto name_buf = llvm::LLVMGetSectionName(si.llsi);
|
||||
auto name = str::str_from_cstr(name_buf);
|
||||
if (str::eq(name, x86::get_meta_sect_name())) {
|
||||
auto cbuf = llvm::LLVMGetSectionContents(si.llsi);
|
||||
auto csz = llvm::LLVMGetSectionSize(si.llsi);
|
||||
auto cvbuf = cbuf as vec::vbuf;
|
||||
ret option::some[vec[u8]](vec::vec_from_vbuf[u8](cvbuf, csz));
|
||||
}
|
||||
llvm::LLVMMoveToNextSection(si.llsi);
|
||||
}
|
||||
ret option::none[vec[u8]];
|
||||
}
|
||||
|
||||
fn load_library_crate(&session::session sess, int cnum, &ast::ident ident,
|
||||
&vec[@ast::meta_item] metas,
|
||||
&vec[str] library_search_paths) {
|
||||
|
|
377
src/comp/metadata/tydecode.rs
Normal file
377
src/comp/metadata/tydecode.rs
Normal file
|
@ -0,0 +1,377 @@
|
|||
// Type decoding
|
||||
import std::str;
|
||||
import std::vec;
|
||||
import std::uint;
|
||||
import std::option;
|
||||
import std::option::none;
|
||||
import std::option::some;
|
||||
import front::ast;
|
||||
import middle::ty;
|
||||
import util::common;
|
||||
import util::common::respan;
|
||||
import util::common::a_ty;
|
||||
import util::common::a_bang;
|
||||
|
||||
export parse_def_id;
|
||||
export parse_ty_data;
|
||||
|
||||
// Compact string representation for ty::t values. API ty_str & parse_from_str
|
||||
// (The second has to be authed pure.) Extra parameters are for converting
|
||||
// to/from def_ids in the data buffer. Whatever format you choose should not
|
||||
// contain pipe characters.
|
||||
|
||||
// Callback to translate defs to strs or back:
|
||||
type str_def = fn(str) -> ast::def_id ;
|
||||
|
||||
type pstate =
|
||||
rec(vec[u8] data, int crate, mutable uint pos, uint len, ty::ctxt tcx);
|
||||
|
||||
type ty_or_bang = util::common::ty_or_bang[ty::t];
|
||||
|
||||
fn peek(@pstate st) -> u8 { ret st.data.(st.pos); }
|
||||
|
||||
fn next(@pstate st) -> u8 {
|
||||
auto ch = st.data.(st.pos);
|
||||
st.pos = st.pos + 1u;
|
||||
ret ch;
|
||||
}
|
||||
|
||||
fn parse_ident(@pstate st, str_def sd, char last) -> ast::ident {
|
||||
fn is_last(char b, char c) -> bool {
|
||||
ret c == b;
|
||||
}
|
||||
ret parse_ident_(st, sd, bind is_last(last, _));
|
||||
}
|
||||
|
||||
fn parse_ident_(@pstate st, str_def sd, fn(char) -> bool is_last)
|
||||
-> ast::ident {
|
||||
auto rslt = "";
|
||||
while (! is_last(peek(st) as char)) {
|
||||
rslt += str::unsafe_from_byte(next(st));
|
||||
}
|
||||
ret rslt;
|
||||
}
|
||||
|
||||
|
||||
fn parse_ty_data(vec[u8] data, int crate_num, uint pos, uint len, str_def sd,
|
||||
ty::ctxt tcx) -> ty::t {
|
||||
auto st =
|
||||
@rec(data=data, crate=crate_num, mutable pos=pos, len=len, tcx=tcx);
|
||||
auto result = parse_ty(st, sd);
|
||||
ret result;
|
||||
}
|
||||
|
||||
fn parse_ty_or_bang(@pstate st, str_def sd) -> ty_or_bang {
|
||||
alt (peek(st) as char) {
|
||||
case ('!') { auto ignore = next(st); ret a_bang[ty::t]; }
|
||||
case (_) { ret a_ty[ty::t](parse_ty(st, sd)); }
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_constrs(@pstate st, str_def sd) -> vec[@ty::constr_def] {
|
||||
let vec[@ty::constr_def] rslt = [];
|
||||
alt (peek(st) as char) {
|
||||
case (':') {
|
||||
do {
|
||||
auto ignore = next(st);
|
||||
vec::push(rslt, parse_constr(st, sd));
|
||||
} while (peek(st) as char == ';')
|
||||
}
|
||||
case (_) { }
|
||||
}
|
||||
ret rslt;
|
||||
}
|
||||
|
||||
fn parse_path(@pstate st, str_def sd) -> ast::path {
|
||||
let vec[ast::ident] idents = [];
|
||||
fn is_last(char c) -> bool {
|
||||
ret (c == '(' || c == ':');
|
||||
}
|
||||
idents += [parse_ident_(st, sd, is_last)];
|
||||
while (true) {
|
||||
alt (peek(st) as char) {
|
||||
case (':') {
|
||||
auto ignore = next(st);
|
||||
ignore = next(st);
|
||||
}
|
||||
case (?c) {
|
||||
if (c == '(') {
|
||||
ret respan(rec(lo=0u, hi=0u),
|
||||
rec(idents=idents, types=[]));
|
||||
}
|
||||
else {
|
||||
idents += [parse_ident_(st, sd, is_last)];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fail "parse_path: ill-formed path";
|
||||
}
|
||||
|
||||
fn parse_constr(@pstate st, str_def sd) -> @ty::constr_def {
|
||||
let vec[@ast::constr_arg] args = [];
|
||||
auto sp = rec(lo=0u,hi=0u); // FIXME: use a real span
|
||||
let ast::path pth = parse_path(st, sd);
|
||||
let char ignore = next(st) as char;
|
||||
assert(ignore as char == '(');
|
||||
auto def = parse_def(st, sd);
|
||||
do {
|
||||
alt (peek(st) as char) {
|
||||
case ('*') {
|
||||
st.pos += 1u;
|
||||
args += [@respan(sp, ast::carg_base)];
|
||||
}
|
||||
case (?c) {
|
||||
/* how will we disambiguate between
|
||||
an arg index and a lit argument? */
|
||||
if (c >= '0' && c <= '9') {
|
||||
// FIXME
|
||||
args += [@respan(sp, ast::carg_ident((c as uint) - 48u))];
|
||||
ignore = next(st) as char;
|
||||
}
|
||||
else {
|
||||
log_err("Lit args are unimplemented");
|
||||
fail; // FIXME
|
||||
}
|
||||
/*
|
||||
else {
|
||||
auto lit = parse_lit(st, sd, ',');
|
||||
args += [respan(st.span, ast::carg_lit(lit))];
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
ignore = next(st) as char;
|
||||
} while (ignore == ';');
|
||||
assert(ignore == ')');
|
||||
ret @respan(sp, rec(path=pth, args=args, id=def));
|
||||
}
|
||||
|
||||
fn parse_ty(@pstate st, str_def sd) -> ty::t {
|
||||
alt (next(st) as char) {
|
||||
case ('n') { ret ty::mk_nil(st.tcx); }
|
||||
case ('z') { ret ty::mk_bot(st.tcx); }
|
||||
case ('b') { ret ty::mk_bool(st.tcx); }
|
||||
case ('i') { ret ty::mk_int(st.tcx); }
|
||||
case ('u') { ret ty::mk_uint(st.tcx); }
|
||||
case ('l') { ret ty::mk_float(st.tcx); }
|
||||
case ('M') {
|
||||
alt (next(st) as char) {
|
||||
case ('b') { ret ty::mk_mach(st.tcx, common::ty_u8); }
|
||||
case ('w') { ret ty::mk_mach(st.tcx, common::ty_u16); }
|
||||
case ('l') { ret ty::mk_mach(st.tcx, common::ty_u32); }
|
||||
case ('d') { ret ty::mk_mach(st.tcx, common::ty_u64); }
|
||||
case ('B') { ret ty::mk_mach(st.tcx, common::ty_i8); }
|
||||
case ('W') { ret ty::mk_mach(st.tcx, common::ty_i16); }
|
||||
case ('L') { ret ty::mk_mach(st.tcx, common::ty_i32); }
|
||||
case ('D') { ret ty::mk_mach(st.tcx, common::ty_i64); }
|
||||
case ('f') { ret ty::mk_mach(st.tcx, common::ty_f32); }
|
||||
case ('F') { ret ty::mk_mach(st.tcx, common::ty_f64); }
|
||||
}
|
||||
}
|
||||
case ('c') { ret ty::mk_char(st.tcx); }
|
||||
case ('s') { ret ty::mk_str(st.tcx); }
|
||||
case ('S') { ret ty::mk_istr(st.tcx); }
|
||||
case ('t') {
|
||||
assert (next(st) as char == '[');
|
||||
auto def = parse_def(st, sd);
|
||||
let vec[ty::t] params = [];
|
||||
while (peek(st) as char != ']') { params += [parse_ty(st, sd)]; }
|
||||
st.pos = st.pos + 1u;
|
||||
ret ty::mk_tag(st.tcx, def, params);
|
||||
}
|
||||
case ('p') { ret ty::mk_param(st.tcx, parse_int(st) as uint); }
|
||||
case ('@') { ret ty::mk_box(st.tcx, parse_mt(st, sd)); }
|
||||
case ('*') { ret ty::mk_ptr(st.tcx, parse_mt(st, sd)); }
|
||||
case ('V') { ret ty::mk_vec(st.tcx, parse_mt(st, sd)); }
|
||||
case ('I') { ret ty::mk_ivec(st.tcx, parse_mt(st, sd)); }
|
||||
case ('a') { ret ty::mk_task(st.tcx); }
|
||||
case ('P') { ret ty::mk_port(st.tcx, parse_ty(st, sd)); }
|
||||
case ('C') { ret ty::mk_chan(st.tcx, parse_ty(st, sd)); }
|
||||
case ('T') {
|
||||
assert (next(st) as char == '[');
|
||||
let vec[ty::mt] params = [];
|
||||
while (peek(st) as char != ']') { params += [parse_mt(st, sd)]; }
|
||||
st.pos = st.pos + 1u;
|
||||
ret ty::mk_tup(st.tcx, params);
|
||||
}
|
||||
case ('R') {
|
||||
assert (next(st) as char == '[');
|
||||
let vec[ty::field] fields = [];
|
||||
while (peek(st) as char != ']') {
|
||||
auto name = "";
|
||||
while (peek(st) as char != '=') {
|
||||
name += str::unsafe_from_byte(next(st));
|
||||
}
|
||||
st.pos = st.pos + 1u;
|
||||
fields += [rec(ident=name, mt=parse_mt(st, sd))];
|
||||
}
|
||||
st.pos = st.pos + 1u;
|
||||
ret ty::mk_rec(st.tcx, fields);
|
||||
}
|
||||
case ('F') {
|
||||
auto func = parse_ty_fn(st, sd);
|
||||
ret ty::mk_fn(st.tcx, ast::proto_fn, func._0, func._1, func._2,
|
||||
func._3);
|
||||
}
|
||||
case ('W') {
|
||||
auto func = parse_ty_fn(st, sd);
|
||||
ret ty::mk_fn(st.tcx, ast::proto_iter, func._0, func._1, func._2,
|
||||
func._3);
|
||||
}
|
||||
case ('N') {
|
||||
auto abi;
|
||||
alt (next(st) as char) {
|
||||
case ('r') { abi = ast::native_abi_rust; }
|
||||
case ('i') { abi = ast::native_abi_rust_intrinsic; }
|
||||
case ('c') { abi = ast::native_abi_cdecl; }
|
||||
case ('l') { abi = ast::native_abi_llvm; }
|
||||
}
|
||||
auto func = parse_ty_fn(st, sd);
|
||||
ret ty::mk_native_fn(st.tcx, abi, func._0, func._1);
|
||||
}
|
||||
case ('O') {
|
||||
assert (next(st) as char == '[');
|
||||
let vec[ty::method] methods = [];
|
||||
while (peek(st) as char != ']') {
|
||||
auto proto;
|
||||
alt (next(st) as char) {
|
||||
case ('W') { proto = ast::proto_iter; }
|
||||
case ('F') { proto = ast::proto_fn; }
|
||||
}
|
||||
auto name = "";
|
||||
while (peek(st) as char != '[') {
|
||||
name += str::unsafe_from_byte(next(st));
|
||||
}
|
||||
auto func = parse_ty_fn(st, sd);
|
||||
methods +=
|
||||
[rec(proto=proto,
|
||||
ident=name,
|
||||
inputs=func._0,
|
||||
output=func._1,
|
||||
cf=func._2,
|
||||
constrs=func._3)];
|
||||
}
|
||||
st.pos += 1u;
|
||||
ret ty::mk_obj(st.tcx, methods);
|
||||
}
|
||||
case ('r') {
|
||||
auto def = parse_def(st, sd);
|
||||
auto inner = parse_ty(st, sd);
|
||||
ret ty::mk_res(st.tcx, def, inner);
|
||||
}
|
||||
case ('X') { ret ty::mk_var(st.tcx, parse_int(st)); }
|
||||
case ('E') { ret ty::mk_native(st.tcx); }
|
||||
case ('Y') { ret ty::mk_type(st.tcx); }
|
||||
case ('#') {
|
||||
auto pos = parse_hex(st);
|
||||
assert (next(st) as char == ':');
|
||||
auto len = parse_hex(st);
|
||||
assert (next(st) as char == '#');
|
||||
alt (st.tcx.rcache.find(tup(st.crate, pos, len))) {
|
||||
case (some(?tt)) { ret tt; }
|
||||
case (none) {
|
||||
auto ps = @rec(pos=pos, len=len with *st);
|
||||
auto tt = parse_ty(ps, sd);
|
||||
st.tcx.rcache.insert(tup(st.crate, pos, len), tt);
|
||||
ret tt;
|
||||
}
|
||||
}
|
||||
}
|
||||
case (?c) {
|
||||
log_err "unexpected char in type string: ";
|
||||
log_err c;
|
||||
fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_mt(@pstate st, str_def sd) -> ty::mt {
|
||||
auto mut;
|
||||
alt (peek(st) as char) {
|
||||
case ('m') { next(st); mut = ast::mut; }
|
||||
case ('?') { next(st); mut = ast::maybe_mut; }
|
||||
case (_) { mut = ast::imm; }
|
||||
}
|
||||
ret rec(ty=parse_ty(st, sd), mut=mut);
|
||||
}
|
||||
|
||||
fn parse_def(@pstate st, str_def sd) -> ast::def_id {
|
||||
auto def = "";
|
||||
while (peek(st) as char != '|') {
|
||||
def += str::unsafe_from_byte(next(st));
|
||||
}
|
||||
st.pos = st.pos + 1u;
|
||||
ret sd(def);
|
||||
}
|
||||
|
||||
fn parse_int(@pstate st) -> int {
|
||||
auto n = 0;
|
||||
while (true) {
|
||||
auto cur = peek(st) as char;
|
||||
if (cur < '0' || cur > '9') { break; }
|
||||
st.pos = st.pos + 1u;
|
||||
n *= 10;
|
||||
n += (cur as int) - ('0' as int);
|
||||
}
|
||||
ret n;
|
||||
}
|
||||
|
||||
fn parse_hex(@pstate st) -> uint {
|
||||
auto n = 0u;
|
||||
while (true) {
|
||||
auto cur = peek(st) as char;
|
||||
if ((cur < '0' || cur > '9') && (cur < 'a' || cur > 'f')) { break; }
|
||||
st.pos = st.pos + 1u;
|
||||
n *= 16u;
|
||||
if ('0' <= cur && cur <= '9') {
|
||||
n += (cur as uint) - ('0' as uint);
|
||||
} else { n += 10u + (cur as uint) - ('a' as uint); }
|
||||
}
|
||||
ret n;
|
||||
}
|
||||
|
||||
fn parse_ty_fn(@pstate st, str_def sd) ->
|
||||
tup(vec[ty::arg], ty::t, ast::controlflow, vec[@ty::constr_def]) {
|
||||
assert (next(st) as char == '[');
|
||||
let vec[ty::arg] inputs = [];
|
||||
while (peek(st) as char != ']') {
|
||||
auto mode = ty::mo_val;
|
||||
if (peek(st) as char == '&') {
|
||||
mode = ty::mo_alias(false);
|
||||
st.pos += 1u;
|
||||
if (peek(st) as char == 'm') {
|
||||
mode = ty::mo_alias(true);
|
||||
st.pos += 1u;
|
||||
}
|
||||
}
|
||||
inputs += [rec(mode=mode, ty=parse_ty(st, sd))];
|
||||
}
|
||||
st.pos += 1u; // eat the ']'
|
||||
auto cs = parse_constrs(st, sd);
|
||||
alt (parse_ty_or_bang(st, sd)) {
|
||||
case (a_bang) {
|
||||
ret tup(inputs, ty::mk_bot(st.tcx), ast::noreturn, cs);
|
||||
}
|
||||
case (a_ty(?t)) { ret tup(inputs, t, ast::return, cs); }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Rust metadata parsing
|
||||
fn parse_def_id(vec[u8] buf) -> ast::def_id {
|
||||
auto colon_idx = 0u;
|
||||
auto len = vec::len[u8](buf);
|
||||
while (colon_idx < len && buf.(colon_idx) != ':' as u8) {
|
||||
colon_idx += 1u;
|
||||
}
|
||||
if (colon_idx == len) {
|
||||
log_err "didn't find ':' when parsing def id";
|
||||
fail;
|
||||
}
|
||||
auto crate_part = vec::slice[u8](buf, 0u, colon_idx);
|
||||
auto def_part = vec::slice[u8](buf, colon_idx + 1u, len);
|
||||
auto crate_num = uint::parse_buf(crate_part, 10u) as int;
|
||||
auto def_id = uint::parse_buf(def_part, 10u) as int;
|
||||
ret tup(crate_num, def_id);
|
||||
}
|
|
@ -65,6 +65,7 @@ mod back {
|
|||
mod metadata {
|
||||
mod defs;
|
||||
mod tyencode;
|
||||
mod tydecode;
|
||||
mod encoder;
|
||||
mod creader;
|
||||
mod cwriter;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue