ocaml/middle_end/projection.ml

170 lines
6.1 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"]
(* CR-someday mshinwell: Move these three types into their own modules. *)
type project_closure = {
set_of_closures : Variable.t;
closure_id : Closure_id.t;
}
type move_within_set_of_closures = {
closure : Variable.t;
start_from : Closure_id.t;
move_to : Closure_id.t;
}
type project_var = {
closure : Variable.t;
closure_id : Closure_id.t;
var : Var_within_closure.t;
}
let compare_project_var
({ closure = closure1; closure_id = closure_id1; var = var1; }
: project_var)
({ closure = closure2; closure_id = closure_id2; var = var2; }
: project_var) =
let c = Variable.compare closure1 closure2 in
if c <> 0 then c
else
let c = Closure_id.compare closure_id1 closure_id2 in
if c <> 0 then c
else
Var_within_closure.compare var1 var2
let compare_move_within_set_of_closures
({ closure = closure1; start_from = start_from1; move_to = move_to1; }
: move_within_set_of_closures)
({ closure = closure2; start_from = start_from2; move_to = move_to2; }
: move_within_set_of_closures) =
let c = Variable.compare closure1 closure2 in
if c <> 0 then c
else
let c = Closure_id.compare start_from1 start_from2 in
if c <> 0 then c
else
Closure_id.compare move_to1 move_to2
let compare_project_closure
({ set_of_closures = set_of_closures1; closure_id = closure_id1; }
: project_closure)
({ set_of_closures = set_of_closures2; closure_id = closure_id2; }
: project_closure) =
let c = Variable.compare set_of_closures1 set_of_closures2 in
if c <> 0 then c
else
Closure_id.compare closure_id1 closure_id2
let print_project_closure ppf (project_closure : project_closure) =
Format.fprintf ppf "@[<2>(project_closure@ %a@ from@ %a)@]"
Closure_id.print project_closure.closure_id
Variable.print project_closure.set_of_closures
let print_move_within_set_of_closures ppf
(move_within_set_of_closures : move_within_set_of_closures) =
Format.fprintf ppf
"@[<2>(move_within_set_of_closures@ %a <-- %a@ (closure = %a))@]"
Closure_id.print move_within_set_of_closures.move_to
Closure_id.print move_within_set_of_closures.start_from
Variable.print move_within_set_of_closures.closure
let print_project_var ppf (project_var : project_var) =
Format.fprintf ppf "@[<2>(project_var@ %a@ from %a=%a)@]"
Var_within_closure.print project_var.var
Closure_id.print project_var.closure_id
Variable.print project_var.closure
type t =
| Project_var of project_var
| Project_closure of project_closure
| Move_within_set_of_closures of move_within_set_of_closures
| Field of int * Variable.t
include Identifiable.Make (struct
type nonrec t = t
let compare t1 t2 =
match t1, t2 with
| Project_var project_var1, Project_var project_var2 ->
compare_project_var project_var1 project_var2
| Project_closure project_closure1, Project_closure project_closure2 ->
compare_project_closure project_closure1 project_closure2
| Move_within_set_of_closures move1, Move_within_set_of_closures move2 ->
compare_move_within_set_of_closures move1 move2
| Field (index1, var1), Field (index2, var2) ->
let c = compare index1 index2 in
if c <> 0 then c
else Variable.compare var1 var2
| Project_var _, _ -> -1
| _, Project_var _ -> 1
| Project_closure _, _ -> -1
| _, Project_closure _ -> 1
| Move_within_set_of_closures _, _ -> -1
| _, Move_within_set_of_closures _ -> -1
let equal t1 t2 =
(compare t1 t2) = 0
let hash = Hashtbl.hash
let print ppf t =
match t with
| Project_closure (project_closure) ->
print_project_closure ppf project_closure
| Project_var (project_var) -> print_project_var ppf project_var
| Move_within_set_of_closures (move_within_set_of_closures) ->
print_move_within_set_of_closures ppf move_within_set_of_closures
| Field (field_index, var) ->
Format.fprintf ppf "Field %d of %a" field_index Variable.print var
let output _ _ = failwith "Projection.output: not yet implemented"
end)
let projecting_from t =
match t with
| Project_var { closure; _ } -> closure
| Project_closure { set_of_closures; _ } -> set_of_closures
| Move_within_set_of_closures { closure; _ } -> closure
| Field (_, var) -> var
let map_projecting_from t ~f : t =
match t with
| Project_var project_var ->
let project_var : project_var =
{ project_var with
closure = f project_var.closure;
}
in
Project_var project_var
| Project_closure project_closure ->
let project_closure : project_closure =
{ project_closure with
set_of_closures = f project_closure.set_of_closures;
}
in
Project_closure project_closure
| Move_within_set_of_closures move ->
let move : move_within_set_of_closures =
{ move with
closure = f move.closure;
}
in
Move_within_set_of_closures move
| Field (field_index, var) -> Field (field_index, f var)