package fix

  1. Overview
  2. Docs

Source file Indexing.ml

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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
(******************************************************************************)
(*                                                                            *)
(*                                    Fix                                     *)
(*                                                                            *)
(*                       François Pottier, Inria Paris                        *)
(*                                                                            *)
(*  Copyright Inria. All rights reserved. This file is distributed under the  *)
(*  terms of the GNU Library General Public License version 2, with a         *)
(*  special exception on linking, as described in the file LICENSE.           *)
(*                                                                            *)
(******************************************************************************)

(* A suspension is used to represent a cardinal-that-may-still-be-unknown. *)

type 'n cardinal =
  int Lazy.t

(* The function [cardinal] forces the cardinal to become fixed. *)

let cardinal =
  Lazy.force

type 'n index =
  int

module type CARDINAL = sig type n val n : n cardinal end

(* [Empty] and [Const] produce sets whose cardinal is known. *)

module Empty : CARDINAL = struct
  type n
  let n = lazy 0
end

module Const (X : sig val cardinal : int end) : CARDINAL = struct
  type n
  let () = assert (X.cardinal >= 0)
  let n = lazy X.cardinal
end

let const c : (module CARDINAL) =
  assert (c >= 0);
  (module struct type n let n = lazy c end)

(* [Gensym] produces a set whose cardinal is a priori unknown. A new reference
   stores the current cardinal, which grows when [fresh()] is invoked. [fresh]
   fails if the suspension [n] has been forced. *)

module Gensym () = struct

  type n
  let counter = ref 0
  let n = lazy !counter

  let fresh () =
    assert (not (Lazy.is_val n));
    let result = !counter in
    incr counter;
    result

end

type ('l, 'r) either =
  | L of 'l
  | R of 'r

module type SUM = sig
  type l and r
  include CARDINAL
  val inj_l : l index -> n index
  val inj_r : r index -> n index
  val prj : n index -> (l index, r index) either
end

module Sum (L : CARDINAL)(R : CARDINAL) = struct

  type n

  type l = L.n
  type r = R.n

  (* The cardinal [l] of the left-hand set becomes fixed now (if it
     wasn't already). We need it to be fixed for our injections and
     projections to make sense. *)
  let l : int = cardinal L.n
  (* The right-hand set can remain open-ended. *)
  let r : int cardinal = R.n

  let n =
    (* We optimize the case where [r] is fixed already, but the code
       in the [else] branch would work always. *)
    if Lazy.is_val r then
      let n = l + cardinal r in
      lazy n
    else
      lazy (l + cardinal r)

  (* Injections. The two sets are numbered side by side. *)
  let inj_l x = x
  let inj_r y = l + y

  (* Projection. *)
  let prj x = if x < l then L x else R (x - l)

end

let sum (type l r) (l : l cardinal) (r : r cardinal) =
  let module L = struct type n = l let n = l end in
  let module R = struct type n = r let n = r end in
  (module Sum(L)(R) : SUM with type l = l and type r = r)

module Index = struct

  type 'n t = 'n index

  let of_int (n : 'n cardinal) i : 'n index =
    let n = cardinal n in
    assert (0 <= i && i < n);
    i

  let to_int i = i

  let iter (n : 'n cardinal) (yield : 'n index -> unit) =
    let n = cardinal n in
    for i = 0 to n - 1 do
      yield i
    done

  exception End_of_set

  let enumerate (n : 'n cardinal) : unit -> 'n index =
    let n = cardinal n in
    let next = ref 0 in
    fun () ->
      let i = !next in
      if n <= i then raise End_of_set;
      incr next;
      i

end

type ('n, 'a) vector =
  'a array

module Vector = struct

  type ('n, 'a) t = ('n, 'a) vector

  let get = Array.unsafe_get
  let set = Array.unsafe_set

  let set_cons t i x =
    set t i (x :: get t i)

  let length a =
    let n = Array.length a in
    lazy n

  let empty = [||]

  let make (n : _ cardinal) x =
    let n = cardinal n in
    Array.make n x

  let make' (n : _ cardinal) f =
    let n = cardinal n in
    if n = 0 then
      empty
    else
      Array.make n (f())

  let init (n : _ cardinal) f =
    let n = cardinal n in
    Array.init n f

  let map = Array.map

end
OCaml

Innovation. Community. Security.