]> git.lizzy.rs Git - rust.git/blob - src/librustc/metadata/tydecode.rs
f566571d0eb3c91c1f5e68fdfe00e0c0c7319c04
[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::uint;
23 use syntax::abi::AbiSet;
24 use syntax::abi;
25 use syntax::ast;
26 use syntax::ast::*;
27 use syntax::opt_vec;
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     'a |source: DefIdSource, ast::DefId| -> ast::DefId;
59
60 pub struct PState<'a> {
61     data: &'a [u8],
62     krate: ast::CrateNum,
63     pos: uint,
64     tcx: 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: 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: ~[ty::t] = ~[];
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 = opt_vec::Empty;
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(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 = ~"";
281     while peek(st) != term {
282         unsafe {
283             str::raw::push_byte(&mut result, next_byte(st));
284         }
285     }
286     next(st);
287     return result;
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       'U' => return ty::mk_unboxed_vec(st.tcx, parse_mt(st, |x,y| conv(x,y))),
354       'V' => {
355         let mt = parse_mt(st, |x,y| conv(x,y));
356         let v = parse_vstore(st, |x,y| conv(x,y));
357         return ty::mk_vec(st.tcx, mt, v);
358       }
359       'v' => {
360         let v = parse_vstore(st, |x,y| conv(x,y));
361         return ty::mk_str(st.tcx, v);
362       }
363       'T' => {
364         assert_eq!(next(st), '[');
365         let mut params = ~[];
366         while peek(st) != ']' { params.push(parse_ty(st, |x,y| conv(x,y))); }
367         st.pos = st.pos + 1u;
368         return ty::mk_tup(st.tcx, params);
369       }
370       'f' => {
371         return ty::mk_closure(st.tcx, parse_closure_ty(st, |x,y| conv(x,y)));
372       }
373       'F' => {
374         return ty::mk_bare_fn(st.tcx, parse_bare_fn_ty(st, |x,y| conv(x,y)));
375       }
376       '#' => {
377         let pos = parse_hex(st);
378         assert_eq!(next(st), ':');
379         let len = parse_hex(st);
380         assert_eq!(next(st), '#');
381         let key = ty::creader_cache_key {cnum: st.krate,
382                                          pos: pos,
383                                          len: len };
384
385         let tt_opt = {
386             let rcache = st.tcx.rcache.borrow();
387             rcache.get().find_copy(&key)
388         };
389         match tt_opt {
390           Some(tt) => return tt,
391           None => {
392             let mut ps = PState {
393                 pos: pos,
394                 .. *st
395             };
396             let tt = parse_ty(&mut ps, |x,y| conv(x,y));
397             let mut rcache = st.tcx.rcache.borrow_mut();
398             rcache.get().insert(key, tt);
399             return tt;
400           }
401         }
402       }
403       '"' => {
404         let _ = parse_def(st, TypeWithId, |x,y| conv(x,y));
405         let inner = parse_ty(st, |x,y| conv(x,y));
406         inner
407       }
408       'a' => {
409           assert_eq!(next(st), '[');
410           let did = parse_def(st, NominalType, |x,y| conv(x,y));
411           let substs = parse_substs(st, |x,y| conv(x,y));
412           assert_eq!(next(st), ']');
413           return ty::mk_struct(st.tcx, did, substs);
414       }
415       c => { error!("unexpected char in type string: {}", c); fail!();}
416     }
417 }
418
419 fn parse_mutability(st: &mut PState) -> ast::Mutability {
420     match peek(st) {
421       'm' => { next(st); ast::MutMutable }
422       _ => { ast::MutImmutable }
423     }
424 }
425
426 fn parse_mt(st: &mut PState, conv: conv_did) -> ty::mt {
427     let m = parse_mutability(st);
428     ty::mt { ty: parse_ty(st, |x,y| conv(x,y)), mutbl: m }
429 }
430
431 fn parse_def(st: &mut PState, source: DefIdSource,
432              conv: conv_did) -> ast::DefId {
433     return conv(source, scan(st, |c| { c == '|' }, parse_def_id));
434 }
435
436 fn parse_uint(st: &mut PState) -> uint {
437     let mut n = 0;
438     loop {
439         let cur = peek(st);
440         if cur < '0' || cur > '9' { return n; }
441         st.pos = st.pos + 1u;
442         n *= 10;
443         n += (cur as uint) - ('0' as uint);
444     };
445 }
446
447 fn parse_hex(st: &mut PState) -> uint {
448     let mut n = 0u;
449     loop {
450         let cur = peek(st);
451         if (cur < '0' || cur > '9') && (cur < 'a' || cur > 'f') { return n; }
452         st.pos = st.pos + 1u;
453         n *= 16u;
454         if '0' <= cur && cur <= '9' {
455             n += (cur as uint) - ('0' as uint);
456         } else { n += 10u + (cur as uint) - ('a' as uint); }
457     };
458 }
459
460 fn parse_purity(c: char) -> Purity {
461     match c {
462         'u' => UnsafeFn,
463         'i' => ImpureFn,
464         'c' => ExternFn,
465         _ => fail!("parse_purity: bad purity {}", c)
466     }
467 }
468
469 fn parse_abi_set(st: &mut PState) -> AbiSet {
470     assert_eq!(next(st), '[');
471     let mut abis = AbiSet::empty();
472     while peek(st) != ']' {
473          scan(st, |c| c == ',', |bytes| {
474                  let abi_str = str::from_utf8(bytes).unwrap().to_owned();
475                  let abi = abi::lookup(abi_str).expect(abi_str);
476                  abis.add(abi);
477               });
478     }
479     assert_eq!(next(st), ']');
480     return abis;
481 }
482
483 fn parse_onceness(c: char) -> ast::Onceness {
484     match c {
485         'o' => ast::Once,
486         'm' => ast::Many,
487         _ => fail!("parse_onceness: bad onceness")
488     }
489 }
490
491 fn parse_closure_ty(st: &mut PState, conv: conv_did) -> ty::ClosureTy {
492     let sigil = parse_sigil(st);
493     let purity = parse_purity(next(st));
494     let onceness = parse_onceness(next(st));
495     let region = parse_region(st, |x,y| conv(x,y));
496     let bounds = parse_bounds(st, |x,y| conv(x,y));
497     let sig = parse_sig(st, |x,y| conv(x,y));
498     ty::ClosureTy {
499         purity: purity,
500         sigil: sigil,
501         onceness: onceness,
502         region: region,
503         bounds: bounds.builtin_bounds,
504         sig: sig
505     }
506 }
507
508 fn parse_bare_fn_ty(st: &mut PState, conv: conv_did) -> ty::BareFnTy {
509     let purity = parse_purity(next(st));
510     let abi = parse_abi_set(st);
511     let sig = parse_sig(st, |x,y| conv(x,y));
512     ty::BareFnTy {
513         purity: purity,
514         abis: abi,
515         sig: sig
516     }
517 }
518
519 fn parse_sig(st: &mut PState, conv: conv_did) -> ty::FnSig {
520     assert_eq!(next(st), '[');
521     let id = parse_uint(st) as ast::NodeId;
522     assert_eq!(next(st), '|');
523     let mut inputs = ~[];
524     while peek(st) != ']' {
525         inputs.push(parse_ty(st, |x,y| conv(x,y)));
526     }
527     st.pos += 1u; // eat the ']'
528     let variadic = match next(st) {
529         'V' => true,
530         'N' => false,
531         r => fail!(format!("bad variadic: {}", r)),
532     };
533     let ret_ty = parse_ty(st, |x,y| conv(x,y));
534     ty::FnSig {binder_id: id,
535                inputs: inputs,
536                output: ret_ty,
537                variadic: variadic}
538 }
539
540 // Rust metadata parsing
541 pub fn parse_def_id(buf: &[u8]) -> ast::DefId {
542     let mut colon_idx = 0u;
543     let len = buf.len();
544     while colon_idx < len && buf[colon_idx] != ':' as u8 { colon_idx += 1u; }
545     if colon_idx == len {
546         error!("didn't find ':' when parsing def id");
547         fail!();
548     }
549
550     let crate_part = buf.slice(0u, colon_idx);
551     let def_part = buf.slice(colon_idx + 1u, len);
552
553     let crate_num = match uint::parse_bytes(crate_part, 10u) {
554        Some(cn) => cn as ast::CrateNum,
555        None => fail!("internal error: parse_def_id: crate number expected, but found {:?}",
556                      crate_part)
557     };
558     let def_num = match uint::parse_bytes(def_part, 10u) {
559        Some(dn) => dn as ast::NodeId,
560        None => fail!("internal error: parse_def_id: id expected, but found {:?}",
561                      def_part)
562     };
563     ast::DefId { krate: crate_num, node: def_num }
564 }
565
566 pub fn parse_type_param_def_data(data: &[u8], start: uint,
567                                  crate_num: ast::CrateNum, tcx: ty::ctxt,
568                                  conv: conv_did) -> ty::TypeParameterDef
569 {
570     let mut st = parse_state_from_data(data, crate_num, start, tcx);
571     parse_type_param_def(&mut st, conv)
572 }
573
574 fn parse_type_param_def(st: &mut PState, conv: conv_did) -> ty::TypeParameterDef {
575     ty::TypeParameterDef {
576         ident: parse_ident(st, ':'),
577         def_id: parse_def(st, NominalType, |x,y| conv(x,y)),
578         bounds: @parse_bounds(st, |x,y| conv(x,y)),
579         default: parse_opt(st, |st| parse_ty(st, |x,y| conv(x,y)))
580     }
581 }
582
583 fn parse_bounds(st: &mut PState, conv: conv_did) -> ty::ParamBounds {
584     let mut param_bounds = ty::ParamBounds {
585         builtin_bounds: ty::EmptyBuiltinBounds(),
586         trait_bounds: ~[]
587     };
588     loop {
589         match next(st) {
590             'S' => {
591                 param_bounds.builtin_bounds.add(ty::BoundSend);
592             }
593             'K' => {
594                 param_bounds.builtin_bounds.add(ty::BoundFreeze);
595             }
596             'O' => {
597                 param_bounds.builtin_bounds.add(ty::BoundStatic);
598             }
599             'Z' => {
600                 param_bounds.builtin_bounds.add(ty::BoundSized);
601             }
602             'P' => {
603                 param_bounds.builtin_bounds.add(ty::BoundPod);
604             }
605             'I' => {
606                 param_bounds.trait_bounds.push(@parse_trait_ref(st, |x,y| conv(x,y)));
607             }
608             '.' => {
609                 return param_bounds;
610             }
611             c => {
612                 fail!("parse_bounds: bad bounds ('{}')", c)
613             }
614         }
615     }
616 }