Permalink
Browse files

Emit strict_types directive

Summary: Emit strict_types directive in hhas if php7.scalar_types option is specified

Reviewed By: oulgen

Differential Revision: D6720224

fbshipit-source-id: af4e19ae6e479bdfe228be704267c34f58d86b94
  • Loading branch information...
vladima authored and hhvm-bot committed Jan 17, 2018
1 parent 8b1b511 commit 5ad487d593f2fea39b08b93d8be7a44782fb59a6
@@ -154,8 +154,9 @@ type decl =
| ClassRefs_decl of SSet.t
| FunctionRefs_decl of SSet.t
| HHFile_decl of bool
| StrictTypes_decl of bool
let rec split_decl_list ds hh_file funs classes optmain datadecls aliasdecls
let rec split_decl_list ds hh_file strict_types funs classes optmain datadecls aliasdecls
includesdecls constantrefsdecls classrefsdecls functionrefsdecls =
match ds with
| [] ->
@@ -169,45 +170,48 @@ let rec split_decl_list ds hh_file funs classes optmain datadecls aliasdecls
; Hhas_symbol_refs.functions = functionrefsdecls
} in
Hhas_program.make hh_file (List.rev datadecls) (List.rev funs)
(List.rev classes) (List.rev aliasdecls) m symbol_refs
(List.rev classes) (List.rev aliasdecls) m symbol_refs (Some strict_types)
end
| Main_decl md :: rest ->
begin match optmain with
| None ->
split_decl_list rest hh_file funs classes (Some md) datadecls aliasdecls
split_decl_list rest hh_file strict_types funs classes (Some md) datadecls aliasdecls
includesdecls constantrefsdecls classrefsdecls functionrefsdecls
| Some _ -> report_error "duplicate main"
end
| Fun_decl fd :: rest ->
split_decl_list rest hh_file (fd :: funs) classes optmain datadecls aliasdecls
split_decl_list rest hh_file strict_types (fd :: funs) classes optmain datadecls aliasdecls
includesdecls constantrefsdecls classrefsdecls functionrefsdecls
| Class_decl cd :: rest ->
split_decl_list rest hh_file funs (cd :: classes) optmain datadecls aliasdecls
split_decl_list rest hh_file strict_types funs (cd :: classes) optmain datadecls aliasdecls
includesdecls constantrefsdecls classrefsdecls functionrefsdecls
| Data_decl dd :: rest ->
split_decl_list rest hh_file funs classes optmain (dd :: datadecls) aliasdecls
split_decl_list rest hh_file strict_types funs classes optmain (dd :: datadecls) aliasdecls
includesdecls constantrefsdecls classrefsdecls functionrefsdecls
| Alias_decl ad :: rest ->
split_decl_list rest hh_file funs classes optmain datadecls (ad :: aliasdecls)
split_decl_list rest hh_file strict_types funs classes optmain datadecls (ad :: aliasdecls)
includesdecls constantrefsdecls classrefsdecls functionrefsdecls
| Includes_decl ids :: rest ->
let includes = Hhas_symbol_refs.IncludePathSet.union ids includesdecls in
split_decl_list rest hh_file funs classes optmain datadecls aliasdecls
split_decl_list rest hh_file strict_types funs classes optmain datadecls aliasdecls
includes constantrefsdecls classrefsdecls functionrefsdecls
| ConstantRefs_decl crs :: rest ->
let constant_refs = SSet.union crs constantrefsdecls in
split_decl_list rest hh_file funs classes optmain datadecls aliasdecls
split_decl_list rest hh_file strict_types funs classes optmain datadecls aliasdecls
includesdecls constant_refs classrefsdecls functionrefsdecls
| ClassRefs_decl crs :: rest ->
let class_refs = SSet.union crs classrefsdecls in
split_decl_list rest hh_file funs classes optmain datadecls aliasdecls
split_decl_list rest hh_file strict_types funs classes optmain datadecls aliasdecls
includesdecls constantrefsdecls class_refs functionrefsdecls
| FunctionRefs_decl frs :: rest ->
let function_refs = SSet.union frs functionrefsdecls in
split_decl_list rest hh_file funs classes optmain datadecls aliasdecls
split_decl_list rest hh_file strict_types funs classes optmain datadecls aliasdecls
includesdecls constantrefsdecls classrefsdecls function_refs
| HHFile_decl hh_file :: rest ->
split_decl_list rest hh_file funs classes optmain datadecls aliasdecls
split_decl_list rest hh_file strict_types funs classes optmain datadecls aliasdecls
includesdecls constantrefsdecls classrefsdecls functionrefsdecls
| StrictTypes_decl strict_types :: rest ->
split_decl_list rest hh_file strict_types funs classes optmain datadecls aliasdecls
includesdecls constantrefsdecls classrefsdecls functionrefsdecls
(* This is a pretty poor way to deal with these flags on functions, and
@@ -19,6 +19,12 @@ module SU = Hhbc_string_utils
let constant_folding () =
Hhbc_options.constant_folding !Hhbc_options.compiler_options
type convert_result = {
ast_defs: (bool * Ast.def) list;
global_state: Emit_env.global_state;
strict_types: bool option;
}
type variables = {
(* all variables declared/used in the scope*)
all_vars: SSet.t;
@@ -95,6 +101,7 @@ type state = {
(* maps name of function that has at least one goto statement
to labels in function (bool value denotes whether label appear in using) *)
function_to_labels_map: (bool SMap.t) SMap.t;
seen_strict_types: bool option;
}
let initial_state =
@@ -116,6 +123,7 @@ let initial_state =
has_finally = false;
goto_state = empty_goto_state;
function_to_labels_map = SMap.empty;
seen_strict_types = None;
}
let total_class_count env st =
@@ -821,6 +829,9 @@ and convert_stmt env st (p, stmt_ as stmt) : _ * stmt =
if st.goto_state.has_goto then st
else { st with goto_state = { st.goto_state with has_goto = true } } in
st, stmt
| Declare (_, (_, Binop (Eq None, (_, Id (_, "strict_types")), (_, Int (_, v)))), _) ->
let st = { st with seen_strict_types = Some (v = "1") } in
st, stmt
| _ ->
st, stmt
@@ -1047,11 +1058,16 @@ let convert_toplevel_prog defs =
let original_defs = hoist_toplevel_functions original_defs in
let fun_defs = List.rev_map st.hoisted_functions (fun fd -> false, Fun fd) in
let class_defs = List.rev_map st.hoisted_classes (fun cd -> false, Class cd) in
(fun_defs @ original_defs @ class_defs,
let ast_defs = fun_defs @ original_defs @ class_defs in
let global_state =
Emit_env.(
{ global_explicit_use_set = st.explicit_use_set
; global_closure_namespaces = st.closure_namespaces
; global_closure_enclosing_classes = st.closure_enclosing_classes
; global_functions_with_finally = st.functions_with_finally
; global_function_to_labels_map = st.function_to_labels_map })
)
; global_function_to_labels_map = st.function_to_labels_map }) in
{
ast_defs;
global_state;
strict_types = st.seen_strict_types;
}
@@ -8,7 +8,11 @@
*
*)
type convert_result = {
ast_defs: (bool * Ast.def) list;
global_state: Emit_env.global_state;
strict_types: bool option;
}
(* Convert entire program *)
val convert_toplevel_prog :
Ast.program ->
(bool * Ast.def) list * Emit_env.global_state
val convert_toplevel_prog : Ast.program -> convert_result
@@ -49,7 +49,7 @@ let emit_fatal_program ~ignore_message op pos message =
[] (* static_inits static_inits *)
None (* doc *)
in
Hhas_program.make false [] [] [] [] body Emit_symbol_refs.empty_symbol_refs
Hhas_program.make false [] [] [] [] body Emit_symbol_refs.empty_symbol_refs None
let from_ast ~is_hh_file ~is_evaled ast =
Utils.try_finally
@@ -58,8 +58,13 @@ let from_ast ~is_hh_file ~is_evaled ast =
Emit_env.set_is_hh_file is_hh_file;
(* Convert closures to top-level classes;
* also hoist inner classes and functions *)
let closed_ast, global_state =
let { ast_defs = closed_ast; global_state; strict_types } =
convert_toplevel_prog ast in
let strict_types =
(* is scalar_types is set - always assume strict_types to have value *)
if Hhbc_options.php7_scalar_types !(Hhbc_options.compiler_options)
then if strict_types = None then Some false else strict_types
else None in
Emit_env.set_global_state global_state;
let flat_closed_ast = List.map snd closed_ast in
let compiled_defs = emit_main is_evaled flat_closed_ast in
@@ -71,7 +76,7 @@ let from_ast ~is_hh_file ~is_evaled ast =
let hhas = Hhas_program.make
is_hh_file
adata compiled_funs compiled_classes
compiled_typedefs compiled_defs symbol_refs in
compiled_typedefs compiled_defs symbol_refs strict_types in
hhas
with Emit_fatal.IncludeTimeFatalException (op, pos, message) ->
emit_fatal_program ~ignore_message:false op pos message
@@ -54,7 +54,7 @@ open Hhas_parser_actions
%type <Instruction_sequence.t> functionbody
%%
program:
nl decllist nl EOF { split_decl_list $2 false [] [] None [] [] Hhas_symbol_refs.IncludePathSet.empty SSet.empty SSet.empty SSet.empty}
nl decllist nl EOF { split_decl_list $2 false false [] [] None [] [] Hhas_symbol_refs.IncludePathSet.empty SSet.empty SSet.empty SSet.empty}
;
decl:
| maindecl {Main_decl $1}
@@ -547,7 +547,7 @@ decllist:
/* empty */ { [] }
| decl nl decllist {$1 :: $3}
| FILEPATHDIRECTIVE STRING SEMI nl decllist {$5}
| STRICTDIRECTIVE INT SEMI nl decllist {$5}
| STRICTDIRECTIVE INT SEMI nl decllist { StrictTypes_decl ($2 = 1L) :: $5}
| HHFILE INT SEMI nl decllist { HHFile_decl ($2 = 1L) :: $5 }
;
includesdecl:
@@ -16,10 +16,13 @@ type t = {
hhas_typedefs : Hhas_typedef.t list;
hhas_main : Hhas_body.t;
hhas_symbol_refs : Hhas_symbol_refs.t;
hhas_strict_types: bool option;
}
let make hhas_is_hh hhas_adata hhas_fun hhas_classes hhas_typedefs hhas_main hhas_symbol_refs =
{ hhas_is_hh; hhas_adata; hhas_fun; hhas_classes; hhas_typedefs; hhas_main; hhas_symbol_refs; }
let make hhas_is_hh hhas_adata hhas_fun hhas_classes hhas_typedefs hhas_main
hhas_symbol_refs hhas_strict_types =
{ hhas_is_hh; hhas_adata; hhas_fun; hhas_classes; hhas_typedefs; hhas_main;
hhas_symbol_refs; hhas_strict_types; }
let is_hh hhas_prog =
hhas_prog.hhas_is_hh
@@ -42,6 +45,9 @@ let adata hhas_prog =
let symbol_refs hhas_prog =
hhas_prog.hhas_symbol_refs
let strict_types hhas_prog =
hhas_prog.hhas_strict_types
let with_main hhas_prog hhas_main =
{hhas_prog with hhas_main}
@@ -1642,15 +1642,21 @@ let add_program_content ?path dump_symbol_refs buf hhas_prog =
end
let add_program ?path dump_symbol_refs buf hhas_prog =
let strict_types =
match Hhas_program.strict_types hhas_prog with
| Some true -> ".strict 1;\n\n"
| Some false -> ".strict 0;\n\n"
| None -> "" in
match path with
| Some p ->
let p = Relative_path.to_absolute p in
B.add_string buf
(Printf.sprintf "# %s starts here\n\n.filepath \"%s\";\n" p p);
(Printf.sprintf "# %s starts here\n\n%s.filepath \"%s\";\n" p strict_types p);
add_program_content ~path:p dump_symbol_refs buf hhas_prog;
B.add_string buf (Printf.sprintf "\n# %s ends here\n" p)
| None ->
B.add_string buf "#starts here\n";
B.add_string buf strict_types;
add_program_content dump_symbol_refs buf hhas_prog;
B.add_string buf "\n#ends here\n"
@@ -828,7 +828,8 @@ let mutate_metadata (input : HP.t) =
(prog |> HP.classes |> delete_map (mutate_class_data ids))
(prog |> HP.typedefs |> delete_map mutate_typedef)
(prog |> HP.main |> mutate_body_data)
Emit_symbol_refs.empty_symbol_refs in
Emit_symbol_refs.empty_symbol_refs
(prog |> HP.strict_types |> option_lift mutate_bool) in
let open Nondet in
return input |> num_fold
(fun a -> mut_data input |> add_event a) !metadata_reps
@@ -46,22 +46,12 @@ slow/parser/php-reserved-name-parent-2.php
slow/parser/php-reserved-name-self-2.php
slow/parser/static_call_access_const_expr.php
slow/parser/unicode-literal-error.php
slow/php7_backported/scalar-types/explicit_weak_include_strict.php
slow/php7_backported/scalar-types/internal_function_strict_mode.php
slow/php7_backported/scalar-types/scalar_strict.php
slow/php7_backported/scalar-types/scalar_strict_64bit.php
slow/php7_backported/scalar-types/scalar_strict_basic.php
slow/php7_backported/scalar-types/strict_call_weak.php
slow/php7_backported/scalar-types/strict_call_weak_explicit.php
slow/php7_backported/scalar-types/weak_include_strict.php
slow/preg-file-mode.php
slow/reflection/1352.php
slow/reflection_classes/default_value_with_namespace.php
slow/reflection_classes/default_value_with_namespace2.php
slow/reflection_classes/default_value_with_namespace3.php
slow/reflection_classes/default_value_with_self.php
slow/typecheck/type_coersion_7strict.php
slow/typecheck/type_coersion_7strict_include.php
slow/unpack_args/unpack_call_error.php
slow/unpack_args/unpack_call_multi.php
slow/variadic_args/by_reference_typehints.php
@@ -41,23 +41,13 @@ slow/parser/php-reserved-name-parent-2.php
slow/parser/php-reserved-name-self-2.php
slow/parser/static_call_access_const_expr.php
slow/parser/unicode-literal-error.php
slow/php7_backported/scalar-types/explicit_weak_include_strict.php
slow/php7_backported/scalar-types/internal_function_strict_mode.php
slow/php7_backported/scalar-types/scalar_strict.php
slow/php7_backported/scalar-types/scalar_strict_64bit.php
slow/php7_backported/scalar-types/scalar_strict_basic.php
slow/php7_backported/scalar-types/strict_call_weak.php
slow/php7_backported/scalar-types/strict_call_weak_explicit.php
slow/php7_backported/scalar-types/weak_include_strict.php
slow/reflection/1352.php
slow/reflection_classes/default_value_with_namespace.php
slow/reflection_classes/default_value_with_namespace2.php
slow/reflection_classes/default_value_with_namespace3.php
slow/reflection_classes/default_value_with_self.php
slow/traits/require_constraint_basic_error.php
slow/traits/require_constraint_recurse.php
slow/typecheck/type_coersion_7strict.php
slow/typecheck/type_coersion_7strict_include.php
slow/unpack_args/unpack_call_error.php
slow/unpack_args/unpack_call_multi.php
slow/variadic_args/by_reference.php

0 comments on commit 5ad487d

Please sign in to comment.