5 Jane Street Holding, LLC
7 email: mmottl\@janestcapital.com
8 WWW: http://www.janestcapital.com/ocaml
10 This library is free software; you can redistribute it and/or
11 modify it under the terms of the GNU Lesser General Public
12 License as published by the Free Software Foundation; either
13 version 2 of the License, or (at your option) any later version.
15 This library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Lesser General Public License for more details.
20 You should have received a copy of the GNU Lesser General Public
21 License along with this library; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 (* Conv: Utility Module for S-expression Conversions *)
31 type 'a sexp_option
= 'a
option
33 (* Conversion of OCaml-values to S-expressions *)
35 let default_string_of_float = ref (fun n
-> sprintf
"%.20G" n
)
36 let read_old_option_format = ref true
37 let write_old_option_format = ref true
39 let sexp_of_unit () = List
[]
40 let sexp_of_bool b
= Atom
(string_of_bool b
)
41 let sexp_of_string str
= Atom str
42 let sexp_of_char c
= Atom
(String.make
1 c
)
43 let sexp_of_int n
= Atom
(string_of_int n
)
44 let sexp_of_float n
= Atom
(!default_string_of_float n
)
45 let sexp_of_int32 n
= Atom
(Int32.to_string n
)
46 let sexp_of_int64 n
= Atom
(Int64.to_string n
)
47 let sexp_of_nativeint n
= Atom
(Nativeint.to_string n
)
48 let sexp_of_big_int n
= Atom
(Big_int.string_of_big_int n
)
49 let sexp_of_nat n
= Atom
(Nat.string_of_nat n
)
50 let sexp_of_num n
= Atom
(Num.string_of_num n
)
51 let sexp_of_ratio n
= Atom
(Ratio.string_of_ratio n
)
52 let sexp_of_ref sexp_of__a rf
= sexp_of__a
!rf
53 let sexp_of_lazy sexp_of__a lv
= sexp_of__a
(Lazy.force lv
)
55 let sexp_of_option sexp_of__a
= function
56 | Some x
when !write_old_option_format -> List
[sexp_of__a x
]
57 | Some x
-> List
[Atom
"some"; sexp_of__a x
]
58 | None
when !write_old_option_format -> List
[]
61 let sexp_of_pair sexp_of__a sexp_of__b
(a
, b
) =
62 List
[sexp_of__a a
; sexp_of__b b
]
64 let sexp_of_triple sexp_of__a sexp_of__b sexp_of__c
(a
, b
, c
) =
65 List
[sexp_of__a a
; sexp_of__b b
; sexp_of__c c
]
67 let sexp_of_list sexp_of__a lst
=
68 List
(List.rev
(List.rev_map sexp_of__a lst
))
70 let sexp_of_array sexp_of__a ar
=
71 let lst_ref = ref [] in
72 for i
= Array.length ar
- 1 downto 0 do
73 lst_ref := sexp_of__a ar
.(i
) :: !lst_ref
77 let sexp_of_hashtbl sexp_of_key sexp_of_val htbl
=
78 let coll k v acc
= List
[sexp_of_key k
; sexp_of_val v
] :: acc
in
79 List
(Hashtbl.fold
coll htbl
[])
81 let sexp_of_float_vec vec
=
82 let lst_ref = ref [] in
83 for i
= Array1.dim vec
downto 1 do
84 lst_ref := sexp_of_float vec
.{i
} :: !lst_ref
88 type vec32
= (float, float32_elt
, fortran_layout
) Array1.t
89 type vec64
= (float, float64_elt
, fortran_layout
) Array1.t
90 let sexp_of_float32_vec (vec
: vec32
) = sexp_of_float_vec vec
91 let sexp_of_float64_vec (vec
: vec64
) = sexp_of_float_vec vec
92 let sexp_of_vec (vec
: vec64
) = sexp_of_float_vec vec
94 let sexp_of_float_mat mat
=
95 let m = Array2.dim1 mat
in
96 let n = Array2.dim2 mat
in
97 let lst_ref = ref [] in
98 for col
= n downto 1 do
99 let vec = Array2.slice_right mat col
in
100 for row
= m downto 1 do
101 lst_ref := sexp_of_float vec.{row
} :: !lst_ref
104 List
(sexp_of_int m :: sexp_of_int n :: !lst_ref)
106 type mat32
= (float, float32_elt
, fortran_layout
) Array2.t
107 type mat64
= (float, float64_elt
, fortran_layout
) Array2.t
108 let sexp_of_float32_mat (mat
: mat32
) = sexp_of_float_mat mat
109 let sexp_of_float64_mat (mat
: mat64
) = sexp_of_float_mat mat
110 let sexp_of_mat (mat
: mat64
) = sexp_of_float_mat mat
112 let sexp_of_abstr _
= Atom
"<abstr>"
113 let sexp_of_fun _
= Atom
"<fun>"
116 let sexp_of_opaque _ _
= Atom
"<opaque>"
118 let string_of__of__sexp_of to_sexp x
= Sexp.to_string
(to_sexp x
)
121 (* Conversion of S-expressions to OCaml-values *)
123 exception Of_sexp_error
of string * Sexp.t
125 let record_check_extra_fields = ref true
127 let of_sexp_error what sexp
= raise
(Of_sexp_error
(what
, sexp
))
129 let unit_of_sexp sexp
= match sexp
with
131 | Atom _
| List _
-> of_sexp_error "unit_of_sexp: empty list needed" sexp
133 let bool_of_sexp sexp
= match sexp
with
134 | Atom
("true" | "True") -> true
135 | Atom
("false" | "False") -> false
136 | Atom _
-> of_sexp_error "bool_of_sexp: unknown string" sexp
137 | List _
-> of_sexp_error "bool_of_sexp: atom needed" sexp
139 let string_of_sexp sexp
= match sexp
with
141 | List _
-> of_sexp_error "string_of_sexp: atom needed" sexp
143 let char_of_sexp sexp
= match sexp
with
145 if String.length str
<> 1 then
147 "char_of_sexp: atom string must contain one character only" sexp
;
149 | List _
-> of_sexp_error "char_of_sexp: atom needed" sexp
151 let int_of_sexp sexp
= match sexp
with
153 (try int_of_string str
154 with exc
-> of_sexp_error ("int_of_sexp: " ^
Printexc.to_string exc
) sexp
)
155 | List _
-> of_sexp_error "int_of_sexp: atom needed" sexp
157 let float_of_sexp sexp
= match sexp
with
159 (try float_of_string str
161 of_sexp_error ("float_of_sexp: " ^
Printexc.to_string exc
) sexp
)
162 | List _
-> of_sexp_error "float_of_sexp: atom needed" sexp
164 let int32_of_sexp sexp
= match sexp
with
166 (try Int32.of_string str
168 of_sexp_error ("int32_of_sexp: " ^
Printexc.to_string exc
) sexp
)
169 | List _
-> of_sexp_error "int32_of_sexp: atom needed" sexp
171 let int64_of_sexp sexp
= match sexp
with
173 (try Int64.of_string str
175 of_sexp_error ("int64_of_sexp: " ^
Printexc.to_string exc
) sexp
)
176 | List _
-> of_sexp_error "int64_of_sexp: atom needed" sexp
178 let nativeint_of_sexp sexp
= match sexp
with
180 (try Nativeint.of_string str
182 of_sexp_error ("nativeint_of_sexp: " ^
Printexc.to_string exc
) sexp
)
183 | List _
-> of_sexp_error "nativeint_of_sexp: atom needed" sexp
185 let big_int_of_sexp sexp
= match sexp
with
187 (try Big_int.big_int_of_string str
189 of_sexp_error ("big_int_of_sexp: " ^
Printexc.to_string exc
) sexp
)
190 | List _
-> of_sexp_error "big_int_of_sexp: atom needed" sexp
192 let nat_of_sexp sexp
= match sexp
with
194 (try Nat.nat_of_string str
196 of_sexp_error ("nat_of_sexp: " ^
Printexc.to_string exc
) sexp
)
197 | List _
-> of_sexp_error "nat_of_sexp: atom needed" sexp
199 let num_of_sexp sexp
= match sexp
with
201 (try Num.num_of_string str
203 of_sexp_error ("num_of_sexp: " ^
Printexc.to_string exc
) sexp
)
204 | List _
-> of_sexp_error "num_of_sexp: atom needed" sexp
206 let ratio_of_sexp sexp
= match sexp
with
208 (try Ratio.ratio_of_string str
210 of_sexp_error ("ratio_of_sexp: " ^
Printexc.to_string exc
) sexp
)
211 | List _
-> of_sexp_error "ratio_of_sexp: atom needed" sexp
213 let ref_of_sexp a__of_sexp sexp
= ref (a__of_sexp sexp
)
214 let lazy_of_sexp a__of_sexp sexp
= lazy (a__of_sexp sexp
)
216 let option_of_sexp a__of_sexp sexp
=
217 if !read_old_option_format then
219 | List
[] | Atom
("none" | "None") -> None
220 | List
[el
] | List
[Atom
("some" | "Some"); el
] -> Some
(a__of_sexp el
)
222 of_sexp_error "option_of_sexp: list must represent optional value" sexp
223 | Atom _
-> of_sexp_error "option_of_sexp: only none can be atom" sexp
226 | Atom
("none" | "None") -> None
227 | List
[Atom
("some" | "Some"); el
] -> Some
(a__of_sexp el
)
228 | Atom _
-> of_sexp_error "option_of_sexp: only none can be atom" sexp
229 | List _
-> of_sexp_error "option_of_sexp: list must be (some el)" sexp
231 let pair_of_sexp a__of_sexp b__of_sexp sexp
= match sexp
with
232 | List
[a_sexp
; b_sexp
] ->
233 let a = a__of_sexp a_sexp
in
234 let b = b__of_sexp b_sexp
in
238 "pair_of_sexp: list must contain exactly two elements only" sexp
239 | Atom _
-> of_sexp_error "pair_of_sexp: list needed" sexp
241 let triple_of_sexp a__of_sexp b__of_sexp c__of_sexp sexp
= match sexp
with
242 | List
[a_sexp
; b_sexp
; c_sexp
] ->
243 let a = a__of_sexp a_sexp
in
244 let b = b__of_sexp b_sexp
in
245 let c = c__of_sexp c_sexp
in
249 "triple_of_sexp: list must contain exactly three elements only" sexp
250 | Atom _
-> of_sexp_error "triple_of_sexp: list needed" sexp
252 let list_of_sexp a__of_sexp sexp
= match sexp
with
254 let rev_lst = List.rev_map a__of_sexp lst
in
256 | Atom _
-> of_sexp_error "list_of_sexp: list needed" sexp
258 let array_of_sexp a__of_sexp sexp
= match sexp
with
261 let len = List.length t
+ 1 in
262 let res = Array.create
len (a__of_sexp h
) in
263 let rec loop i
= function
265 | h
:: t
-> res.(i
) <- a__of_sexp h
; loop (i
+ 1) t
in
267 | Atom _
-> of_sexp_error "array_of_sexp: list needed" sexp
269 let hashtbl_of_sexp key_of_sexp val_of_sexp sexp
= match sexp
with
271 let htbl = Hashtbl.create
0 in
273 | List
[k_sexp
; v_sexp
] ->
274 Hashtbl.add
htbl (key_of_sexp k_sexp
) (val_of_sexp v_sexp
)
276 of_sexp_error "hashtbl_of_sexp: tuple list needed" sexp
280 | Atom _
-> of_sexp_error "hashtbl_of_sexp: list needed" sexp
282 let float_vec_of_sexp empty_float_vec create_float_vec sexp
= match sexp
with
283 | List
[] -> empty_float_vec
285 let len = List.length lst
in
286 let res = create_float_vec
len in
287 let rec loop i
= function
289 | h
:: t
-> res.{i
} <- float_of_sexp h
; loop (i
+ 1) t
in
291 | Atom _
-> of_sexp_error "float_vec_of_sexp: list needed" sexp
293 let create_float32_vec = Array1.create float32 fortran_layout
294 let create_float64_vec = Array1.create float64 fortran_layout
295 let empty_float32_vec = create_float32_vec 0
296 let empty_float64_vec = create_float64_vec 0
297 let float32_vec_of_sexp = float_vec_of_sexp empty_float32_vec create_float32_vec
298 let float64_vec_of_sexp = float_vec_of_sexp empty_float64_vec create_float64_vec
299 let vec_of_sexp = float_vec_of_sexp empty_float64_vec create_float64_vec
301 let check_too_much_data sexp data
res =
302 if data
= [] then res
303 else of_sexp_error "float_mat_of_sexp: too much data" sexp
305 let float_mat_of_sexp create_float_mat sexp
= match sexp
with
306 | List
(sm
:: sn
:: data
) ->
307 let m = int_of_sexp sm
in
308 let n = int_of_sexp sn
in
309 let res = create_float_mat
m n in
310 if m = 0 || n = 0 then check_too_much_data sexp data
res
312 let rec loop_cols col data
=
313 let vec = Array2.slice_right
res col
in
314 let rec loop_rows row
= function
315 | [] -> of_sexp_error "float_mat_of_sexp: not enough data" sexp
317 vec.{row
} <- float_of_sexp h
;
319 if col
= n then check_too_much_data sexp t
res
320 else loop_cols (col
+ 1) t
321 else loop_rows (row
+ 1) t
in
324 | List _
-> of_sexp_error "float_mat_of_sexp: list too short" sexp
325 | Atom _
-> of_sexp_error "float_mat_of_sexp: list needed" sexp
327 let create_float32_mat = Array2.create float32 fortran_layout
328 let create_float64_mat = Array2.create float64 fortran_layout
330 let float32_mat_of_sexp = float_mat_of_sexp create_float32_mat
331 let float64_mat_of_sexp = float_mat_of_sexp create_float64_mat
332 let mat_of_sexp = float_mat_of_sexp create_float64_mat
334 let fun_of_sexp sexp
=
335 of_sexp_error "fun_of_sexp: cannot convert function values" sexp
337 let of_string__of__of_sexp of_sexp s
=
339 let sexp = Sexp.of_string s
in
342 failwith
(sprintf
"of_string failed on %s with %s" s
(Printexc.to_string e
))