File: utils.ml

package info (click to toggle)
ocaml-deriving-ocsigen 0.6.2-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 628 kB
  • ctags: 1,159
  • sloc: ml: 6,334; makefile: 63; sh: 18
file content (246 lines) | stat: -rw-r--r-- 7,309 bytes parent folder | download
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
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
(* Copyright Jeremy Yallop 2007.
   Copyright Grégoire Henry 2011.
   This file is free software, distributed under the MIT license.
   See the file COPYING for details.
*)

type ('a,'b) either = Left of 'a | Right of 'b

let either_partition (f : 'a -> ('b, 'c) either) (l : 'a list)
    : 'b list * 'c list =
  let rec aux (lefts, rights) = function
    | [] -> (List.rev lefts, List.rev rights)
    | x::xs ->
        match f x with
          | Left l  -> aux (l :: lefts, rights) xs
          | Right r -> aux (lefts, r :: rights) xs
  in aux ([], []) l


module List =
struct
  include List

  let fold_left1 : ('a -> 'a -> 'a) -> 'a list -> 'a
    = fun f l -> match l with
      | x::xs  -> List.fold_left f x xs
      | []     -> invalid_arg "fold_left1"

  let rec fold_right1 : ('a -> 'a -> 'a) -> 'a list -> 'a
    = fun f l -> match l with
      | [x]   -> x
      | x::xs -> f x (fold_right1 f xs)
      | []    -> invalid_arg "fold_right1"

  let rec range from upto =
    let rec aux f t result =
      if f = t then result
      else aux (f+1) t (f::result)
    in if upto < from then raise (Invalid_argument "range")
      else List.rev (aux from upto [])

  let rec last : 'a list -> 'a = function
    | []    -> invalid_arg "last"
    | [x]   -> x
    | _::xs -> last xs

  let concat_map f l =
    let rec aux = function
      | _, [] -> []
      | f, x :: xs -> f x @ aux (f, xs)
    in aux (f,l)

  let concat_map2 (f : 'a -> 'b -> 'c list) (l1 : 'a list) (l2 : 'b list) : 'c list =
    let rec aux = function
      | [], [] -> []
      | x::xs, y :: ys -> f x y @ aux (xs, ys)
      | _ -> invalid_arg "concat_map2"
    in aux (l1, l2)

  let mapn ?(init=0) f =
    let rec aux n = function
      | [] -> []
      | x::xs -> f x n :: aux (n+1) xs in
      aux init

  let rec zip xs ys = match xs, ys with
  | [], [] -> []
  | x::xs, y::ys -> (x, y) :: zip xs ys
  | _, _ -> invalid_arg "List.zip"

  let rec split3 xyzs = match xyzs with
  | [] -> [], [], []
  | (x, y, z) :: xyzs ->
      let xs, ys, zs = split3 xyzs in
      x :: xs, y :: ys, z :: zs

end

module F =
struct
  let id x = x
  let curry f x y = f (x,y)
  let uncurry f (x,y) = f x y
end

module Option =
struct
  let map f = function
    | None -> None
    | Some x -> Some (f x)
end

module DumpAst =
struct
  open Camlp4.PreCast.Ast

  let rec ident = function
    | IdAcc (_, i1, i2) -> "IdAcc ("^ident i1^","^ident i2^")"
    | IdApp (_, i1, i2) -> "IdApp ("^ident i1^","^ident i2^")"
    | IdLid (_, s) -> "IdLid("^s^")"
    | IdUid (_, s) -> "IdUid("^s^")"
    | IdAnt (_, s) -> "IdAnt("^s^")"

  let rec ctyp = function
    | TyLab (_, s, c) -> "TyLab ("^s ^ "," ^ ctyp c ^")"
    | TyDcl (_, s, cs, c2, ccs) -> "TyDcl ("^s ^", [" ^ String.concat ";" (List.map ctyp cs) ^"], "^ctyp c2 ^ ", ["^
        String.concat "," (List.map (fun (c1,c2) -> "(" ^ ctyp c1 ^ ", " ^ ctyp c2 ^ ")") ccs)
        ^ "])"
    | TyObj (_, c, _) -> "TyObj ("^ ctyp c ^ ", ?)"
    | TyOlb (_, s, c) -> "TyOlb ("^s ^ "," ^ ctyp c ^")"
    | TyOf (_, c1, c2) -> "TyOf ("^ ctyp c1 ^ ", " ^ ctyp c2 ^ ")"
    | TyOr (_, c1, c2) -> "TyOr ("^ ctyp c1 ^ ", " ^ ctyp c2 ^ ")"
    | TyRec (_, c) -> "TyRec("^ctyp c^")"
    | TySum (_, c) -> "TySum("^ctyp c^")"
    | TyPrv (_, c) -> "TyPrv("^ctyp c^")"
    | TyMut (_, c) -> "TyMut("^ctyp c^")"
    | TyTup (_, c) -> "TyTup("^ctyp c^")"
    | TyVrnEq (_, c) -> "TyVrnEq("^ctyp c^")"
    | TyVrnSup (_, c) -> "TyVrnSup("^ctyp c^")"
    | TyVrnInf (_, c) -> "TyVrnInf("^ctyp c^")"
    | TyCls (_, i) -> "TyCls("^ident i^")"
    | TyId (_, i) -> "TyId("^ident i^")"
    | TyNil (_) -> "TyNil"
    | TyAli (_, c1, c2) -> "TyAli ("^ ctyp c1 ^ ", " ^ ctyp c2 ^")"
    | TyAny (_) -> "TyAny"
    | TyApp (_, c1, c2) -> "TyApp ("^ ctyp c1 ^ ", " ^ ctyp c2 ^")"
    | TyArr (_, c1, c2) -> "TyArr ("^ ctyp c1 ^ ", " ^ ctyp c2 ^")"
    | TyMan (_, c1, c2) -> "TyMan ("^ ctyp c1 ^ ", " ^ ctyp c2 ^")"
    | TyPol (_, c1, c2) -> "TyPol ("^ ctyp c1 ^ ", " ^ ctyp c2 ^")"
    | TyQuo (_, s) -> "TyQuo("^s^")"
    | TyQuP (_, s) -> "TyQuP("^s^")"
    | TyQuM (_, s) -> "TyQuM("^s^")"
    | TyVrn (_, s) -> "TyVrn("^s^")"
    | TyCol (_, c1, c2) -> "TyCol ("^ ctyp c1 ^ ", " ^ ctyp c2 ^")"
    | TySem (_, c1, c2) -> "TySem ("^ ctyp c1 ^ ", " ^ ctyp c2 ^")"
    | TyCom (_, c1, c2) -> "TyCom ("^ ctyp c1 ^ ", " ^ ctyp c2 ^")"
    | TyAnd (_, c1, c2) -> "TyAnd ("^ ctyp c1 ^ ", " ^ ctyp c2 ^")"
    | TySta (_, c1, c2) -> "TySta ("^ ctyp c1 ^ ", " ^ ctyp c2 ^")"
    | TyVrnInfSup (_, c1, c2) -> "TyVrnInfSup ("^ ctyp c1 ^ ", " ^ ctyp c2 ^")"
    | TyAmp (_, c1, c2) -> "TyAmp ("^ ctyp c1 ^ ", " ^ ctyp c2 ^")"
    | TyOfAmp (_, c1, c2) -> "TyOfAmp ("^ ctyp c1 ^ ", " ^ ctyp c2 ^")"
    | TyPkg (_, mt) -> failwith "first-class modules not supported"
    | TyAnt (_, s) -> "TyAnt("^s^")"
#if ocaml_version >= (4, 00)
    | TyTypePol (_, c1, c2) -> "TyTypoPol("^ ctyp c1^ ", "^ ctyp c2 ^")"
    | TyAnP _ -> "TyAnP"
    | TyAnM _ -> "TyAnM"
#endif
end

module Map = struct

  module type OrderedType = Map.OrderedType

  module type S = sig
    include Map.S
    exception Not_found of key
    val fromList : (key * 'a) list -> 'a t
    val union_disjoint : 'a t list -> 'a t
    val union_disjoint2 : 'a t -> 'a t -> 'a t
  end

  module Make(Ord: OrderedType) = struct

    let nf = Not_found
    exception Not_found of Ord.t

    include Map.Make(Ord)

    let find s m =
      try find s m
      with e when e = nf -> raise (Not_found s)

    let fromList : (key * 'a) list -> 'a t = fun elems ->
      List.fold_right (F.uncurry add) elems empty

    let union_disjoint2 l r =
      fold
	(fun k v r ->
           if mem k r then invalid_arg "union_disjoint"
           else add k v r) l r

    let union_disjoint maps = List.fold_right union_disjoint2 maps empty

  end

end

module Set = struct

  module type OrderedType = Set.OrderedType

  module type S = sig
    include Set.S
    val toList : t -> elt list
    val fromList : elt list -> t
  end

  module Make (Ord : OrderedType) = struct
    include Set.Make(Ord)
    let toList t = fold (fun x acc -> x :: acc) t []
    let fromList elems = List.fold_right add elems empty
  end

end

let random_id length =
  let idchars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_'" in
  let nidchars = String.length idchars in
  let s = String.create length in
    for i = 0 to length - 1 do
      s.[i] <- idchars.[Random.int nidchars]
    done;
    s

(* The function used in OCaml to convert variant labels to their
   integer representations.  The formula is given in Jacques
   Garrigue's 1998 ML workshop paper.
*)
let tag_hash s =
  let wrap = 0x40000000 in
  let acc = ref 0 in
  let len = String.length s in
    for i = 0 to len - 1 do
      let c = String.unsafe_get s i in
      let n = Char.code c in
        acc := (223 * !acc + n);
    done;
    acc := !acc land (1 lsl 31 - 1);
    if !acc >= wrap then !acc - (1 lsl 31) else !acc

let _ =
  (* Sanity check to make sure the function doesn't change underneath
     us *)
  assert (tag_hash "premiums" = tag_hash "squigglier");
  assert (tag_hash "deriving" = 398308260);
  assert (tag_hash "Candela" = -1019855834)


(* For type variable renaming *)

let c = "abcdefghijklmnopqrstuvwxyz"

let rec typevar_of_int x =
  assert (x >= 0 && x < 26);
  String.make 1 (c.[x])