// run-pass #![allow(dead_code)] #![allow(unused_imports)] // Test a sample usage pattern for regions. Makes use of the // following features: // // - Multiple lifetime parameters // - Arenas #![feature(rustc_private, libc)] extern crate rustc_arena; extern crate libc; // Necessary to pull in object code as the rest of the rustc crates are shipped only as rmeta // files. #[allow(unused_extern_crates)] extern crate rustc_driver; use TypeStructure::{TypeInt, TypeFunction}; use AstKind::{ExprInt, ExprVar, ExprLambda}; use rustc_arena::TypedArena; use std::collections::HashMap; use std::mem; type Type<'tcx> = &'tcx TypeStructure<'tcx>; #[derive(Copy, Clone, Debug)] enum TypeStructure<'tcx> { TypeInt, TypeFunction(Type<'tcx>, Type<'tcx>), } impl<'tcx> PartialEq for TypeStructure<'tcx> { fn eq(&self, other: &TypeStructure<'tcx>) -> bool { match (*self, *other) { (TypeInt, TypeInt) => true, (TypeFunction(s_a, s_b), TypeFunction(o_a, o_b)) => *s_a == *o_a && *s_b == *o_b, _ => false } } } impl<'tcx> Eq for TypeStructure<'tcx> {} type TyArena<'tcx> = TypedArena>; type AstArena<'ast> = TypedArena>; struct TypeContext<'tcx, 'ast> { ty_arena: &'tcx TyArena<'tcx>, types: Vec> , type_table: HashMap>, ast_arena: &'ast AstArena<'ast>, ast_counter: usize, } impl<'tcx,'ast> TypeContext<'tcx, 'ast> { fn new(ty_arena: &'tcx TyArena<'tcx>, ast_arena: &'ast AstArena<'ast>) -> TypeContext<'tcx, 'ast> { TypeContext { ty_arena: ty_arena, types: Vec::new(), type_table: HashMap::new(), ast_arena: ast_arena, ast_counter: 0 } } fn add_type(&mut self, s: TypeStructure<'tcx>) -> Type<'tcx> { for &ty in &self.types { if *ty == s { return ty; } } let ty = self.ty_arena.alloc(s); self.types.push(ty); ty } fn set_type(&mut self, id: NodeId, ty: Type<'tcx>) -> Type<'tcx> { self.type_table.insert(id, ty); ty } fn ast(&mut self, a: AstKind<'ast>) -> Ast<'ast> { let id = self.ast_counter; self.ast_counter += 1; self.ast_arena.alloc(AstStructure { id: NodeId {id:id}, kind: a }) } } #[derive(Copy, Clone, PartialEq, Eq, Hash)] struct NodeId { id: usize } type Ast<'ast> = &'ast AstStructure<'ast>; #[derive(Copy, Clone)] struct AstStructure<'ast> { id: NodeId, kind: AstKind<'ast> } #[derive(Copy, Clone)] enum AstKind<'ast> { ExprInt, ExprVar(usize), ExprLambda(Ast<'ast>), } fn compute_types<'tcx,'ast>(tcx: &mut TypeContext<'tcx,'ast>, ast: Ast<'ast>) -> Type<'tcx> { match ast.kind { ExprInt | ExprVar(_) => { let ty = tcx.add_type(TypeInt); tcx.set_type(ast.id, ty) } ExprLambda(ast) => { let arg_ty = tcx.add_type(TypeInt); let body_ty = compute_types(tcx, ast); let lambda_ty = tcx.add_type(TypeFunction(arg_ty, body_ty)); tcx.set_type(ast.id, lambda_ty) } } } pub fn main() { let ty_arena = TypedArena::default(); let ast_arena = TypedArena::default(); let mut tcx = TypeContext::new(&ty_arena, &ast_arena); let ast = tcx.ast(ExprInt); let ty = compute_types(&mut tcx, ast); assert_eq!(*ty, TypeInt); }