summaryrefslogtreecommitdiff
path: root/lambda/switch.mli
blob: 5744193751abc3e267d1e89de9b4b24dae32cb77 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
(**************************************************************************)
(*                                                                        *)
(*                                 OCaml                                  *)
(*                                                                        *)
(*             Luc Maranget, projet Moscova, INRIA Rocquencourt           *)
(*                                                                        *)
(*   Copyright 2000 Institut National de Recherche en Informatique et     *)
(*     en Automatique.                                                    *)
(*                                                                        *)
(*   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.          *)
(*                                                                        *)
(**************************************************************************)

(*
  This module transforms generic switches in combinations
  of if tests and switches.
*)

(* For detecting action sharing, object style *)

(* Store for actions in object style:
  act_store : store an action, returns index in table
              In case an action with equal key exists, returns index
              of the stored action. Otherwise add entry in table.
  act_store_shared : This stored action will always be shared.
  act_get   : retrieve table
  act_get_shared : retrieve table, with sharing explicit
*)

type 'a shared = Shared of 'a | Single of 'a

type ('a, 'ctx) t_store =
    {act_get : unit -> 'a array ;
     act_get_shared : unit -> 'a shared array ;
     act_store : 'ctx -> 'a -> int ;
     act_store_shared : 'ctx -> 'a -> int ; }

module type Stored = sig
  type t
  type key
  val compare_key : key -> key -> int
  val make_key : t -> key option
end

module type CtxStored = sig
  include Stored
  type context
  val make_key : context -> t -> key option
end

module CtxStore(A:CtxStored) :
    sig
      val mk_store : unit -> (A.t, A.context) t_store
    end

module Store(A:Stored) :
    sig
      val mk_store : unit -> (A.t, unit) t_store
    end

(* Arguments to the Make functor *)
module type S =
  sig
    (* type of basic tests *)
    type primitive
    (* basic tests themselves *)
    val eqint : primitive
    val neint : primitive
    val leint : primitive
    val ltint : primitive
    val geint : primitive
    val gtint : primitive

    (* type of source locations *)
    type loc
    (* type of switch scrutinees *)
    type arg
    (* type of tests on scrutinees *)
    type test
    (* type of actions *)
    type act

    (* Various constructors, for making a binder,
        adding one integer, etc. *)

    (* [bind arg cont] should bind the expression arg to a variable,
       then call [cont] on that variable, and return the term made of
       the binding and the result of the call. *)
    val bind : arg -> (arg -> act) -> act
    (* [make_const n] generates a term for the integer constant [n] *)
    val make_const : int -> arg
    (* [make_offset arg n] generates a term for adding the constant
       integer [n] to the term [arg] *)
    val make_offset : arg -> int -> arg
    (* [make_prim p args] generates a test using the primitive operation [p]
       applied to arguments [args] *)
    val make_prim : primitive -> arg list -> test
    (* [make_isout h arg] generates a test that holds when [arg] is out of
       the interval [0, h] *)
    val make_isout : arg -> arg -> test
    (* [make_isin h arg] generates a test that holds when [arg] is in
       the interval [0, h] *)
    val make_isin : arg -> arg -> test
    (* [make_is_nonzero arg] generates a test that holds when [arg] is any
       value except 0 *)
    val make_is_nonzero : arg -> test
    (* [arg_as_test arg] casts [arg], known to be either 0 or 1,
       to a boolean test *)
    val arg_as_test : arg -> test
    (* [make_if cond ifso ifnot] generates a conditional branch *)
    val make_if : test -> act -> act -> act
   (* construct an actual switch :
      make_switch arg cases acts
      NB:  cases is in the value form *)
    val make_switch : loc -> arg -> int array -> act array -> act

   (* Build last minute sharing of action stuff *)
   val make_catch : act -> int * (act -> act)
   val make_exit : int -> act
  end


(*
  Make.zyva arg low high cases actions where
    - arg is the argument of the switch.
    - low, high are the interval limits.
    - cases is a list of sub-interval and action indices
    - actions is an array of actions.

  All these arguments specify a switch construct and zyva
  returns an action that performs the switch.
*)
module Make :
  functor (Arg : S) ->
    sig
(* Standard entry point, sharing is tracked *)
      val zyva :
          Arg.loc ->
          (int * int) ->
           Arg.arg ->
           (int * int * int) array ->
           (Arg.act, _) t_store ->
           Arg.act

(* Output test sequence, sharing tracked *)
     val test_sequence :
           Arg.arg ->
           (int * int * int) array ->
           (Arg.act, _) t_store ->
           Arg.act
    end