]> git.lizzy.rs Git - rust.git/blob - src/librustc/metadata/tydecode.rs
libstd: Remove all uses of `~str` from `libstd`
[rust.git] / src / librustc / metadata / tydecode.rs
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.
4 //
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.
10
11
12 // Type decoding
13
14 // tjc note: Would be great to have a `match check` macro equivalent
15 // for some of these
16
17 #![allow(non_camel_case_types)]
18
19 use middle::ty;
20
21 use std::rc::Rc;
22 use std::str;
23 use std::strbuf::StrBuf;
24 use std::uint;
25 use syntax::abi;
26 use syntax::ast;
27 use syntax::ast::*;
28 use syntax::owned_slice::OwnedSlice;
29 use syntax::parse::token;
30
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.
34
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`.
40 //
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.
47     NominalType,
48
49     // Identifies a type alias (`type X = ...`).
50     TypeWithId,
51
52     // Identifies a type parameter (`fn foo<X>() { ... }`).
53     TypeParameter,
54
55     // Identifies a region parameter (`fn foo<'X>() { ... }`).
56     RegionParameter,
57 }
58 pub type conv_did<'a> =
59     |source: DefIdSource, ast::DefId|: 'a -> ast::DefId;
60
61 pub struct PState<'a> {
62     data: &'a [u8],
63     krate: ast::CrateNum,
64     pos: uint,
65     tcx: &'a ty::ctxt
66 }
67
68 fn peek(st: &PState) -> char {
69     st.data[st.pos] as char
70 }
71
72 fn next(st: &mut PState) -> char {
73     let ch = st.data[st.pos] as char;
74     st.pos = st.pos + 1u;
75     return ch;
76 }
77
78 fn next_byte(st: &mut PState) -> u8 {
79     let b = st.data[st.pos];
80     st.pos = st.pos + 1u;
81     return b;
82 }
83
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) {
88         st.pos += 1;
89         debug!("scan: '{}'", st.data[st.pos] as char);
90     }
91     let end_pos = st.pos;
92     st.pos += 1;
93     return op(st.data.slice(start_pos, end_pos));
94 }
95
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) );
99 }
100
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())
104     })
105 }
106
107 pub fn parse_state_from_data<'a>(data: &'a [u8], crate_num: ast::CrateNum,
108                              pos: uint, tcx: &'a ty::ctxt) -> PState<'a> {
109     PState {
110         data: data,
111         krate: crate_num,
112         pos: pos,
113         tcx: tcx
114     }
115 }
116
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)
121 }
122
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)
127 }
128
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)
133 }
134
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)
139 }
140
141 fn parse_size(st: &mut PState) -> Option<uint> {
142     assert_eq!(next(st), '/');
143
144     if peek(st) == '|' {
145         assert_eq!(next(st), '|');
146         None
147     } else {
148         let n = parse_uint(st);
149         assert_eq!(next(st), '|');
150         Some(n)
151     }
152 }
153
154 fn parse_trait_store(st: &mut PState, conv: conv_did) -> ty::TraitStore {
155     match next(st) {
156         '~' => ty::UniqTraitStore,
157         '&' => ty::RegionTraitStore(parse_region(st, conv), parse_mutability(st)),
158         c => {
159             st.tcx.sess.bug(format!("parse_trait_store(): bad input '{}'",
160                                     c).as_slice())
161         }
162     }
163 }
164
165 fn parse_substs(st: &mut PState, conv: conv_did) -> ty::substs {
166     let regions = parse_region_substs(st, |x,y| conv(x,y));
167
168     let self_ty = parse_opt(st, |st| parse_ty(st, |x,y| conv(x,y)) );
169
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;
174
175     return ty::substs {
176         regions: regions,
177         self_ty: self_ty,
178         tps: params
179     };
180 }
181
182 fn parse_region_substs(st: &mut PState, conv: conv_did) -> ty::RegionSubsts {
183     match next(st) {
184         'e' => ty::ErasedRegions,
185         'n' => {
186             let mut regions = vec!();
187             while peek(st) != '.' {
188                 let r = parse_region(st, |x,y| conv(x,y));
189                 regions.push(r);
190             }
191             assert_eq!(next(st), '.');
192             ty::NonerasedRegions(OwnedSlice::from_vec(regions))
193         }
194         _ => fail!("parse_bound_region: bad input")
195     }
196 }
197
198 fn parse_bound_region(st: &mut PState, conv: conv_did) -> ty::BoundRegion {
199     match next(st) {
200         'a' => {
201             let id = parse_uint(st);
202             assert_eq!(next(st), '|');
203             ty::BrAnon(id)
204         }
205         '[' => {
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)
209         }
210         'f' => {
211             let id = parse_uint(st);
212             assert_eq!(next(st), '|');
213             ty::BrFresh(id)
214         }
215         _ => fail!("parse_bound_region: bad input")
216     }
217 }
218
219 fn parse_region(st: &mut PState, conv: conv_did) -> ty::Region {
220     match next(st) {
221       'b' => {
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)
228       }
229       'B' => {
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)
237       }
238       'f' => {
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,
245                                     bound_region: br})
246       }
247       's' => {
248         let id = parse_uint(st) as ast::NodeId;
249         assert_eq!(next(st), '|');
250         ty::ReScope(id)
251       }
252       't' => {
253         ty::ReStatic
254       }
255       'e' => {
256         ty::ReStatic
257       }
258       _ => fail!("parse_region: bad input")
259     }
260 }
261
262 fn parse_opt<T>(st: &mut PState, f: |&mut PState| -> T) -> Option<T> {
263     match next(st) {
264       'n' => None,
265       's' => Some(f(st)),
266       _ => fail!("parse_opt: bad input")
267     }
268 }
269
270 fn parse_str(st: &mut PState, term: char) -> StrBuf {
271     let mut result = StrBuf::new();
272     while peek(st) != term {
273         unsafe {
274             result.push_bytes([next_byte(st)])
275         }
276     }
277     next(st);
278     result
279 }
280
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}
285 }
286
287 fn parse_ty(st: &mut PState, conv: conv_did) -> ty::t {
288     match next(st) {
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(),
294       'M' => {
295         match next(st) {
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")
308         }
309       }
310       'c' => return ty::mk_char(),
311       't' => {
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);
317       }
318       'x' => {
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);
326       }
327       'p' => {
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);
331       }
332       's' => {
333         let did = parse_def(st, TypeParameter, |x,y| conv(x,y));
334         return ty::mk_self(st.tcx, did);
335       }
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))),
339       '&' => {
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);
343       }
344       'V' => {
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);
348       }
349       'v' => {
350         return ty::mk_str(st.tcx);
351       }
352       'T' => {
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);
358       }
359       'f' => {
360         return ty::mk_closure(st.tcx, parse_closure_ty(st, |x,y| conv(x,y)));
361       }
362       'F' => {
363         return ty::mk_bare_fn(st.tcx, parse_bare_fn_ty(st, |x,y| conv(x,y)));
364       }
365       '#' => {
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,
371                                          pos: pos,
372                                          len: len };
373
374         match st.tcx.rcache.borrow().find_copy(&key) {
375           Some(tt) => return tt,
376           None => {}
377         }
378         let mut ps = PState {
379             pos: pos,
380             .. *st
381         };
382         let tt = parse_ty(&mut ps, |x,y| conv(x,y));
383         st.tcx.rcache.borrow_mut().insert(key, tt);
384         return tt;
385       }
386       '"' => {
387         let _ = parse_def(st, TypeWithId, |x,y| conv(x,y));
388         let inner = parse_ty(st, |x,y| conv(x,y));
389         inner
390       }
391       'a' => {
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);
397       }
398       c => { fail!("unexpected char in type string: {}", c);}
399     }
400 }
401
402 fn parse_mutability(st: &mut PState) -> ast::Mutability {
403     match peek(st) {
404       'm' => { next(st); ast::MutMutable }
405       _ => { ast::MutImmutable }
406     }
407 }
408
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 }
412 }
413
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));
417 }
418
419 fn parse_uint(st: &mut PState) -> uint {
420     let mut n = 0;
421     loop {
422         let cur = peek(st);
423         if cur < '0' || cur > '9' { return n; }
424         st.pos = st.pos + 1u;
425         n *= 10;
426         n += (cur as uint) - ('0' as uint);
427     };
428 }
429
430 fn parse_hex(st: &mut PState) -> uint {
431     let mut n = 0u;
432     loop {
433         let cur = peek(st);
434         if (cur < '0' || cur > '9') && (cur < 'a' || cur > 'f') { return n; }
435         st.pos = st.pos + 1u;
436         n *= 16u;
437         if '0' <= cur && cur <= '9' {
438             n += (cur as uint) - ('0' as uint);
439         } else { n += 10u + (cur as uint) - ('a' as uint); }
440     };
441 }
442
443 fn parse_fn_style(c: char) -> FnStyle {
444     match c {
445         'u' => UnsafeFn,
446         'n' => NormalFn,
447         _ => fail!("parse_fn_style: bad fn_style {}", c)
448     }
449 }
450
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)
456     })
457 }
458
459 fn parse_onceness(c: char) -> ast::Onceness {
460     match c {
461         'o' => ast::Once,
462         'm' => ast::Many,
463         _ => fail!("parse_onceness: bad onceness")
464     }
465 }
466
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));
473     ty::ClosureTy {
474         fn_style: fn_style,
475         onceness: onceness,
476         store: store,
477         bounds: bounds.builtin_bounds,
478         sig: sig
479     }
480 }
481
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));
486     ty::BareFnTy {
487         fn_style: fn_style,
488         abi: abi,
489         sig: sig
490     }
491 }
492
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)));
500     }
501     st.pos += 1u; // eat the ']'
502     let variadic = match next(st) {
503         'V' => true,
504         'N' => false,
505         r => fail!(format!("bad variadic: {}", r)),
506     };
507     let ret_ty = parse_ty(st, |x,y| conv(x,y));
508     ty::FnSig {binder_id: id,
509                inputs: inputs,
510                output: ret_ty,
511                variadic: variadic}
512 }
513
514 // Rust metadata parsing
515 pub fn parse_def_id(buf: &[u8]) -> ast::DefId {
516     let mut colon_idx = 0u;
517     let len = buf.len();
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");
521         fail!();
522     }
523
524     let crate_part = buf.slice(0u, colon_idx);
525     let def_part = buf.slice(colon_idx + 1u, len);
526
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 {:?}",
530                      crate_part)
531     };
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 {:?}",
535                      def_part)
536     };
537     ast::DefId { krate: crate_num, node: def_num }
538 }
539
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
543 {
544     let mut st = parse_state_from_data(data, crate_num, start, tcx);
545     parse_type_param_def(&mut st, conv)
546 }
547
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)))
554     }
555 }
556
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()
561     };
562     loop {
563         match next(st) {
564             'S' => {
565                 param_bounds.builtin_bounds.add(ty::BoundSend);
566             }
567             'O' => {
568                 param_bounds.builtin_bounds.add(ty::BoundStatic);
569             }
570             'Z' => {
571                 param_bounds.builtin_bounds.add(ty::BoundSized);
572             }
573             'P' => {
574                 param_bounds.builtin_bounds.add(ty::BoundCopy);
575             }
576             'T' => {
577                 param_bounds.builtin_bounds.add(ty::BoundShare);
578             }
579             'I' => {
580                 param_bounds.trait_bounds.push(Rc::new(parse_trait_ref(st, |x,y| conv(x,y))));
581             }
582             '.' => {
583                 return param_bounds;
584             }
585             c => {
586                 fail!("parse_bounds: bad bounds ('{}')", c)
587             }
588         }
589     }
590 }