ocaml/middle_end/freshening.mli

168 lines
6.2 KiB
OCaml

(**************************************************************************)
(* *)
(* OCaml *)
(* *)
(* Pierre Chambart, OCamlPro *)
(* Mark Shinwell and Leo White, Jane Street Europe *)
(* *)
(* Copyright 2013--2016 OCamlPro SAS *)
(* Copyright 2014--2016 Jane Street Group LLC *)
(* *)
(* All rights reserved. This file is distributed under the terms of *)
(* the GNU Lesser General Public License version 2.1, with the *)
(* special exception on linking described in the file LICENSE. *)
(* *)
(**************************************************************************)
[@@@ocaml.warning "+a-4-9-30-40-41-42"]
(** Freshening of various identifiers. *)
(** A table used for freshening variables and static exception identifiers. *)
type t
type subst = t
(** The freshening that does nothing. This is the unique inactive
freshening. *)
val empty : t
val is_empty : t -> bool
(** Activate the freshening. Without activation, operations to request
freshenings have no effect (cf. the documentation below for
[add_variable]). As such, the inactive renaming is unique. *)
val activate : t -> t
(** Given the inactive freshening, return the same; otherwise, return an
empty active freshening. *)
val empty_preserving_activation_state : t -> t
(** [add_variable t var]
If [t] is active:
It returns a fresh variable [new_var] and adds [var] -> [new_var]
to the freshening.
If a renaming [other_var] -> [var] or [symbol] -> [var] was already
present in [t], it will also add [other_var] -> [new_var] and
[symbol] -> [new_var].
If [t] is inactive, this is the identity.
*)
val add_variable : t -> Variable.t -> Variable.t * t
(** Like [add_variable], but for multiple variables, each freshened
separately. *)
val add_variables'
: t
-> Variable.t list
-> Variable.t list * t
(** Like [add_variables'], but passes through the second component of the
input list unchanged. *)
val add_variables
: t
-> (Variable.t * 'a) list
-> (Variable.t * 'a) list * t
(** Like [add_variable], but for mutable variables. *)
val add_mutable_variable : t -> Mutable_variable.t -> Mutable_variable.t * t
(** As for [add_variable], but for static exception identifiers. *)
val add_static_exception : t -> Static_exception.t -> Static_exception.t * t
(** [apply_variable t var] applies the freshening [t] to [var].
If no renaming is specified in [t] for [var] it is returned unchanged. *)
val apply_variable : t -> Variable.t -> Variable.t
(** As for [apply_variable], but for mutable variables. *)
val apply_mutable_variable : t -> Mutable_variable.t -> Mutable_variable.t
(** As for [apply_variable], but for static exception identifiers. *)
val apply_static_exception : t -> Static_exception.t -> Static_exception.t
(** Replace recursive accesses to the closures in the set through
[Symbol] by the corresponding [Var]. This is used to recover
the recursive call when importing code from another compilation unit.
If the renaming is inactive, this is the identity.
*)
val rewrite_recursive_calls_with_symbols
: t
-> Flambda.function_declarations
-> make_closure_symbol:(Closure_id.t -> Symbol.t)
-> Flambda.function_declarations
(* CR-soon mshinwell for mshinwell: maybe inaccurate module name, it freshens
closure IDs as well. Check use points though *)
module Project_var : sig
(** A table used for freshening of identifiers in [Project_closure] and
[Move_within_set_of_closures] ("ids of closures"); and [Project_var]
("bound vars of closures") expressions.
This information is propagated bottom up and populated when inlining a
function containing a closure declaration.
For instance,
[let f x =
let g y = ... x ... in
... g.x ... (Project_var x)
... g 1 ... (Apply (Project_closure g ...))
]
If f is inlined, g is renamed. The approximation of g will carry this
table such that later the access to the field x of g and selection of
g in the closure can be substituted.
*)
type t
(* The freshening that does nothing. *)
val empty : t
(** Composition of two freshenings. *)
val compose : earlier:t -> later:t -> t
(** Freshen a closure ID based on the given renaming. The same ID is
returned if the renaming does not affect it.
If dealing with approximations, you probably want to use
[Simple_value_approx.freshen_and_check_closure_id] instead of this
function.
*)
val apply_closure_id : t -> Closure_id.t -> Closure_id.t
(** Like [apply_closure_id], but for variables within closures. *)
val apply_var_within_closure
: t
-> Var_within_closure.t
-> Var_within_closure.t
val print : Format.formatter -> t -> unit
end
(* CR-soon mshinwell for mshinwell: add comment *)
val apply_function_decls_and_free_vars
: t
-> (Flambda.specialised_to * 'a) Variable.Map.t
-> Flambda.function_declarations
-> only_freshen_parameters:bool
-> (Flambda.specialised_to * 'a) Variable.Map.t
* Flambda.function_declarations
* t
* Project_var.t
val does_not_freshen : t -> Variable.t list -> bool
val print : Format.formatter -> t -> unit
(** N.B. This does not freshen the domain of the supplied map, only the
range. *)
(* CR-someday mshinwell: consider fixing that *)
val freshen_projection_relation
: Flambda.specialised_to Variable.Map.t
-> freshening:t
-> closure_freshening:Project_var.t
-> Flambda.specialised_to Variable.Map.t
val freshen_projection_relation'
: (Flambda.specialised_to * 'a) Variable.Map.t
-> freshening:t
-> closure_freshening:Project_var.t
-> (Flambda.specialised_to * 'a) Variable.Map.t