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)]
19 pub use self::DefIdSource::*;
23 use middle::subst::VecPerParamSpace;
24 use middle::ty::{mod, Ty};
28 use std::string::String;
31 use syntax::parse::token;
33 // Compact string representation for Ty values. API ty_str &
34 // parse_from_str. Extra parameters are for converting to/from def_ids in the
35 // data buffer. Whatever format you choose should not contain pipe characters.
37 // Def id conversion: when we encounter def-ids, they have to be translated.
38 // For example, the crate number must be converted from the crate number used
39 // in the library we are reading from into the local crate numbers in use
40 // here. To perform this translation, the type decoder is supplied with a
41 // conversion function of type `conv_did`.
43 // Sometimes, particularly when inlining, the correct translation of the
44 // def-id will depend on where it originated from. Therefore, the conversion
45 // function is given an indicator of the source of the def-id. See
46 // astencode.rs for more information.
48 pub enum DefIdSource {
49 // Identifies a struct, trait, enum, etc.
52 // Identifies a type alias (`type X = ...`).
55 // Identifies a type parameter (`fn foo<X>() { ... }`).
58 // Identifies a region parameter (`fn foo<'X>() { ... }`).
61 // Identifies an unboxed closure
64 pub type conv_did<'a> =
65 |source: DefIdSource, ast::DefId|: 'a -> ast::DefId;
67 pub struct PState<'a, 'tcx: 'a> {
71 tcx: &'a ty::ctxt<'tcx>
74 fn peek(st: &PState) -> char {
75 st.data[st.pos] as char
78 fn next(st: &mut PState) -> char {
79 let ch = st.data[st.pos] as char;
84 fn next_byte(st: &mut PState) -> u8 {
85 let b = st.data[st.pos];
90 fn scan<R>(st: &mut PState, is_last: |char| -> bool, op: |&[u8]| -> R) -> R {
91 let start_pos = st.pos;
92 debug!("scan: '{}' (start)", st.data[st.pos] as char);
93 while !is_last(st.data[st.pos] as char) {
95 debug!("scan: '{}'", st.data[st.pos] as char);
99 return op(st.data[start_pos..end_pos]);
102 pub fn parse_ident(st: &mut PState, last: char) -> ast::Ident {
103 ast::Ident::new(parse_name(st, last))
106 pub fn parse_name(st: &mut PState, last: char) -> ast::Name {
107 fn is_last(b: char, c: char) -> bool { return c == b; }
108 parse_name_(st, |a| is_last(last, a) )
111 fn parse_name_(st: &mut PState, is_last: |char| -> bool) -> ast::Name {
112 scan(st, is_last, |bytes| {
113 token::intern(str::from_utf8(bytes).unwrap())
117 pub fn parse_state_from_data<'a, 'tcx>(data: &'a [u8], crate_num: ast::CrateNum,
118 pos: uint, tcx: &'a ty::ctxt<'tcx>)
119 -> PState<'a, 'tcx> {
128 fn data_log_string(data: &[u8], pos: uint) -> String {
129 let mut buf = String::new();
131 for i in range(pos, data.len()) {
133 if c > 0x20 && c <= 0x7F {
143 pub fn parse_ty_closure_data<'tcx>(data: &[u8],
144 crate_num: ast::CrateNum,
146 tcx: &ty::ctxt<'tcx>,
148 -> ty::ClosureTy<'tcx> {
149 let mut st = parse_state_from_data(data, crate_num, pos, tcx);
150 parse_closure_ty(&mut st, conv)
153 pub fn parse_ty_data<'tcx>(data: &[u8], crate_num: ast::CrateNum, pos: uint,
154 tcx: &ty::ctxt<'tcx>, conv: conv_did) -> Ty<'tcx> {
155 debug!("parse_ty_data {}", data_log_string(data, pos));
156 let mut st = parse_state_from_data(data, crate_num, pos, tcx);
157 parse_ty(&mut st, conv)
160 pub fn parse_region_data(data: &[u8], crate_num: ast::CrateNum, pos: uint, tcx: &ty::ctxt,
161 conv: conv_did) -> ty::Region {
162 debug!("parse_region_data {}", data_log_string(data, pos));
163 let mut st = parse_state_from_data(data, crate_num, pos, tcx);
164 parse_region(&mut st, conv)
167 pub fn parse_bare_fn_ty_data<'tcx>(data: &[u8], crate_num: ast::CrateNum, pos: uint,
168 tcx: &ty::ctxt<'tcx>, conv: conv_did)
169 -> ty::BareFnTy<'tcx> {
170 debug!("parse_bare_fn_ty_data {}", data_log_string(data, pos));
171 let mut st = parse_state_from_data(data, crate_num, pos, tcx);
172 parse_bare_fn_ty(&mut st, conv)
175 pub fn parse_trait_ref_data<'tcx>(data: &[u8], crate_num: ast::CrateNum, pos: uint,
176 tcx: &ty::ctxt<'tcx>, conv: conv_did)
177 -> ty::TraitRef<'tcx> {
178 debug!("parse_trait_ref_data {}", data_log_string(data, pos));
179 let mut st = parse_state_from_data(data, crate_num, pos, tcx);
180 parse_trait_ref(&mut st, conv)
183 pub fn parse_substs_data<'tcx>(data: &[u8], crate_num: ast::CrateNum, pos: uint,
184 tcx: &ty::ctxt<'tcx>, conv: conv_did) -> subst::Substs<'tcx> {
185 debug!("parse_substs_data {}", data_log_string(data, pos));
186 let mut st = parse_state_from_data(data, crate_num, pos, tcx);
187 parse_substs(&mut st, conv)
190 pub fn parse_bounds_data<'tcx>(data: &[u8], crate_num: ast::CrateNum,
191 pos: uint, tcx: &ty::ctxt<'tcx>, conv: conv_did)
192 -> ty::ParamBounds<'tcx> {
193 let mut st = parse_state_from_data(data, crate_num, pos, tcx);
194 parse_bounds(&mut st, conv)
197 pub fn parse_existential_bounds_data(data: &[u8], crate_num: ast::CrateNum,
198 pos: uint, tcx: &ty::ctxt, conv: conv_did)
199 -> ty::ExistentialBounds {
200 let mut st = parse_state_from_data(data, crate_num, pos, tcx);
201 parse_existential_bounds(&mut st, conv)
204 pub fn parse_builtin_bounds_data(data: &[u8], crate_num: ast::CrateNum,
205 pos: uint, tcx: &ty::ctxt, conv: conv_did)
206 -> ty::BuiltinBounds {
207 let mut st = parse_state_from_data(data, crate_num, pos, tcx);
208 parse_builtin_bounds(&mut st, conv)
211 fn parse_size(st: &mut PState) -> Option<uint> {
212 assert_eq!(next(st), '/');
215 assert_eq!(next(st), '|');
218 let n = parse_uint(st);
219 assert_eq!(next(st), '|');
224 fn parse_trait_store(st: &mut PState, conv: conv_did) -> ty::TraitStore {
226 '~' => ty::UniqTraitStore,
227 '&' => ty::RegionTraitStore(parse_region(st, conv), parse_mutability(st)),
229 st.tcx.sess.bug(format!("parse_trait_store(): bad input '{}'",
235 fn parse_vec_per_param_space<'a, 'tcx, T>(st: &mut PState<'a, 'tcx>,
236 f: |&mut PState<'a, 'tcx>| -> T)
237 -> VecPerParamSpace<T>
239 let mut r = VecPerParamSpace::empty();
240 for &space in subst::ParamSpace::all().iter() {
241 assert_eq!(next(st), '[');
242 while peek(st) != ']' {
243 r.push(space, f(st));
245 assert_eq!(next(st), ']');
250 fn parse_substs<'a, 'tcx>(st: &mut PState<'a, 'tcx>,
251 conv: conv_did) -> subst::Substs<'tcx> {
253 parse_region_substs(st, |x,y| conv(x,y));
256 parse_vec_per_param_space(st, |st| parse_ty(st, |x,y| conv(x,y)));
258 return subst::Substs { types: types,
262 fn parse_region_substs(st: &mut PState, conv: conv_did) -> subst::RegionSubsts {
264 'e' => subst::ErasedRegions,
266 subst::NonerasedRegions(
267 parse_vec_per_param_space(
268 st, |st| parse_region(st, |x,y| conv(x,y))))
270 _ => panic!("parse_bound_region: bad input")
274 fn parse_bound_region(st: &mut PState, conv: conv_did) -> ty::BoundRegion {
277 let id = parse_uint(st);
278 assert_eq!(next(st), '|');
282 let def = parse_def(st, RegionParameter, |x,y| conv(x,y));
283 let ident = token::str_to_ident(parse_str(st, ']').as_slice());
284 ty::BrNamed(def, ident.name)
287 let id = parse_uint(st);
288 assert_eq!(next(st), '|');
292 _ => panic!("parse_bound_region: bad input")
296 fn parse_region(st: &mut PState, conv: conv_did) -> ty::Region {
299 assert_eq!(next(st), '[');
300 let id = ty::DebruijnIndex::new(parse_uint(st));
301 assert_eq!(next(st), '|');
302 let br = parse_bound_region(st, |x,y| conv(x,y));
303 assert_eq!(next(st), ']');
304 ty::ReLateBound(id, br)
307 assert_eq!(next(st), '[');
308 let node_id = parse_uint(st) as ast::NodeId;
309 assert_eq!(next(st), '|');
310 let space = parse_param_space(st);
311 assert_eq!(next(st), '|');
312 let index = parse_uint(st);
313 assert_eq!(next(st), '|');
314 let nm = token::str_to_ident(parse_str(st, ']').as_slice());
315 ty::ReEarlyBound(node_id, space, index, nm.name)
318 assert_eq!(next(st), '[');
319 let scope = parse_scope(st);
320 assert_eq!(next(st), '|');
321 let br = parse_bound_region(st, |x,y| conv(x,y));
322 assert_eq!(next(st), ']');
323 ty::ReFree(ty::FreeRegion { scope: scope,
327 let scope = parse_scope(st);
328 assert_eq!(next(st), '|');
337 _ => panic!("parse_region: bad input")
341 fn parse_scope(st: &mut PState) -> region::CodeExtent {
344 let node_id = parse_uint(st) as ast::NodeId;
345 region::CodeExtent::Misc(node_id)
347 _ => panic!("parse_scope: bad input")
351 fn parse_opt<'a, 'tcx, T>(st: &mut PState<'a, 'tcx>, f: |&mut PState<'a, 'tcx>| -> T)
356 _ => panic!("parse_opt: bad input")
360 fn parse_str(st: &mut PState, term: char) -> String {
361 let mut result = String::new();
362 while peek(st) != term {
364 result.as_mut_vec().push_all(&[next_byte(st)])
371 fn parse_trait_ref<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did)
372 -> ty::TraitRef<'tcx> {
373 let def = parse_def(st, NominalType, |x,y| conv(x,y));
374 let substs = parse_substs(st, |x,y| conv(x,y));
375 ty::TraitRef {def_id: def, substs: substs}
378 fn parse_ty<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did) -> Ty<'tcx> {
380 'b' => return ty::mk_bool(),
381 'i' => return ty::mk_int(),
382 'u' => return ty::mk_uint(),
385 'b' => return ty::mk_mach_uint(ast::TyU8),
386 'w' => return ty::mk_mach_uint(ast::TyU16),
387 'l' => return ty::mk_mach_uint(ast::TyU32),
388 'd' => return ty::mk_mach_uint(ast::TyU64),
389 'B' => return ty::mk_mach_int(ast::TyI8),
390 'W' => return ty::mk_mach_int(ast::TyI16),
391 'L' => return ty::mk_mach_int(ast::TyI32),
392 'D' => return ty::mk_mach_int(ast::TyI64),
393 'f' => return ty::mk_mach_float(ast::TyF32),
394 'F' => return ty::mk_mach_float(ast::TyF64),
395 _ => panic!("parse_ty: bad numeric type")
398 'c' => return ty::mk_char(),
400 assert_eq!(next(st), '[');
401 let def = parse_def(st, NominalType, |x,y| conv(x,y));
402 let substs = parse_substs(st, |x,y| conv(x,y));
403 assert_eq!(next(st), ']');
404 return ty::mk_enum(st.tcx, def, substs);
407 assert_eq!(next(st), '[');
408 let trait_ref = parse_trait_ref(st, |x,y| conv(x,y));
409 let bounds = parse_existential_bounds(st, |x,y| conv(x,y));
410 assert_eq!(next(st), ']');
411 return ty::mk_trait(st.tcx, trait_ref, bounds);
414 let did = parse_def(st, TypeParameter, |x,y| conv(x,y));
415 debug!("parsed ty_param: did={}", did);
416 let index = parse_uint(st);
417 assert_eq!(next(st), '|');
418 let space = parse_param_space(st);
419 assert_eq!(next(st), '|');
420 return ty::mk_param(st.tcx, space, index, did);
422 '~' => return ty::mk_uniq(st.tcx, parse_ty(st, |x,y| conv(x,y))),
423 '*' => return ty::mk_ptr(st.tcx, parse_mt(st, |x,y| conv(x,y))),
425 let r = parse_region(st, |x,y| conv(x,y));
426 let mt = parse_mt(st, |x,y| conv(x,y));
427 return ty::mk_rptr(st.tcx, r, mt);
430 let t = parse_ty(st, |x,y| conv(x,y));
431 let sz = parse_size(st);
432 return ty::mk_vec(st.tcx, t, sz);
435 return ty::mk_str(st.tcx);
438 assert_eq!(next(st), '[');
439 let mut params = Vec::new();
440 while peek(st) != ']' { params.push(parse_ty(st, |x,y| conv(x,y))); }
441 st.pos = st.pos + 1u;
442 return ty::mk_tup(st.tcx, params);
445 return ty::mk_closure(st.tcx, parse_closure_ty(st, |x,y| conv(x,y)));
448 return ty::mk_bare_fn(st.tcx, parse_bare_fn_ty(st, |x,y| conv(x,y)));
451 let pos = parse_hex(st);
452 assert_eq!(next(st), ':');
453 let len = parse_hex(st);
454 assert_eq!(next(st), '#');
455 let key = ty::creader_cache_key {cnum: st.krate,
459 match st.tcx.rcache.borrow().get(&key).cloned() {
460 Some(tt) => return tt,
463 let mut ps = PState {
467 let tt = parse_ty(&mut ps, |x,y| conv(x,y));
468 st.tcx.rcache.borrow_mut().insert(key, tt);
472 let _ = parse_def(st, TypeWithId, |x,y| conv(x,y));
473 let inner = parse_ty(st, |x,y| conv(x,y));
477 assert_eq!(next(st), '[');
478 let did = parse_def(st, NominalType, |x,y| conv(x,y));
479 let substs = parse_substs(st, |x,y| conv(x,y));
480 assert_eq!(next(st), ']');
481 return ty::mk_struct(st.tcx, did, substs);
484 assert_eq!(next(st), '[');
485 let did = parse_def(st, UnboxedClosureSource, |x,y| conv(x,y));
486 let region = parse_region(st, |x,y| conv(x,y));
487 let substs = parse_substs(st, |x,y| conv(x,y));
488 assert_eq!(next(st), ']');
489 return ty::mk_unboxed_closure(st.tcx, did, region, substs);
494 c => { panic!("unexpected char in type string: {}", c);}
498 fn parse_mutability(st: &mut PState) -> ast::Mutability {
500 'm' => { next(st); ast::MutMutable }
501 _ => { ast::MutImmutable }
505 fn parse_mt<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did) -> ty::mt<'tcx> {
506 let m = parse_mutability(st);
507 ty::mt { ty: parse_ty(st, |x,y| conv(x,y)), mutbl: m }
510 fn parse_def(st: &mut PState, source: DefIdSource,
511 conv: conv_did) -> ast::DefId {
512 return conv(source, scan(st, |c| { c == '|' }, parse_def_id));
515 fn parse_uint(st: &mut PState) -> uint {
519 if cur < '0' || cur > '9' { return n; }
520 st.pos = st.pos + 1u;
522 n += (cur as uint) - ('0' as uint);
526 fn parse_param_space(st: &mut PState) -> subst::ParamSpace {
527 subst::ParamSpace::from_uint(parse_uint(st))
530 fn parse_hex(st: &mut PState) -> uint {
534 if (cur < '0' || cur > '9') && (cur < 'a' || cur > 'f') { return n; }
535 st.pos = st.pos + 1u;
537 if '0' <= cur && cur <= '9' {
538 n += (cur as uint) - ('0' as uint);
539 } else { n += 10u + (cur as uint) - ('a' as uint); }
543 fn parse_fn_style(c: char) -> ast::FnStyle {
545 'u' => ast::UnsafeFn,
546 'n' => ast::NormalFn,
547 _ => panic!("parse_fn_style: bad fn_style {}", c)
551 fn parse_abi_set(st: &mut PState) -> abi::Abi {
552 assert_eq!(next(st), '[');
553 scan(st, |c| c == ']', |bytes| {
554 let abi_str = str::from_utf8(bytes).unwrap();
555 abi::lookup(abi_str.as_slice()).expect(abi_str)
559 fn parse_onceness(c: char) -> ast::Onceness {
563 _ => panic!("parse_onceness: bad onceness")
567 fn parse_closure_ty<'a, 'tcx>(st: &mut PState<'a, 'tcx>,
568 conv: conv_did) -> ty::ClosureTy<'tcx> {
569 let fn_style = parse_fn_style(next(st));
570 let onceness = parse_onceness(next(st));
571 let store = parse_trait_store(st, |x,y| conv(x,y));
572 let bounds = parse_existential_bounds(st, |x,y| conv(x,y));
573 let sig = parse_sig(st, |x,y| conv(x,y));
574 let abi = parse_abi_set(st);
585 fn parse_bare_fn_ty<'a, 'tcx>(st: &mut PState<'a, 'tcx>,
586 conv: conv_did) -> ty::BareFnTy<'tcx> {
587 let fn_style = parse_fn_style(next(st));
588 let abi = parse_abi_set(st);
589 let sig = parse_sig(st, |x,y| conv(x,y));
597 fn parse_sig<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did) -> ty::FnSig<'tcx> {
598 assert_eq!(next(st), '[');
599 let mut inputs = Vec::new();
600 while peek(st) != ']' {
601 inputs.push(parse_ty(st, |x,y| conv(x,y)));
603 st.pos += 1u; // eat the ']'
604 let variadic = match next(st) {
607 r => panic!(format!("bad variadic: {}", r)),
609 let output = match peek(st) {
614 _ => ty::FnConverging(parse_ty(st, |x,y| conv(x,y)))
616 ty::FnSig {inputs: inputs,
621 // Rust metadata parsing
622 pub fn parse_def_id(buf: &[u8]) -> ast::DefId {
623 let mut colon_idx = 0u;
625 while colon_idx < len && buf[colon_idx] != ':' as u8 { colon_idx += 1u; }
626 if colon_idx == len {
627 error!("didn't find ':' when parsing def id");
631 let crate_part = buf[0u..colon_idx];
632 let def_part = buf[colon_idx + 1u..len];
634 let crate_num = match str::from_utf8(crate_part).and_then(from_str::<uint>) {
635 Some(cn) => cn as ast::CrateNum,
636 None => panic!("internal error: parse_def_id: crate number expected, found {}",
639 let def_num = match str::from_utf8(def_part).and_then(from_str::<uint>) {
640 Some(dn) => dn as ast::NodeId,
641 None => panic!("internal error: parse_def_id: id expected, found {}",
644 ast::DefId { krate: crate_num, node: def_num }
647 pub fn parse_type_param_def_data<'tcx>(data: &[u8], start: uint,
648 crate_num: ast::CrateNum, tcx: &ty::ctxt<'tcx>,
649 conv: conv_did) -> ty::TypeParameterDef<'tcx>
651 let mut st = parse_state_from_data(data, crate_num, start, tcx);
652 parse_type_param_def(&mut st, conv)
655 fn parse_type_param_def<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did)
656 -> ty::TypeParameterDef<'tcx> {
657 let name = parse_name(st, ':');
658 let def_id = parse_def(st, NominalType, |x,y| conv(x,y));
659 let space = parse_param_space(st);
660 assert_eq!(next(st), '|');
661 let index = parse_uint(st);
662 assert_eq!(next(st), '|');
663 let associated_with = parse_opt(st, |st| {
664 parse_def(st, NominalType, |x,y| conv(x,y))
666 assert_eq!(next(st), '|');
667 let bounds = parse_bounds(st, |x,y| conv(x,y));
668 let default = parse_opt(st, |st| parse_ty(st, |x,y| conv(x,y)));
670 ty::TypeParameterDef {
675 associated_with: associated_with,
681 fn parse_existential_bounds(st: &mut PState, conv: conv_did) -> ty::ExistentialBounds {
682 let r = parse_region(st, |x,y| conv(x,y));
683 let bb = parse_builtin_bounds(st, conv);
684 return ty::ExistentialBounds { region_bound: r, builtin_bounds: bb };
687 fn parse_builtin_bounds(st: &mut PState, _conv: conv_did) -> ty::BuiltinBounds {
688 let mut builtin_bounds = ty::empty_builtin_bounds();
693 builtin_bounds.insert(ty::BoundSend);
696 builtin_bounds.insert(ty::BoundSized);
699 builtin_bounds.insert(ty::BoundCopy);
702 builtin_bounds.insert(ty::BoundSync);
705 return builtin_bounds;
708 panic!("parse_bounds: bad builtin bounds ('{}')", c)
714 fn parse_bounds<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did)
715 -> ty::ParamBounds<'tcx> {
716 let builtin_bounds = parse_builtin_bounds(st, |x,y| conv(x,y));
718 let mut param_bounds = ty::ParamBounds {
719 region_bounds: Vec::new(),
720 builtin_bounds: builtin_bounds,
721 trait_bounds: Vec::new()
726 param_bounds.region_bounds.push(parse_region(st, |x, y| conv (x, y)));
729 param_bounds.trait_bounds.push(Rc::new(parse_trait_ref(st, |x,y| conv(x,y))));
735 panic!("parse_bounds: bad bounds ('{}')", c)