Check argument to 'unset' in reactive mode
[hiphop-php.git] / hphp / hack / src / hhbc / emit_env.ml
blobff3db7029fa0da469a9d4742ca6379cdcd96d51c
1 (**
2 * Copyright (c) 2017, Facebook, Inc.
3 * All rights reserved.
5 * This source code is licensed under the MIT license found in the
6 * LICENSE file in the "hack" directory of this source tree.
8 *)
10 type t = {
11 env_pipe_var : Local.t option;
12 env_scope : Ast_scope.Scope.t;
13 env_namespace : Namespace_env.env;
14 env_needs_local_this : bool;
15 env_jump_targets : Jump_targets.t;
16 env_in_try : bool;
17 env_allows_array_append : bool;
20 type global_state =
21 { global_explicit_use_set: SSet.t
22 ; global_closure_namespaces: Namespace_env.env SMap.t
23 ; global_closure_enclosing_classes: Ast.class_ SMap.t
24 ; global_functions_with_finally: SSet.t
25 ; global_function_to_labels_map: (bool SMap.t) SMap.t
26 ; global_functions_with_hhas_blocks: (string list) SMap.t
29 let empty_global_state =
30 { global_explicit_use_set = SSet.empty
31 ; global_closure_namespaces = SMap.empty
32 ; global_closure_enclosing_classes = SMap.empty
33 ; global_functions_with_finally = SSet.empty
34 ; global_function_to_labels_map = SMap.empty
35 ; global_functions_with_hhas_blocks = SMap.empty
38 let is_hh_file_ = ref false
39 let is_systemlib_ = ref false
40 let global_state_ = ref empty_global_state
42 let set_is_hh_file v = is_hh_file_ := v
43 let set_is_systemlib v = is_systemlib_ := v
45 let is_hh_syntax_enabled () =
46 !is_hh_file_ || Hhbc_options.enable_hiphop_syntax !Hhbc_options.compiler_options
47 let is_systemlib () = !is_systemlib_
49 let get_explicit_use_set () = (!global_state_).global_explicit_use_set
50 let get_closure_namespaces () = (!global_state_).global_closure_namespaces
51 let get_closure_enclosing_classes () =
52 (!global_state_).global_closure_enclosing_classes
53 let get_functions_with_finally () =
54 (!global_state_).global_functions_with_finally
55 let get_function_to_labels_map () =
56 (!global_state_).global_function_to_labels_map
57 let get_inline_hhas_blocks key =
58 SMap.get key (!global_state_).global_functions_with_hhas_blocks
59 |> Option.value ~default:[]
61 let get_unique_id_for_main () =
62 "|"
63 let get_unique_id_for_function { Ast.f_name = (_, n); _ } =
64 "|" ^ n
65 let get_unique_id_for_method { Ast.c_name = (_, cls); _ } { Ast.m_name = (_, m); _} =
66 cls ^ "|" ^ m
68 let set_global_state s = global_state_ := s
69 let clear_global_state () = set_global_state empty_global_state
71 let empty = {
72 env_pipe_var = None;
73 env_scope = Ast_scope.Scope.toplevel;
74 env_namespace = Namespace_env.empty_with_default_popt;
75 env_needs_local_this = false;
76 env_jump_targets = Jump_targets.empty;
77 env_in_try = false;
78 env_allows_array_append = false;
81 let get_pipe_var env = env.env_pipe_var
82 let get_scope env = env.env_scope
83 let get_namespace env = env.env_namespace
84 let get_needs_local_this env = env.env_needs_local_this
85 let get_jump_targets env = env.env_jump_targets
86 let is_in_try env = env.env_in_try
87 let does_env_allow_array_append env = env.env_allows_array_append
89 (* Environment is second parameter so we can chain these e.g.
90 * empty |> with_scope scope |> with_namespace ns
92 let with_scope scope env =
93 { env with env_scope = scope }
94 let with_namespace namespace env =
95 { env with env_namespace = namespace }
96 let with_needs_local_this needs_local_this env =
97 { env with env_needs_local_this = needs_local_this }
98 let with_pipe_var v env =
99 { env with env_pipe_var = Some v }
100 let make_class_env ast_class =
101 { env_pipe_var = None; env_scope = [Ast_scope.ScopeItem.Class ast_class];
102 env_namespace = ast_class.Ast.c_namespace; env_needs_local_this = false;
103 env_jump_targets = Jump_targets.empty; env_in_try = false;
104 env_allows_array_append = false;
106 let with_try env = { env with env_in_try = true }
108 let do_in_loop_body break_label continue_label ?iter env s f =
109 Jump_targets.with_loop (!is_hh_file_) break_label continue_label
110 iter env.env_jump_targets s @@
111 fun env_jump_targets s -> f { env with env_jump_targets } s
113 let do_in_switch_body end_label env s f =
114 Jump_targets.with_switch (!is_hh_file_) end_label
115 env.env_jump_targets s @@
116 fun env_jump_targets s -> f { env with env_jump_targets } s
118 let do_in_try_body finally_label env s f =
119 Jump_targets.with_try (!is_hh_file_) finally_label
120 env.env_jump_targets s @@
121 fun env_jump_targets s -> f { env with env_jump_targets } s
123 let do_in_finally_body env s f =
124 Jump_targets.with_finally (!is_hh_file_)
125 env.env_jump_targets s @@
126 fun env_jump_targets s -> f { env with env_jump_targets } s
128 let do_in_using_body finally_label env s f =
129 Jump_targets.with_using (!is_hh_file_) finally_label
130 env.env_jump_targets s @@
131 fun env_jump_targets s -> f { env with env_jump_targets } s
133 let do_function env s f =
134 Jump_targets.with_function (!is_hh_file_)
135 env.env_jump_targets s @@
136 fun env_jump_targets s -> f { env with env_jump_targets } s