1 // Copyright (c) Facebook, Inc. and its affiliates.
3 // This source code is licensed under the MIT license found in the
4 // LICENSE file in the "hack" directory of this source tree.
7 use std::cell::RefCell;
11 use crate::reason::Reason;
12 use crate::tast::SavedEnv;
13 use crate::typing_ctx::TypingCtx;
14 use crate::typing_defs::{ParamMode, Ty};
15 use crate::typing_error::TypingError;
16 use crate::typing_local_types::{Local, LocalMap};
17 use crate::typing_return::TypingReturnInfo;
18 use crate::utils::core::{IdentGen, LocalId};
22 pub struct TEnv<R: Reason> {
23 pub ctx: Arc<TypingCtx<R>>,
29 errors: Rc<RefCell<Vec<TypingError<R>>>>,
32 struct TGEnv<R: Reason> {
33 return_: RefCell<TypingReturnInfo<R>>,
34 params: RefCell<HashMap<LocalId, (Ty<R>, R::Pos, ParamMode)>>,
37 struct TLEnv<R: Reason> {
38 per_cont_env: PerContEnv<R>,
41 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
53 #[derive(Debug, Clone)]
54 struct PerContEnv<R: Reason>(RefCell<HashMap<TypingContKey, PerContEntry<R>>>);
56 #[derive(Debug, Clone)]
57 struct PerContEntry<R: Reason> {
58 local_types: LocalMap<R>,
61 impl<R: Reason> TGEnv<R> {
62 fn new(ctx: &TypingCtx<R>) -> Self {
64 return_: RefCell::new(TypingReturnInfo::placeholder(ctx.alloc)),
65 params: RefCell::new(HashMap::new()),
70 impl<R: Reason> TLEnv<R> {
73 per_cont_env: PerContEnv::new(),
78 impl<R: Reason> PerContEnv<R> {
80 Self(RefCell::new(HashMap::new()))
83 fn add(&self, key: TypingContKey, x: LocalId, ty: Local<R>) {
84 if let Some(cont) = self.0.borrow_mut().get_mut(&key) {
85 cont.local_types.add(x, ty);
89 fn get(&self, key: TypingContKey, x: &LocalId) -> Option<Local<R>> {
93 .and_then(|env| env.local_types.get(x))
97 fn has_cont(&self, key: TypingContKey) -> bool {
98 self.0.borrow().get(&key).is_some()
102 impl<R: Reason> TEnv<R> {
103 pub fn new(ctx: Arc<TypingCtx<R>>) -> Self {
104 let genv = Rc::new(TGEnv::new(&ctx));
109 lenv: Rc::new(TLEnv::new()),
111 idents: IdentGen::new(),
112 errors: Rc::new(RefCell::new(Vec::new())),
116 pub fn destruct(self) -> Vec<TypingError<R>> {
117 let mut empty = Vec::new();
118 let mut full = self.errors.borrow_mut();
119 std::mem::swap(&mut empty, &mut full);
123 pub fn add_error(&self, error: TypingError<R>) {
124 self.errors.borrow_mut().push(error)
127 pub fn fun_env(ctx: Arc<TypingCtx<R>>, _fd: &oxidized::aast::FunDef<(), ()>) -> Self {
131 pub fn set_param(&self, id: LocalId, ty: Ty<R>, pos: R::Pos, param_mode: ParamMode) {
135 .insert(id, (ty, pos, param_mode));
138 pub fn get_params(&self) -> HashMap<LocalId, (Ty<R>, R::Pos, ParamMode)> {
139 self.genv.params.borrow().clone()
142 pub fn set_params(&self, m: HashMap<LocalId, (Ty<R>, R::Pos, ParamMode)>) {
143 *self.genv.params.borrow_mut() = m;
146 fn set_local_(&self, x: LocalId, ty: Local<R>) {
147 self.lenv.per_cont_env.add(TypingContKey::Next, x, ty);
150 pub fn set_local(&self, immutable: bool, x: LocalId, ty: Ty<R>, pos: R::Pos) {
151 // TODO(hrust): union simplification
152 let expr_id = match self.lenv.per_cont_env.get(TypingContKey::Next, &x) {
153 None => self.idents.make(),
154 Some(l) => l.expr_id,
159 self.set_local_(x, Local { ty, pos, expr_id })
162 pub fn get_return(&self) -> TypingReturnInfo<R> {
163 self.genv.return_.borrow().clone()
166 pub fn set_return(&self, ret: TypingReturnInfo<R>) {
167 *self.genv.return_.borrow_mut() = ret;
170 pub fn has_next(&self) -> bool {
171 self.lenv.per_cont_env.has_cont(TypingContKey::Next)
174 pub fn save(&self, _local_tpenv: ()) -> SavedEnv {