1 // run-pass
2
3 #![allow(dead_code)]
4 #![allow(unused_imports)]
5
6 // Test a sample usage pattern for regions. Makes use of the
7 // following features:
8 //
9 // - Multiple lifetime parameters
10 // - Arenas
11
12 #![feature(rustc_private, libc)]
13
14 extern crate rustc_arena;
15 extern crate libc;
16
17 // Necessary to pull in object code as the rest of the rustc crates are shipped only as rmeta
18 // files.
19 #[allow(unused_extern_crates)]
20 extern crate rustc_driver;
21
22 use TypeStructure::{TypeInt, TypeFunction};
23 use AstKind::{ExprInt, ExprVar, ExprLambda};
24 use rustc_arena::TypedArena;
25 use std::collections::HashMap;
26 use std::mem;
27
28 type Type<'tcx> = &'tcx TypeStructure<'tcx>;
29
30 #[derive(Copy, Clone, Debug)]
31 enum TypeStructure<'tcx> {
32 TypeInt,
33 TypeFunction(Type<'tcx>, Type<'tcx>),
34 }
35
36 impl<'tcx> PartialEq for TypeStructure<'tcx> {
eq(&self, other: &TypeStructure<'tcx>) -> bool37 fn eq(&self, other: &TypeStructure<'tcx>) -> bool {
38 match (*self, *other) {
39 (TypeInt, TypeInt) => true,
40 (TypeFunction(s_a, s_b), TypeFunction(o_a, o_b)) => *s_a == *o_a && *s_b == *o_b,
41 _ => false
42 }
43 }
44 }
45
46 impl<'tcx> Eq for TypeStructure<'tcx> {}
47
48 type TyArena<'tcx> = TypedArena<TypeStructure<'tcx>>;
49 type AstArena<'ast> = TypedArena<AstStructure<'ast>>;
50
51 struct TypeContext<'tcx, 'ast> {
52 ty_arena: &'tcx TyArena<'tcx>,
53 types: Vec<Type<'tcx>> ,
54 type_table: HashMap<NodeId, Type<'tcx>>,
55
56 ast_arena: &'ast AstArena<'ast>,
57 ast_counter: usize,
58 }
59
60 impl<'tcx,'ast> TypeContext<'tcx, 'ast> {
new(ty_arena: &'tcx TyArena<'tcx>, ast_arena: &'ast AstArena<'ast>) -> TypeContext<'tcx, 'ast>61 fn new(ty_arena: &'tcx TyArena<'tcx>, ast_arena: &'ast AstArena<'ast>)
62 -> TypeContext<'tcx, 'ast> {
63 TypeContext { ty_arena: ty_arena,
64 types: Vec::new(),
65 type_table: HashMap::new(),
66
67 ast_arena: ast_arena,
68 ast_counter: 0 }
69 }
70
add_type(&mut self, s: TypeStructure<'tcx>) -> Type<'tcx>71 fn add_type(&mut self, s: TypeStructure<'tcx>) -> Type<'tcx> {
72 for &ty in &self.types {
73 if *ty == s {
74 return ty;
75 }
76 }
77
78 let ty = self.ty_arena.alloc(s);
79 self.types.push(ty);
80 ty
81 }
82
set_type(&mut self, id: NodeId, ty: Type<'tcx>) -> Type<'tcx>83 fn set_type(&mut self, id: NodeId, ty: Type<'tcx>) -> Type<'tcx> {
84 self.type_table.insert(id, ty);
85 ty
86 }
87
ast(&mut self, a: AstKind<'ast>) -> Ast<'ast>88 fn ast(&mut self, a: AstKind<'ast>) -> Ast<'ast> {
89 let id = self.ast_counter;
90 self.ast_counter += 1;
91 self.ast_arena.alloc(AstStructure { id: NodeId {id:id}, kind: a })
92 }
93 }
94
95 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
96 struct NodeId {
97 id: usize
98 }
99
100 type Ast<'ast> = &'ast AstStructure<'ast>;
101
102 #[derive(Copy, Clone)]
103 struct AstStructure<'ast> {
104 id: NodeId,
105 kind: AstKind<'ast>
106 }
107
108 #[derive(Copy, Clone)]
109 enum AstKind<'ast> {
110 ExprInt,
111 ExprVar(usize),
112 ExprLambda(Ast<'ast>),
113 }
114
compute_types<'tcx,'ast>(tcx: &mut TypeContext<'tcx,'ast>, ast: Ast<'ast>) -> Type<'tcx>115 fn compute_types<'tcx,'ast>(tcx: &mut TypeContext<'tcx,'ast>,
116 ast: Ast<'ast>) -> Type<'tcx>
117 {
118 match ast.kind {
119 ExprInt | ExprVar(_) => {
120 let ty = tcx.add_type(TypeInt);
121 tcx.set_type(ast.id, ty)
122 }
123 ExprLambda(ast) => {
124 let arg_ty = tcx.add_type(TypeInt);
125 let body_ty = compute_types(tcx, ast);
126 let lambda_ty = tcx.add_type(TypeFunction(arg_ty, body_ty));
127 tcx.set_type(ast.id, lambda_ty)
128 }
129 }
130 }
131
main()132 pub fn main() {
133 let ty_arena = TypedArena::default();
134 let ast_arena = TypedArena::default();
135 let mut tcx = TypeContext::new(&ty_arena, &ast_arena);
136 let ast = tcx.ast(ExprInt);
137 let ty = compute_types(&mut tcx, ast);
138 assert_eq!(*ty, TypeInt);
139 }
140