1
(************************************************************************)
2
(* v * The Coq Proof Assistant / The Coq Development Team *)
3
(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
4
(* \VV/ **************************************************************)
5
(* // * This file is distributed under the terms of the *)
6
(* * GNU Lesser General Public License Version 2.1 *)
7
(************************************************************************)
11
(* This module defines validation functions to ensure an imported
12
value (using input_value) has the correct structure. *)
14
let rec pr_obj_rec o =
16
Format.print_int(Obj.magic o)
17
else if Obj.is_block o then
19
if t > Obj.no_scan_tag then
20
if t = Obj.string_tag then
21
Format.print_string ("\""^String.escaped(Obj.magic o)^"\"")
23
Format.print_string "?"
25
(let n = Obj.size o in
26
Format.print_string ("#"^string_of_int t^"(");
29
pr_obj_rec (Obj.field o i);
30
if i<>n-1 then (Format.print_string ","; Format.print_cut())
33
Format.print_string ")")
34
else Format.print_string "?"
36
let pr_obj o = pr_obj_rec o; Format.print_newline()
38
(**************************************************************************)
39
(* Obj low-level validators *)
41
exception ValidObjError of string * Obj.t
42
let fail o s = raise (ValidObjError(s,o))
47
with ValidObjError(msg,obj) ->
49
print_endline ("Validation failed: "^msg);
52
failwith "validation failed"
54
(* data not validated *)
55
let no_val (o:Obj.t) = ()
57
(* Check that object o is a block with tag t *)
59
if Obj.is_block o && Obj.tag o = t then ()
60
else fail o ("expected tag "^string_of_int t)
63
if Obj.is_block o then
64
(if Obj.tag o > Obj.no_scan_tag then
65
fail o (s^": found no scan tag"))
66
else fail o (s^": expected block obj")
68
(* Check that an object is a tuple (or a record). v is an array of
69
validation functions for each field. Its size corresponds to the
70
expected size of the object. *)
72
let n = Array.length v in
73
val_block ("tuple: "^s) o;
74
if Obj.size o = n then
75
Array.iteri (fun i f -> f (Obj.field o i)) v
77
fail o ("tuple:" ^s^" size found:"^string_of_int (Obj.size o))
79
(* Check that the object is either a constant constructor of tag < cc,
80
or a constructed variant. each element of vv is an array of
81
validation functions to be applied to the constructor arguments.
82
The size of vv corresponds to the number of non-constant
83
constructors, and the size of vv.(i) is the expected arity of the
84
i-th non-constant constructor. *)
85
let val_sum s cc vv o =
86
if Obj.is_block o then
88
let n = Array.length vv in
90
if i < n then val_tuple (s^"(tag "^string_of_int i^")") vv.(i) o
91
else fail o ("bad tag in (sum type) "^s^": max is "^string_of_int i))
92
else if Obj.is_int o then
93
let (n:int) = Obj.magic o in
95
fail o (s^": bad constant constructor "^string_of_int n))
96
else fail o ("not a sum ("^s^")")
98
let val_enum s n = val_sum s n [||]
100
(* Recursive types: avoid looping by eta-expansion *)
101
let rec val_rec_sum s cc f o =
102
val_sum s cc (f (val_rec_sum s cc f)) o
104
let rec val_rectype f o =
107
(**************************************************************************)
110
(* Check the o is an array of values satisfying f. *)
111
let val_array ?(name="array") f o =
113
for i = 0 to Obj.size o - 1 do
114
(f (Obj.field o i):unit)
117
(* Integer validator *)
119
if not (Obj.is_int o) then fail o "expected an int"
121
(* String validator *)
123
try val_tag Obj.string_tag o
124
with Failure _ -> fail o "expected a string"
127
let val_bool = val_enum "bool" 2
130
let val_opt ?(name="option") f = val_sum name 1 [|[|f|]|]
133
let val_list ?(name="list") f =
134
val_rec_sum name 1 (fun vlist -> [|[|f;vlist|]|])
137
let val_ref ?(name="ref") f = val_tuple name [|f|]
139
(**************************************************************************)
140
(* Standard library types *)
143
let val_set ?(name="Set.t") f =
144
val_rec_sum name 1 (fun vset -> [|[|vset;f;vset;val_int|]|])
147
let rec val_map ?(name="Map.t") fk fv =
148
val_rec_sum name 1 (fun vmap -> [|[|vmap;fk;fv;vmap;val_int|]|])
150
(**************************************************************************)
156
let val_dp = val_list ~name:"dirpath" val_id
158
let val_name = val_sum "name" 1 [|[|val_id|]|]
160
let val_uid = val_tuple "uniq_ident" [|val_int;val_str;val_dp|]
163
val_rec_sum "module_path" 0
164
(fun vmp -> [|[|val_dp|];[|val_uid|];[|val_uid|];[|vmp;val_id|]|])
166
let val_kn = val_tuple "kernel_name" [|val_mp;val_dp;val_id|]
168
let val_ind = val_tuple "inductive"[|val_kn;val_int|]
169
let val_cstr = val_tuple "constructor"[|val_ind;val_int|]
172
let val_level = val_sum "level" 1 [|[|val_dp;val_int|]|]
173
let val_univ = val_sum "univ" 0
174
[|[|val_level|];[|val_list val_level;val_list val_level|]|]
177
val_set ~name:"Univ.constraints"
178
(val_tuple "univ_constraint"
179
[|val_level;val_enum "order_request" 3;val_level|])