1 // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
14 // tjc note: Would be great to have a `match check` macro equivalent
17 #![allow(non_camel_case_types)]
23 use std::strbuf::StrBuf;
28 use syntax::owned_slice::OwnedSlice;
29 use syntax::parse::token;
31 // Compact string representation for ty::t values. API ty_str &
32 // parse_from_str. Extra parameters are for converting to/from def_ids in the
33 // data buffer. Whatever format you choose should not contain pipe characters.
35 // Def id conversion: when we encounter def-ids, they have to be translated.
36 // For example, the crate number must be converted from the crate number used
37 // in the library we are reading from into the local crate numbers in use
38 // here. To perform this translation, the type decoder is supplied with a
39 // conversion function of type `conv_did`.
41 // Sometimes, particularly when inlining, the correct translation of the
42 // def-id will depend on where it originated from. Therefore, the conversion
43 // function is given an indicator of the source of the def-id. See
44 // astencode.rs for more information.
45 pub enum DefIdSource {
46 // Identifies a struct, trait, enum, etc.
49 // Identifies a type alias (`type X = ...`).
52 // Identifies a type parameter (`fn foo<X>() { ... }`).
55 // Identifies a region parameter (`fn foo<'X>() { ... }`).
58 pub type conv_did<'a> =
59 |source: DefIdSource, ast::DefId|: 'a -> ast::DefId;
61 pub struct PState<'a> {
68 fn peek(st: &PState) -> char {
69 st.data[st.pos] as char
72 fn next(st: &mut PState) -> char {
73 let ch = st.data[st.pos] as char;
78 fn next_byte(st: &mut PState) -> u8 {
79 let b = st.data[st.pos];
84 fn scan<R>(st: &mut PState, is_last: |char| -> bool, op: |&[u8]| -> R) -> R {
85 let start_pos = st.pos;
86 debug!("scan: '{}' (start)", st.data[st.pos] as char);
87 while !is_last(st.data[st.pos] as char) {
89 debug!("scan: '{}'", st.data[st.pos] as char);
93 return op(st.data.slice(start_pos, end_pos));
96 pub fn parse_ident(st: &mut PState, last: char) -> ast::Ident {
97 fn is_last(b: char, c: char) -> bool { return c == b; }
98 return parse_ident_(st, |a| is_last(last, a) );
101 fn parse_ident_(st: &mut PState, is_last: |char| -> bool) -> ast::Ident {
102 scan(st, is_last, |bytes| {
103 token::str_to_ident(str::from_utf8(bytes).unwrap())
107 pub fn parse_state_from_data<'a>(data: &'a [u8], crate_num: ast::CrateNum,
108 pos: uint, tcx: &'a ty::ctxt) -> PState<'a> {
117 pub fn parse_ty_data(data: &[u8], crate_num: ast::CrateNum, pos: uint, tcx: &ty::ctxt,
118 conv: conv_did) -> ty::t {
119 let mut st = parse_state_from_data(data, crate_num, pos, tcx);
120 parse_ty(&mut st, conv)
123 pub fn parse_bare_fn_ty_data(data: &[u8], crate_num: ast::CrateNum, pos: uint, tcx: &ty::ctxt,
124 conv: conv_did) -> ty::BareFnTy {
125 let mut st = parse_state_from_data(data, crate_num, pos, tcx);
126 parse_bare_fn_ty(&mut st, conv)
129 pub fn parse_trait_ref_data(data: &[u8], crate_num: ast::CrateNum, pos: uint, tcx: &ty::ctxt,
130 conv: conv_did) -> ty::TraitRef {
131 let mut st = parse_state_from_data(data, crate_num, pos, tcx);
132 parse_trait_ref(&mut st, conv)
135 pub fn parse_substs_data(data: &[u8], crate_num: ast::CrateNum, pos: uint, tcx: &ty::ctxt,
136 conv: conv_did) -> ty::substs {
137 let mut st = parse_state_from_data(data, crate_num, pos, tcx);
138 parse_substs(&mut st, conv)
141 fn parse_size(st: &mut PState) -> Option<uint> {
142 assert_eq!(next(st), '/');
145 assert_eq!(next(st), '|');
148 let n = parse_uint(st);
149 assert_eq!(next(st), '|');
154 fn parse_trait_store(st: &mut PState, conv: conv_did) -> ty::TraitStore {
156 '~' => ty::UniqTraitStore,
157 '&' => ty::RegionTraitStore(parse_region(st, conv), parse_mutability(st)),
159 st.tcx.sess.bug(format!("parse_trait_store(): bad input '{}'",
165 fn parse_substs(st: &mut PState, conv: conv_did) -> ty::substs {
166 let regions = parse_region_substs(st, |x,y| conv(x,y));
168 let self_ty = parse_opt(st, |st| parse_ty(st, |x,y| conv(x,y)) );
170 assert_eq!(next(st), '[');
171 let mut params: Vec<ty::t> = Vec::new();
172 while peek(st) != ']' { params.push(parse_ty(st, |x,y| conv(x,y))); }
173 st.pos = st.pos + 1u;
182 fn parse_region_substs(st: &mut PState, conv: conv_did) -> ty::RegionSubsts {
184 'e' => ty::ErasedRegions,
186 let mut regions = vec!();
187 while peek(st) != '.' {
188 let r = parse_region(st, |x,y| conv(x,y));
191 assert_eq!(next(st), '.');
192 ty::NonerasedRegions(OwnedSlice::from_vec(regions))
194 _ => fail!("parse_bound_region: bad input")
198 fn parse_bound_region(st: &mut PState, conv: conv_did) -> ty::BoundRegion {
201 let id = parse_uint(st);
202 assert_eq!(next(st), '|');
206 let def = parse_def(st, RegionParameter, |x,y| conv(x,y));
207 let ident = token::str_to_ident(parse_str(st, ']').as_slice());
208 ty::BrNamed(def, ident.name)
211 let id = parse_uint(st);
212 assert_eq!(next(st), '|');
215 _ => fail!("parse_bound_region: bad input")
219 fn parse_region(st: &mut PState, conv: conv_did) -> ty::Region {
222 assert_eq!(next(st), '[');
223 let id = parse_uint(st) as ast::NodeId;
224 assert_eq!(next(st), '|');
225 let br = parse_bound_region(st, |x,y| conv(x,y));
226 assert_eq!(next(st), ']');
227 ty::ReLateBound(id, br)
230 assert_eq!(next(st), '[');
231 let node_id = parse_uint(st) as ast::NodeId;
232 assert_eq!(next(st), '|');
233 let index = parse_uint(st);
234 assert_eq!(next(st), '|');
235 let nm = token::str_to_ident(parse_str(st, ']').as_slice());
236 ty::ReEarlyBound(node_id, index, nm.name)
239 assert_eq!(next(st), '[');
240 let id = parse_uint(st) as ast::NodeId;
241 assert_eq!(next(st), '|');
242 let br = parse_bound_region(st, |x,y| conv(x,y));
243 assert_eq!(next(st), ']');
244 ty::ReFree(ty::FreeRegion {scope_id: id,
248 let id = parse_uint(st) as ast::NodeId;
249 assert_eq!(next(st), '|');
258 _ => fail!("parse_region: bad input")
262 fn parse_opt<T>(st: &mut PState, f: |&mut PState| -> T) -> Option<T> {
266 _ => fail!("parse_opt: bad input")
270 fn parse_str(st: &mut PState, term: char) -> StrBuf {
271 let mut result = StrBuf::new();
272 while peek(st) != term {
274 result.push_bytes([next_byte(st)])
281 fn parse_trait_ref(st: &mut PState, conv: conv_did) -> ty::TraitRef {
282 let def = parse_def(st, NominalType, |x,y| conv(x,y));
283 let substs = parse_substs(st, |x,y| conv(x,y));
284 ty::TraitRef {def_id: def, substs: substs}
287 fn parse_ty(st: &mut PState, conv: conv_did) -> ty::t {
289 'n' => return ty::mk_nil(),
290 'z' => return ty::mk_bot(),
291 'b' => return ty::mk_bool(),
292 'i' => return ty::mk_int(),
293 'u' => return ty::mk_uint(),
296 'b' => return ty::mk_mach_uint(ast::TyU8),
297 'w' => return ty::mk_mach_uint(ast::TyU16),
298 'l' => return ty::mk_mach_uint(ast::TyU32),
299 'd' => return ty::mk_mach_uint(ast::TyU64),
300 'B' => return ty::mk_mach_int(ast::TyI8),
301 'W' => return ty::mk_mach_int(ast::TyI16),
302 'L' => return ty::mk_mach_int(ast::TyI32),
303 'D' => return ty::mk_mach_int(ast::TyI64),
304 'f' => return ty::mk_mach_float(ast::TyF32),
305 'F' => return ty::mk_mach_float(ast::TyF64),
306 'Q' => return ty::mk_mach_float(ast::TyF128),
307 _ => fail!("parse_ty: bad numeric type")
310 'c' => return ty::mk_char(),
312 assert_eq!(next(st), '[');
313 let def = parse_def(st, NominalType, |x,y| conv(x,y));
314 let substs = parse_substs(st, |x,y| conv(x,y));
315 assert_eq!(next(st), ']');
316 return ty::mk_enum(st.tcx, def, substs);
319 assert_eq!(next(st), '[');
320 let def = parse_def(st, NominalType, |x,y| conv(x,y));
321 let substs = parse_substs(st, |x,y| conv(x,y));
322 let store = parse_trait_store(st, |x,y| conv(x,y));
323 let bounds = parse_bounds(st, |x,y| conv(x,y));
324 assert_eq!(next(st), ']');
325 return ty::mk_trait(st.tcx, def, substs, store, bounds.builtin_bounds);
328 let did = parse_def(st, TypeParameter, |x,y| conv(x,y));
329 debug!("parsed ty_param: did={:?}", did);
330 return ty::mk_param(st.tcx, parse_uint(st), did);
333 let did = parse_def(st, TypeParameter, |x,y| conv(x,y));
334 return ty::mk_self(st.tcx, did);
336 '@' => return ty::mk_box(st.tcx, parse_ty(st, |x,y| conv(x,y))),
337 '~' => return ty::mk_uniq(st.tcx, parse_ty(st, |x,y| conv(x,y))),
338 '*' => return ty::mk_ptr(st.tcx, parse_mt(st, |x,y| conv(x,y))),
340 let r = parse_region(st, |x,y| conv(x,y));
341 let mt = parse_mt(st, |x,y| conv(x,y));
342 return ty::mk_rptr(st.tcx, r, mt);
345 let mt = parse_mt(st, |x,y| conv(x,y));
346 let sz = parse_size(st);
347 return ty::mk_vec(st.tcx, mt, sz);
350 return ty::mk_str(st.tcx);
353 assert_eq!(next(st), '[');
354 let mut params = Vec::new();
355 while peek(st) != ']' { params.push(parse_ty(st, |x,y| conv(x,y))); }
356 st.pos = st.pos + 1u;
357 return ty::mk_tup(st.tcx, params);
360 return ty::mk_closure(st.tcx, parse_closure_ty(st, |x,y| conv(x,y)));
363 return ty::mk_bare_fn(st.tcx, parse_bare_fn_ty(st, |x,y| conv(x,y)));
366 let pos = parse_hex(st);
367 assert_eq!(next(st), ':');
368 let len = parse_hex(st);
369 assert_eq!(next(st), '#');
370 let key = ty::creader_cache_key {cnum: st.krate,
374 match st.tcx.rcache.borrow().find_copy(&key) {
375 Some(tt) => return tt,
378 let mut ps = PState {
382 let tt = parse_ty(&mut ps, |x,y| conv(x,y));
383 st.tcx.rcache.borrow_mut().insert(key, tt);
387 let _ = parse_def(st, TypeWithId, |x,y| conv(x,y));
388 let inner = parse_ty(st, |x,y| conv(x,y));
392 assert_eq!(next(st), '[');
393 let did = parse_def(st, NominalType, |x,y| conv(x,y));
394 let substs = parse_substs(st, |x,y| conv(x,y));
395 assert_eq!(next(st), ']');
396 return ty::mk_struct(st.tcx, did, substs);
398 c => { fail!("unexpected char in type string: {}", c);}
402 fn parse_mutability(st: &mut PState) -> ast::Mutability {
404 'm' => { next(st); ast::MutMutable }
405 _ => { ast::MutImmutable }
409 fn parse_mt(st: &mut PState, conv: conv_did) -> ty::mt {
410 let m = parse_mutability(st);
411 ty::mt { ty: parse_ty(st, |x,y| conv(x,y)), mutbl: m }
414 fn parse_def(st: &mut PState, source: DefIdSource,
415 conv: conv_did) -> ast::DefId {
416 return conv(source, scan(st, |c| { c == '|' }, parse_def_id));
419 fn parse_uint(st: &mut PState) -> uint {
423 if cur < '0' || cur > '9' { return n; }
424 st.pos = st.pos + 1u;
426 n += (cur as uint) - ('0' as uint);
430 fn parse_hex(st: &mut PState) -> uint {
434 if (cur < '0' || cur > '9') && (cur < 'a' || cur > 'f') { return n; }
435 st.pos = st.pos + 1u;
437 if '0' <= cur && cur <= '9' {
438 n += (cur as uint) - ('0' as uint);
439 } else { n += 10u + (cur as uint) - ('a' as uint); }
443 fn parse_fn_style(c: char) -> FnStyle {
447 _ => fail!("parse_fn_style: bad fn_style {}", c)
451 fn parse_abi_set(st: &mut PState) -> abi::Abi {
452 assert_eq!(next(st), '[');
453 scan(st, |c| c == ']', |bytes| {
454 let abi_str = str::from_utf8(bytes).unwrap().to_owned();
455 abi::lookup(abi_str.as_slice()).expect(abi_str)
459 fn parse_onceness(c: char) -> ast::Onceness {
463 _ => fail!("parse_onceness: bad onceness")
467 fn parse_closure_ty(st: &mut PState, conv: conv_did) -> ty::ClosureTy {
468 let fn_style = parse_fn_style(next(st));
469 let onceness = parse_onceness(next(st));
470 let store = parse_trait_store(st, |x,y| conv(x,y));
471 let bounds = parse_bounds(st, |x,y| conv(x,y));
472 let sig = parse_sig(st, |x,y| conv(x,y));
477 bounds: bounds.builtin_bounds,
482 fn parse_bare_fn_ty(st: &mut PState, conv: conv_did) -> ty::BareFnTy {
483 let fn_style = parse_fn_style(next(st));
484 let abi = parse_abi_set(st);
485 let sig = parse_sig(st, |x,y| conv(x,y));
493 fn parse_sig(st: &mut PState, conv: conv_did) -> ty::FnSig {
494 assert_eq!(next(st), '[');
495 let id = parse_uint(st) as ast::NodeId;
496 assert_eq!(next(st), '|');
497 let mut inputs = Vec::new();
498 while peek(st) != ']' {
499 inputs.push(parse_ty(st, |x,y| conv(x,y)));
501 st.pos += 1u; // eat the ']'
502 let variadic = match next(st) {
505 r => fail!(format!("bad variadic: {}", r)),
507 let ret_ty = parse_ty(st, |x,y| conv(x,y));
508 ty::FnSig {binder_id: id,
514 // Rust metadata parsing
515 pub fn parse_def_id(buf: &[u8]) -> ast::DefId {
516 let mut colon_idx = 0u;
518 while colon_idx < len && buf[colon_idx] != ':' as u8 { colon_idx += 1u; }
519 if colon_idx == len {
520 error!("didn't find ':' when parsing def id");
524 let crate_part = buf.slice(0u, colon_idx);
525 let def_part = buf.slice(colon_idx + 1u, len);
527 let crate_num = match uint::parse_bytes(crate_part, 10u) {
528 Some(cn) => cn as ast::CrateNum,
529 None => fail!("internal error: parse_def_id: crate number expected, but found {:?}",
532 let def_num = match uint::parse_bytes(def_part, 10u) {
533 Some(dn) => dn as ast::NodeId,
534 None => fail!("internal error: parse_def_id: id expected, but found {:?}",
537 ast::DefId { krate: crate_num, node: def_num }
540 pub fn parse_type_param_def_data(data: &[u8], start: uint,
541 crate_num: ast::CrateNum, tcx: &ty::ctxt,
542 conv: conv_did) -> ty::TypeParameterDef
544 let mut st = parse_state_from_data(data, crate_num, start, tcx);
545 parse_type_param_def(&mut st, conv)
548 fn parse_type_param_def(st: &mut PState, conv: conv_did) -> ty::TypeParameterDef {
549 ty::TypeParameterDef {
550 ident: parse_ident(st, ':'),
551 def_id: parse_def(st, NominalType, |x,y| conv(x,y)),
552 bounds: Rc::new(parse_bounds(st, |x,y| conv(x,y))),
553 default: parse_opt(st, |st| parse_ty(st, |x,y| conv(x,y)))
557 fn parse_bounds(st: &mut PState, conv: conv_did) -> ty::ParamBounds {
558 let mut param_bounds = ty::ParamBounds {
559 builtin_bounds: ty::EmptyBuiltinBounds(),
560 trait_bounds: Vec::new()
565 param_bounds.builtin_bounds.add(ty::BoundSend);
568 param_bounds.builtin_bounds.add(ty::BoundStatic);
571 param_bounds.builtin_bounds.add(ty::BoundSized);
574 param_bounds.builtin_bounds.add(ty::BoundCopy);
577 param_bounds.builtin_bounds.add(ty::BoundShare);
580 param_bounds.trait_bounds.push(Rc::new(parse_trait_ref(st, |x,y| conv(x,y))));
586 fail!("parse_bounds: bad bounds ('{}')", c)