]> git.lizzy.rs Git - rust.git/blob - src/librustc/metadata/tydecode.rs
libstd: Implement `StrBuf`, a new string buffer type like `Vec`, and
[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::str;
22 use std::strbuf::StrBuf;
23 use std::uint;
24 use syntax::abi;
25 use syntax::ast;
26 use syntax::ast::*;
27 use syntax::owned_slice::OwnedSlice;
28 use syntax::parse::token;
29
30 // Compact string representation for ty::t values. API ty_str &
31 // parse_from_str. Extra parameters are for converting to/from def_ids in the
32 // data buffer. Whatever format you choose should not contain pipe characters.
33
34 // Def id conversion: when we encounter def-ids, they have to be translated.
35 // For example, the crate number must be converted from the crate number used
36 // in the library we are reading from into the local crate numbers in use
37 // here.  To perform this translation, the type decoder is supplied with a
38 // conversion function of type `conv_did`.
39 //
40 // Sometimes, particularly when inlining, the correct translation of the
41 // def-id will depend on where it originated from.  Therefore, the conversion
42 // function is given an indicator of the source of the def-id.  See
43 // astencode.rs for more information.
44 pub enum DefIdSource {
45     // Identifies a struct, trait, enum, etc.
46     NominalType,
47
48     // Identifies a type alias (`type X = ...`).
49     TypeWithId,
50
51     // Identifies a type parameter (`fn foo<X>() { ... }`).
52     TypeParameter,
53
54     // Identifies a region parameter (`fn foo<'X>() { ... }`).
55     RegionParameter,
56 }
57 pub type conv_did<'a> =
58     |source: DefIdSource, ast::DefId|: 'a -> ast::DefId;
59
60 pub struct PState<'a> {
61     data: &'a [u8],
62     krate: ast::CrateNum,
63     pos: uint,
64     tcx: &'a ty::ctxt
65 }
66
67 fn peek(st: &PState) -> char {
68     st.data[st.pos] as char
69 }
70
71 fn next(st: &mut PState) -> char {
72     let ch = st.data[st.pos] as char;
73     st.pos = st.pos + 1u;
74     return ch;
75 }
76
77 fn next_byte(st: &mut PState) -> u8 {
78     let b = st.data[st.pos];
79     st.pos = st.pos + 1u;
80     return b;
81 }
82
83 fn scan<R>(st: &mut PState, is_last: |char| -> bool, op: |&[u8]| -> R) -> R {
84     let start_pos = st.pos;
85     debug!("scan: '{}' (start)", st.data[st.pos] as char);
86     while !is_last(st.data[st.pos] as char) {
87         st.pos += 1;
88         debug!("scan: '{}'", st.data[st.pos] as char);
89     }
90     let end_pos = st.pos;
91     st.pos += 1;
92     return op(st.data.slice(start_pos, end_pos));
93 }
94
95 pub fn parse_ident(st: &mut PState, last: char) -> ast::Ident {
96     fn is_last(b: char, c: char) -> bool { return c == b; }
97     return parse_ident_(st, |a| is_last(last, a) );
98 }
99
100 fn parse_ident_(st: &mut PState, is_last: |char| -> bool) -> ast::Ident {
101     scan(st, is_last, |bytes| {
102         token::str_to_ident(str::from_utf8(bytes).unwrap())
103     })
104 }
105
106 pub fn parse_state_from_data<'a>(data: &'a [u8], crate_num: ast::CrateNum,
107                              pos: uint, tcx: &'a ty::ctxt) -> PState<'a> {
108     PState {
109         data: data,
110         krate: crate_num,
111         pos: pos,
112         tcx: tcx
113     }
114 }
115
116 pub fn parse_ty_data(data: &[u8], crate_num: ast::CrateNum, pos: uint, tcx: &ty::ctxt,
117                      conv: conv_did) -> ty::t {
118     let mut st = parse_state_from_data(data, crate_num, pos, tcx);
119     parse_ty(&mut st, conv)
120 }
121
122 pub fn parse_bare_fn_ty_data(data: &[u8], crate_num: ast::CrateNum, pos: uint, tcx: &ty::ctxt,
123                              conv: conv_did) -> ty::BareFnTy {
124     let mut st = parse_state_from_data(data, crate_num, pos, tcx);
125     parse_bare_fn_ty(&mut st, conv)
126 }
127
128 pub fn parse_trait_ref_data(data: &[u8], crate_num: ast::CrateNum, pos: uint, tcx: &ty::ctxt,
129                             conv: conv_did) -> ty::TraitRef {
130     let mut st = parse_state_from_data(data, crate_num, pos, tcx);
131     parse_trait_ref(&mut st, conv)
132 }
133
134 pub fn parse_substs_data(data: &[u8], crate_num: ast::CrateNum, pos: uint, tcx: &ty::ctxt,
135                          conv: conv_did) -> ty::substs {
136     let mut st = parse_state_from_data(data, crate_num, pos, tcx);
137     parse_substs(&mut st, conv)
138 }
139
140 fn parse_sigil(st: &mut PState) -> ast::Sigil {
141     match next(st) {
142         '@' => ast::ManagedSigil,
143         '~' => ast::OwnedSigil,
144         '&' => ast::BorrowedSigil,
145         c => st.tcx.sess.bug(format!("parse_sigil(): bad input '{}'", c))
146     }
147 }
148
149 fn parse_vstore(st: &mut PState, conv: conv_did) -> ty::vstore {
150     assert_eq!(next(st), '/');
151
152     let c = peek(st);
153     if '0' <= c && c <= '9' {
154         let n = parse_uint(st);
155         assert_eq!(next(st), '|');
156         return ty::vstore_fixed(n);
157     }
158
159     match next(st) {
160       '~' => ty::vstore_uniq,
161       '&' => ty::vstore_slice(parse_region(st, conv)),
162       c => st.tcx.sess.bug(format!("parse_vstore(): bad input '{}'", c))
163     }
164 }
165
166 fn parse_trait_store(st: &mut PState, conv: conv_did) -> ty::TraitStore {
167     match next(st) {
168         '~' => ty::UniqTraitStore,
169         '&' => ty::RegionTraitStore(parse_region(st, conv)),
170         c => st.tcx.sess.bug(format!("parse_trait_store(): bad input '{}'", c))
171     }
172 }
173
174 fn parse_substs(st: &mut PState, conv: conv_did) -> ty::substs {
175     let regions = parse_region_substs(st, |x,y| conv(x,y));
176
177     let self_ty = parse_opt(st, |st| parse_ty(st, |x,y| conv(x,y)) );
178
179     assert_eq!(next(st), '[');
180     let mut params: Vec<ty::t> = Vec::new();
181     while peek(st) != ']' { params.push(parse_ty(st, |x,y| conv(x,y))); }
182     st.pos = st.pos + 1u;
183
184     return ty::substs {
185         regions: regions,
186         self_ty: self_ty,
187         tps: params
188     };
189 }
190
191 fn parse_region_substs(st: &mut PState, conv: conv_did) -> ty::RegionSubsts {
192     match next(st) {
193         'e' => ty::ErasedRegions,
194         'n' => {
195             let mut regions = vec!();
196             while peek(st) != '.' {
197                 let r = parse_region(st, |x,y| conv(x,y));
198                 regions.push(r);
199             }
200             assert_eq!(next(st), '.');
201             ty::NonerasedRegions(OwnedSlice::from_vec(regions))
202         }
203         _ => fail!("parse_bound_region: bad input")
204     }
205 }
206
207 fn parse_bound_region(st: &mut PState, conv: conv_did) -> ty::BoundRegion {
208     match next(st) {
209         'a' => {
210             let id = parse_uint(st);
211             assert_eq!(next(st), '|');
212             ty::BrAnon(id)
213         }
214         '[' => {
215             let def = parse_def(st, RegionParameter, |x,y| conv(x,y));
216             let ident = token::str_to_ident(parse_str(st, ']'));
217             ty::BrNamed(def, ident.name)
218         }
219         'f' => {
220             let id = parse_uint(st);
221             assert_eq!(next(st), '|');
222             ty::BrFresh(id)
223         }
224         _ => fail!("parse_bound_region: bad input")
225     }
226 }
227
228 fn parse_region(st: &mut PState, conv: conv_did) -> ty::Region {
229     match next(st) {
230       'b' => {
231         assert_eq!(next(st), '[');
232         let id = parse_uint(st) as ast::NodeId;
233         assert_eq!(next(st), '|');
234         let br = parse_bound_region(st, |x,y| conv(x,y));
235         assert_eq!(next(st), ']');
236         ty::ReLateBound(id, br)
237       }
238       'B' => {
239         assert_eq!(next(st), '[');
240         let node_id = parse_uint(st) as ast::NodeId;
241         assert_eq!(next(st), '|');
242         let index = parse_uint(st);
243         assert_eq!(next(st), '|');
244         let nm = token::str_to_ident(parse_str(st, ']'));
245         ty::ReEarlyBound(node_id, index, nm.name)
246       }
247       'f' => {
248         assert_eq!(next(st), '[');
249         let id = parse_uint(st) as ast::NodeId;
250         assert_eq!(next(st), '|');
251         let br = parse_bound_region(st, |x,y| conv(x,y));
252         assert_eq!(next(st), ']');
253         ty::ReFree(ty::FreeRegion {scope_id: id,
254                                     bound_region: br})
255       }
256       's' => {
257         let id = parse_uint(st) as ast::NodeId;
258         assert_eq!(next(st), '|');
259         ty::ReScope(id)
260       }
261       't' => {
262         ty::ReStatic
263       }
264       'e' => {
265         ty::ReStatic
266       }
267       _ => fail!("parse_region: bad input")
268     }
269 }
270
271 fn parse_opt<T>(st: &mut PState, f: |&mut PState| -> T) -> Option<T> {
272     match next(st) {
273       'n' => None,
274       's' => Some(f(st)),
275       _ => fail!("parse_opt: bad input")
276     }
277 }
278
279 fn parse_str(st: &mut PState, term: char) -> ~str {
280     let mut result = StrBuf::new();
281     while peek(st) != term {
282         unsafe {
283             result.push_bytes([next_byte(st)])
284         }
285     }
286     next(st);
287     return result.into_owned();
288 }
289
290 fn parse_trait_ref(st: &mut PState, conv: conv_did) -> ty::TraitRef {
291     let def = parse_def(st, NominalType, |x,y| conv(x,y));
292     let substs = parse_substs(st, |x,y| conv(x,y));
293     ty::TraitRef {def_id: def, substs: substs}
294 }
295
296 fn parse_ty(st: &mut PState, conv: conv_did) -> ty::t {
297     match next(st) {
298       'n' => return ty::mk_nil(),
299       'z' => return ty::mk_bot(),
300       'b' => return ty::mk_bool(),
301       'i' => return ty::mk_int(),
302       'u' => return ty::mk_uint(),
303       'M' => {
304         match next(st) {
305           'b' => return ty::mk_mach_uint(ast::TyU8),
306           'w' => return ty::mk_mach_uint(ast::TyU16),
307           'l' => return ty::mk_mach_uint(ast::TyU32),
308           'd' => return ty::mk_mach_uint(ast::TyU64),
309           'B' => return ty::mk_mach_int(ast::TyI8),
310           'W' => return ty::mk_mach_int(ast::TyI16),
311           'L' => return ty::mk_mach_int(ast::TyI32),
312           'D' => return ty::mk_mach_int(ast::TyI64),
313           'f' => return ty::mk_mach_float(ast::TyF32),
314           'F' => return ty::mk_mach_float(ast::TyF64),
315           _ => fail!("parse_ty: bad numeric type")
316         }
317       }
318       'c' => return ty::mk_char(),
319       't' => {
320         assert_eq!(next(st), '[');
321         let def = parse_def(st, NominalType, |x,y| conv(x,y));
322         let substs = parse_substs(st, |x,y| conv(x,y));
323         assert_eq!(next(st), ']');
324         return ty::mk_enum(st.tcx, def, substs);
325       }
326       'x' => {
327         assert_eq!(next(st), '[');
328         let def = parse_def(st, NominalType, |x,y| conv(x,y));
329         let substs = parse_substs(st, |x,y| conv(x,y));
330         let store = parse_trait_store(st, |x,y| conv(x,y));
331         let mt = parse_mutability(st);
332         let bounds = parse_bounds(st, |x,y| conv(x,y));
333         assert_eq!(next(st), ']');
334         return ty::mk_trait(st.tcx, def, substs, store, mt, bounds.builtin_bounds);
335       }
336       'p' => {
337         let did = parse_def(st, TypeParameter, |x,y| conv(x,y));
338         debug!("parsed ty_param: did={:?}", did);
339         return ty::mk_param(st.tcx, parse_uint(st), did);
340       }
341       's' => {
342         let did = parse_def(st, TypeParameter, |x,y| conv(x,y));
343         return ty::mk_self(st.tcx, did);
344       }
345       '@' => return ty::mk_box(st.tcx, parse_ty(st, |x,y| conv(x,y))),
346       '~' => return ty::mk_uniq(st.tcx, parse_ty(st, |x,y| conv(x,y))),
347       '*' => return ty::mk_ptr(st.tcx, parse_mt(st, |x,y| conv(x,y))),
348       '&' => {
349         let r = parse_region(st, |x,y| conv(x,y));
350         let mt = parse_mt(st, |x,y| conv(x,y));
351         return ty::mk_rptr(st.tcx, r, mt);
352       }
353       'V' => {
354         let mt = parse_mt(st, |x,y| conv(x,y));
355         let v = parse_vstore(st, |x,y| conv(x,y));
356         return ty::mk_vec(st.tcx, mt, v);
357       }
358       'v' => {
359         let v = parse_vstore(st, |x,y| conv(x,y));
360         return ty::mk_str(st.tcx, v);
361       }
362       'T' => {
363         assert_eq!(next(st), '[');
364         let mut params = Vec::new();
365         while peek(st) != ']' { params.push(parse_ty(st, |x,y| conv(x,y))); }
366         st.pos = st.pos + 1u;
367         return ty::mk_tup(st.tcx, params);
368       }
369       'f' => {
370         return ty::mk_closure(st.tcx, parse_closure_ty(st, |x,y| conv(x,y)));
371       }
372       'F' => {
373         return ty::mk_bare_fn(st.tcx, parse_bare_fn_ty(st, |x,y| conv(x,y)));
374       }
375       '#' => {
376         let pos = parse_hex(st);
377         assert_eq!(next(st), ':');
378         let len = parse_hex(st);
379         assert_eq!(next(st), '#');
380         let key = ty::creader_cache_key {cnum: st.krate,
381                                          pos: pos,
382                                          len: len };
383
384         match st.tcx.rcache.borrow().find_copy(&key) {
385           Some(tt) => return tt,
386           None => {}
387         }
388         let mut ps = PState {
389             pos: pos,
390             .. *st
391         };
392         let tt = parse_ty(&mut ps, |x,y| conv(x,y));
393         st.tcx.rcache.borrow_mut().insert(key, tt);
394         return tt;
395       }
396       '"' => {
397         let _ = parse_def(st, TypeWithId, |x,y| conv(x,y));
398         let inner = parse_ty(st, |x,y| conv(x,y));
399         inner
400       }
401       'a' => {
402           assert_eq!(next(st), '[');
403           let did = parse_def(st, NominalType, |x,y| conv(x,y));
404           let substs = parse_substs(st, |x,y| conv(x,y));
405           assert_eq!(next(st), ']');
406           return ty::mk_struct(st.tcx, did, substs);
407       }
408       c => { error!("unexpected char in type string: {}", c); fail!();}
409     }
410 }
411
412 fn parse_mutability(st: &mut PState) -> ast::Mutability {
413     match peek(st) {
414       'm' => { next(st); ast::MutMutable }
415       _ => { ast::MutImmutable }
416     }
417 }
418
419 fn parse_mt(st: &mut PState, conv: conv_did) -> ty::mt {
420     let m = parse_mutability(st);
421     ty::mt { ty: parse_ty(st, |x,y| conv(x,y)), mutbl: m }
422 }
423
424 fn parse_def(st: &mut PState, source: DefIdSource,
425              conv: conv_did) -> ast::DefId {
426     return conv(source, scan(st, |c| { c == '|' }, parse_def_id));
427 }
428
429 fn parse_uint(st: &mut PState) -> uint {
430     let mut n = 0;
431     loop {
432         let cur = peek(st);
433         if cur < '0' || cur > '9' { return n; }
434         st.pos = st.pos + 1u;
435         n *= 10;
436         n += (cur as uint) - ('0' as uint);
437     };
438 }
439
440 fn parse_hex(st: &mut PState) -> uint {
441     let mut n = 0u;
442     loop {
443         let cur = peek(st);
444         if (cur < '0' || cur > '9') && (cur < 'a' || cur > 'f') { return n; }
445         st.pos = st.pos + 1u;
446         n *= 16u;
447         if '0' <= cur && cur <= '9' {
448             n += (cur as uint) - ('0' as uint);
449         } else { n += 10u + (cur as uint) - ('a' as uint); }
450     };
451 }
452
453 fn parse_purity(c: char) -> Purity {
454     match c {
455         'u' => UnsafeFn,
456         'i' => ImpureFn,
457         'c' => ExternFn,
458         _ => fail!("parse_purity: bad purity {}", c)
459     }
460 }
461
462 fn parse_abi_set(st: &mut PState) -> abi::Abi {
463     assert_eq!(next(st), '[');
464     scan(st, |c| c == ']', |bytes| {
465         let abi_str = str::from_utf8(bytes).unwrap().to_owned();
466         abi::lookup(abi_str).expect(abi_str)
467     })
468 }
469
470 fn parse_onceness(c: char) -> ast::Onceness {
471     match c {
472         'o' => ast::Once,
473         'm' => ast::Many,
474         _ => fail!("parse_onceness: bad onceness")
475     }
476 }
477
478 fn parse_closure_ty(st: &mut PState, conv: conv_did) -> ty::ClosureTy {
479     let sigil = parse_sigil(st);
480     let purity = parse_purity(next(st));
481     let onceness = parse_onceness(next(st));
482     let region = parse_region(st, |x,y| conv(x,y));
483     let bounds = parse_bounds(st, |x,y| conv(x,y));
484     let sig = parse_sig(st, |x,y| conv(x,y));
485     ty::ClosureTy {
486         purity: purity,
487         sigil: sigil,
488         onceness: onceness,
489         region: region,
490         bounds: bounds.builtin_bounds,
491         sig: sig
492     }
493 }
494
495 fn parse_bare_fn_ty(st: &mut PState, conv: conv_did) -> ty::BareFnTy {
496     let purity = parse_purity(next(st));
497     let abi = parse_abi_set(st);
498     let sig = parse_sig(st, |x,y| conv(x,y));
499     ty::BareFnTy {
500         purity: purity,
501         abi: abi,
502         sig: sig
503     }
504 }
505
506 fn parse_sig(st: &mut PState, conv: conv_did) -> ty::FnSig {
507     assert_eq!(next(st), '[');
508     let id = parse_uint(st) as ast::NodeId;
509     assert_eq!(next(st), '|');
510     let mut inputs = Vec::new();
511     while peek(st) != ']' {
512         inputs.push(parse_ty(st, |x,y| conv(x,y)));
513     }
514     st.pos += 1u; // eat the ']'
515     let variadic = match next(st) {
516         'V' => true,
517         'N' => false,
518         r => fail!(format!("bad variadic: {}", r)),
519     };
520     let ret_ty = parse_ty(st, |x,y| conv(x,y));
521     ty::FnSig {binder_id: id,
522                inputs: inputs,
523                output: ret_ty,
524                variadic: variadic}
525 }
526
527 // Rust metadata parsing
528 pub fn parse_def_id(buf: &[u8]) -> ast::DefId {
529     let mut colon_idx = 0u;
530     let len = buf.len();
531     while colon_idx < len && buf[colon_idx] != ':' as u8 { colon_idx += 1u; }
532     if colon_idx == len {
533         error!("didn't find ':' when parsing def id");
534         fail!();
535     }
536
537     let crate_part = buf.slice(0u, colon_idx);
538     let def_part = buf.slice(colon_idx + 1u, len);
539
540     let crate_num = match uint::parse_bytes(crate_part, 10u) {
541        Some(cn) => cn as ast::CrateNum,
542        None => fail!("internal error: parse_def_id: crate number expected, but found {:?}",
543                      crate_part)
544     };
545     let def_num = match uint::parse_bytes(def_part, 10u) {
546        Some(dn) => dn as ast::NodeId,
547        None => fail!("internal error: parse_def_id: id expected, but found {:?}",
548                      def_part)
549     };
550     ast::DefId { krate: crate_num, node: def_num }
551 }
552
553 pub fn parse_type_param_def_data(data: &[u8], start: uint,
554                                  crate_num: ast::CrateNum, tcx: &ty::ctxt,
555                                  conv: conv_did) -> ty::TypeParameterDef
556 {
557     let mut st = parse_state_from_data(data, crate_num, start, tcx);
558     parse_type_param_def(&mut st, conv)
559 }
560
561 fn parse_type_param_def(st: &mut PState, conv: conv_did) -> ty::TypeParameterDef {
562     ty::TypeParameterDef {
563         ident: parse_ident(st, ':'),
564         def_id: parse_def(st, NominalType, |x,y| conv(x,y)),
565         bounds: @parse_bounds(st, |x,y| conv(x,y)),
566         default: parse_opt(st, |st| parse_ty(st, |x,y| conv(x,y)))
567     }
568 }
569
570 fn parse_bounds(st: &mut PState, conv: conv_did) -> ty::ParamBounds {
571     let mut param_bounds = ty::ParamBounds {
572         builtin_bounds: ty::EmptyBuiltinBounds(),
573         trait_bounds: Vec::new()
574     };
575     loop {
576         match next(st) {
577             'S' => {
578                 param_bounds.builtin_bounds.add(ty::BoundSend);
579             }
580             'O' => {
581                 param_bounds.builtin_bounds.add(ty::BoundStatic);
582             }
583             'Z' => {
584                 param_bounds.builtin_bounds.add(ty::BoundSized);
585             }
586             'P' => {
587                 param_bounds.builtin_bounds.add(ty::BoundCopy);
588             }
589             'T' => {
590                 param_bounds.builtin_bounds.add(ty::BoundShare);
591             }
592             'I' => {
593                 param_bounds.trait_bounds.push(@parse_trait_ref(st, |x,y| conv(x,y)));
594             }
595             '.' => {
596                 return param_bounds;
597             }
598             c => {
599                 fail!("parse_bounds: bad bounds ('{}')", c)
600             }
601         }
602     }
603 }