Skip to content

Commit

Permalink
feat(engine/phases): intro simplify_hoisting
Browse files Browse the repository at this point in the history
This commit introduces a phase that simplifies the pattern:

```
/// Note `let` below is NOT monadic
let hoistN = e in body
```

into `body[hoistN/e]`, when:

 - the local ident `hoistN` is of kind `SideEffectHoistVar` (we know it was produced by the side effect utils module);
 - `body` contains exactly one occurence of `hoistN`.

That simplifies greatly the extracted code.
  • Loading branch information
W95Psp committed Mar 12, 2024
1 parent 5204e6c commit 6cc0fca
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 15 deletions.
1 change: 1 addition & 0 deletions engine/backends/fstar/fstar_backend.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1357,6 +1357,7 @@ module TransformToInputLanguage =
|> Phases.Functionalize_loops
|> Phases.Reject.As_pattern
|> Phases.Traits_specs
|> Phases.Simplify_hoisting
|> SubtypeToInputLanguage
|> Identity
]
Expand Down
1 change: 1 addition & 0 deletions engine/lib/diagnostics.ml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ module Phase = struct
| FunctionalizeLoops
| TraitsSpecs
| SimplifyMatchReturn
| SimplifyHoisting
| DropNeedlessReturns
| DummyA
| DummyB
Expand Down
4 changes: 3 additions & 1 deletion engine/lib/local_ident.ml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ module T = struct

let make_final name = { name; id = mk_id Final 0 }
let is_final { id; _ } = [%matches? Final] @@ fst id
let is_side_effect_hoist_var {id; _} = [%matches? SideEffectHoistVar] @@ fst id

let is_side_effect_hoist_var { id; _ } =
[%matches? SideEffectHoistVar] @@ fst id
end

include Base.Comparator.Make (T)
Expand Down
23 changes: 9 additions & 14 deletions engine/lib/local_ident.mli
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
module T : sig
type kind =
Typ
(** type namespace *)
| Cnst
(** Generic constant namespace *)
| Expr
(** Expression namespace *)
| LILifetime
(** Lifetime namespace *)
| Final
(** Frozen identifier: such an identifier will *not* be rewritten by the name policy *)
| SideEffectHoistVar
(** A variable generated by `Side_effect_utils` *)
| Typ (** type namespace *)
| Cnst (** Generic constant namespace *)
| Expr (** Expression namespace *)
| LILifetime (** Lifetime namespace *)
| Final
(** Frozen identifier: such an identifier will *not* be rewritten by the name policy *)
| SideEffectHoistVar (** A variable generated by `Side_effect_utils` *)
[@@deriving show, yojson, hash, compare, sexp, eq]

type id [@@deriving show, yojson, hash, compare, sexp, eq]
Expand All @@ -21,10 +16,10 @@ module T : sig
type t = { name : string; id : id }
[@@deriving show, yojson, hash, compare, sexp, eq]

(** Creates a frozen final local identifier: such an indentifier won't be rewritten by a name policy *)
val make_final : string -> t
val is_final : t -> bool
(** Creates a frozen final local identifier: such an indentifier won't be rewritten by a name policy *)

val is_final : t -> bool
val is_side_effect_hoist_var : t -> bool
end

Expand Down
1 change: 1 addition & 0 deletions engine/lib/phases.ml
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ module Traits_specs = Phase_traits_specs.Make
module Drop_needless_returns = Phase_drop_needless_returns.Make
module Drop_sized_trait = Phase_drop_sized_trait.Make
module Simplify_match_return = Phase_simplify_match_return.Make
module Simplify_hoisting = Phase_simplify_hoisting.Make
66 changes: 66 additions & 0 deletions engine/lib/phases/phase_simplify_hoisting.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
open! Prelude

module Make (F : Features.T) =
Phase_utils.MakeMonomorphicPhase
(F)
(struct
let phase_id = Diagnostics.Phase.SimplifyHoisting

open Ast.Make (F)
module U = Ast_utils.Make (F)
module Visitors = Ast_visitors.Make (F)

module Error = Phase_utils.MakeError (struct
let ctx = Diagnostics.Context.Phase phase_id
end)

let inline_matches =
object
inherit [_] Visitors.map as super

method! visit_expr () e =
match e with
| {
e =
Let
{
monadic = None;
lhs =
{
p =
PBinding
{
mut = Immutable;
mode = ByValue;
var;
subpat = None;
_;
};
_;
};
rhs;
body;
};
_;
}
when Local_ident.is_side_effect_hoist_var var ->
let body, count =
(object
inherit [_] Visitors.mapreduce as super
method zero = 0
method plus = ( + )

method! visit_expr () e =
match e.e with
| LocalVar v when [%eq: Local_ident.t] v var -> (rhs, 1)
| _ -> super#visit_expr () e
end)
#visit_expr
() body
in
if [%eq: int] count 1 then body else super#visit_expr () e
| _ -> super#visit_expr () e
end

let ditems = List.map ~f:(inline_matches#visit_item ())
end)
4 changes: 4 additions & 0 deletions engine/lib/phases/phase_simplify_hoisting.mli
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
(** This phase rewrites `let pat = match ... { ... => ..., ... => return ... }; e`
into `match ... { ... => let pat = ...; e}`. *)

module Make : Phase_utils.UNCONSTRAINTED_MONOMORPHIC_PHASE

0 comments on commit 6cc0fca

Please sign in to comment.