Skip to content

Commit

Permalink
Continue refactoring coroutines for lambda lowering
Browse files Browse the repository at this point in the history
Summary: In order to correctly generate properties, etc, for coroutine closure classes we will need to classify all the locals used in a lambda into outer variables, inner variables, and formal parameters. In this refactoring, I create a tool in the lambda analyzer to do that, and fix up the closure data to be initialized from it.  Tweaks to the actual codegen will come in a subsequent diff.

Reviewed By: michaeltingley

Differential Revision: D5504520

fbshipit-source-id: 03bd16f1402b0441a9ed3575d328334360c64bb3
  • Loading branch information
ericlippert authored and hhvm-bot committed Jul 27, 2017
1 parent 2a1bcb5 commit f2760fe
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 28 deletions.
Expand Up @@ -852,34 +852,17 @@ let extract_parameter_declarations function_parameter_list =
end

let compute_state_machine_data
locals_and_params
(inner_variables, outer_variables, used_params)
coroutine_result_data_variables
outer_variables
function_parameter_list =
let parameters = extract_parameter_declarations function_parameter_list in
(* TODO: Add a test case for "..." param. *)
let parameter_names =
parameters
|> Core_list.map ~f:
begin
function
| {
parameter_name =
{
syntax =
Token { EditableToken.kind = TokenKind.Variable; text; _; };
_;
};
_;
} ->
text
| _ -> failwith "Parameter had unexpected token."
end
|> SSet.of_list in
let local_variables = SSet.diff locals_and_params parameter_names in
let parameters = extract_parameter_declarations function_parameter_list in
let local_variables = SSet.union inner_variables outer_variables in
let local_variables = SSet.elements local_variables in
(* TODO: Why is this a map? *)
let local_variables = local_variables @
(SMap.keys coroutine_result_data_variables) in
let outer_variables = SSet.elements outer_variables in
CoroutineStateMachineData.{ local_variables; parameters; outer_variables; }

(**
Expand All @@ -894,15 +877,11 @@ let generate_coroutine_state_machine
function_parameter_list =
let new_body, coroutine_result_data_variables =
lower_body original_body in
(* TODO: Refactor this so that the lambda analyzer partitions used locals
into parameters, inner variables and outer variables. *)
let outer_variables = Lambda_analyzer.outer_variables
context.Coroutine_context.parents original_body in
let used_locals = all_used_locals original_body in
let used_locals = Lambda_analyzer.partition_used_locals
context.Coroutine_context.parents function_parameter_list original_body in
let state_machine_data = compute_state_machine_data
used_locals
coroutine_result_data_variables
outer_variables
function_parameter_list in
let closure_syntax =
CoroutineClosureGenerator.generate_coroutine_closure
Expand Down
13 changes: 13 additions & 0 deletions hphp/hack/src/parser/lambda_analyzer.ml
Expand Up @@ -112,6 +112,7 @@ let get_body node =
| AnonymousFunction { anonymous_body; _ } -> anonymous_body
| _ -> make_missing()

(* TODO: This does not consider situations like "${x}" as the use of a local.*)
let add_local acc node =
match syntax node with
| VariableExpression { variable_expression =
Expand Down Expand Up @@ -164,3 +165,15 @@ let outer_variables parents lambda =
let outer = SSet.inter all_outer all_used in
SSet.elements outer
(* Note that we are guaranteed that the list is sorted. *)

let partition_used_locals parents params body =
let all_used = fold_no_lambdas add_local SSet.empty body in
let all_used = SSet.remove "$this" all_used in
let decls = syntax_node_to_list params in
let all_params = List.filter_map decls ~f:param_name in
let all_params = SSet.of_list all_params in
let used_params = SSet.inter all_used all_params in
let all_outer = List.fold_left parents ~f:local_variables ~init:SSet.empty in
let used_outer = SSet.inter all_used all_outer in
let inner = SSet.diff all_used (SSet.union used_params used_outer) in
(inner, used_outer, used_params)

0 comments on commit f2760fe

Please sign in to comment.