/[svn]/typing/typer.ml
ViewVC logotype

Contents of /typing/typer.ml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1368 - (hide annotations)
Tue Jul 10 18:43:07 2007 UTC (5 years, 10 months ago) by abate
File size: 56963 byte(s)
[r2004-12-25 20:39:15 by afrisch] Default values for record fields

Original author: afrisch
Date: 2004-12-25 20:39:15+00:00
1 abate 237 (* TODO:
2 abate 276 - rewrite type-checking of operators to propagate constraint
3 abate 278 - optimize computation of pattern free variables
4     - check whether it is worth using recursive hash-consing internally
5 abate 276 *)
6 abate 237
7 abate 677 open Location
8     open Ast
9     open Ident
10 abate 276
11 abate 786 let debug_schema = false
12    
13 abate 320 let warning loc msg =
14 abate 695 Format.fprintf !Location.warning_ppf "Warning %a:@\n%a%s@."
15 abate 522 Location.print_loc (loc,`Full)
16     Location.html_hilight (loc,`Full)
17 abate 320 msg
18    
19 abate 1190 exception NonExhaustive of Types.descr
20     exception Constraint of Types.descr * Types.descr
21     exception ShouldHave of Types.descr * string
22     exception ShouldHave2 of Types.descr * string * Types.descr
23     exception WrongLabel of Types.descr * label
24     exception UnboundId of id * bool
25     exception UnboundExtId of Types.CompUnit.t * id
26     exception Error of string
27    
28 abate 1238
29     exception Warning of string * Types.t
30    
31 abate 1190 let raise_loc loc exn = raise (Location (loc,`Full,exn))
32     let raise_loc_str loc ofs exn = raise (Location (loc,`Char ofs,exn))
33     let error loc msg = raise_loc loc (Error msg)
34    
35 abate 686 type item =
36     | Type of Types.t
37 abate 691 | Val of Types.t
38 abate 686
39 abate 1096 module UEnv = Map.Make(U)
40    
41 abate 691 type t = {
42 abate 686 ids : item Env.t;
43 abate 713 ns: Ns.table;
44 abate 1096 cu: Types.CompUnit.t UEnv.t;
45 abate 1190 schemas: string UEnv.t
46 abate 677 }
47 abate 542
48 abate 698 let hash _ = failwith "Typer.hash"
49     let compare _ _ = failwith "Typer.compare"
50     let dump ppf _ = failwith "Typer.dump"
51     let equal _ _ = failwith "Typer.equal"
52     let check _ = failwith "Typer.check"
53 abate 691
54     (* TODO: filter out builtin defs ? *)
55 abate 705 let serialize_item s = function
56     | Type t -> Serialize.Put.bits 1 s 0; Types.serialize s t
57     | Val t -> Serialize.Put.bits 1 s 1; Types.serialize s t
58    
59 abate 691 let serialize s env =
60 abate 705 Serialize.Put.env Id.serialize serialize_item Env.iter s env.ids;
61 abate 713 Ns.serialize_table s env.ns
62 abate 691
63 abate 705 let deserialize_item s = match Serialize.Get.bits 1 s with
64     | 0 -> Type (Types.deserialize s)
65     | 1 -> Val (Types.deserialize s)
66     | _ -> assert false
67    
68 abate 691 let deserialize s =
69 abate 1190 let ids = Serialize.Get.env Id.deserialize deserialize_item Env.add Env.empty s in
70 abate 691 let ns = Ns.deserialize_table s in
71 abate 1190 { ids = ids; ns = ns; cu = UEnv.empty; schemas = UEnv.empty }
72 abate 691
73    
74 abate 686 let empty_env = {
75     ids = Env.empty;
76 abate 713 ns = Ns.empty_table;
77 abate 1096 cu = UEnv.empty;
78 abate 1190 schemas = UEnv.empty
79 abate 686 }
80    
81 abate 713 let from_comp_unit = ref (fun cu -> assert false)
82    
83 abate 723 let enter_cu x cu env =
84 abate 1096 { env with cu = UEnv.add x cu env.cu }
85 abate 723
86 abate 1096 let find_cu x env =
87     try UEnv.find x env.cu
88     with Not_found -> Types.CompUnit.mk x
89 abate 723
90    
91 abate 1190 let enter_schema x uri env =
92     { env with schemas = UEnv.add x uri env.schemas }
93     let find_schema x env =
94     try UEnv.find x env.schemas
95     with Not_found -> raise (Error (Printf.sprintf "%s: no such schema" (U.get_str x)))
96    
97 abate 686 let enter_type id t env =
98     { env with ids = Env.add id (Type t) env.ids }
99     let enter_types l env =
100     { env with ids =
101     List.fold_left (fun accu (id,t) -> Env.add id (Type t) accu) env.ids l }
102     let find_type id env =
103     match Env.find id env.ids with
104     | Type t -> t
105 abate 691 | Val _ -> raise Not_found
106 abate 686
107 abate 723 let find_type_global loc cu id env =
108 abate 1096 let cu = find_cu cu env in
109 abate 713 let env = !from_comp_unit cu in
110     find_type id env
111    
112 abate 686 let enter_value id t env =
113 abate 691 { env with ids = Env.add id (Val t) env.ids }
114 abate 686 let enter_values l env =
115     { env with ids =
116 abate 691 List.fold_left (fun accu (id,t) -> Env.add id (Val t) accu) env.ids l }
117 abate 1238 let enter_values_dummy l env =
118     { env with ids =
119     List.fold_left (fun accu id -> Env.add id (Val Types.empty) accu) env.ids l }
120 abate 686 let find_value id env =
121     match Env.find id env.ids with
122 abate 691 | Val t -> t
123 abate 686 | _ -> raise Not_found
124 abate 713 let find_value_global cu id env =
125     let env = !from_comp_unit cu in
126     find_value id env
127 abate 686
128 abate 692 let value_name_ok id env =
129     try match Env.find id env.ids with
130     | Val t -> true
131     | _ -> false
132     with Not_found -> true
133 abate 686
134 abate 695 let iter_values env f =
135     Env.iter (fun x ->
136     function Val t -> f x t;
137     | _ -> ()) env.ids
138 abate 692
139 abate 713
140 abate 956 let register_types cu env =
141     let prefix = U.concat (Types.CompUnit.value cu) (U.mk ":") in
142     Env.iter (fun x ->
143     function
144     | Type t ->
145     let n = U.concat prefix (Id.value x) in
146     Types.Print.register_global n t
147     | _ -> ()) env.ids
148 abate 713
149 abate 956
150 abate 677 (* Namespaces *)
151 abate 542
152 abate 686 let set_ns_table_for_printer env =
153 abate 713 Ns.InternalPrinter.set_table env.ns
154 abate 686
155 abate 713 let get_ns_table tenv = tenv.ns
156 abate 542
157 abate 686 let enter_ns p ns env =
158 abate 713 { env with ns = Ns.add_prefix p ns env.ns }
159 abate 686
160 abate 677 let protect_error_ns loc f x =
161     try f x
162     with Ns.UnknownPrefix ns ->
163     raise_loc_generic loc
164     ("Undefined namespace prefix " ^ (U.to_string ns))
165 abate 542
166 abate 677 let parse_atom env loc t =
167 abate 713 let (ns,l) = protect_error_ns loc (Ns.map_tag env.ns) t in
168 abate 677 Atoms.V.mk ns l
169    
170     let parse_ns env loc ns =
171 abate 713 protect_error_ns loc (Ns.map_prefix env.ns) ns
172 abate 5
173 abate 677 let parse_label env loc t =
174 abate 713 let (ns,l) = protect_error_ns loc (Ns.map_attr env.ns) t in
175 abate 677 LabelPool.mk (ns,l)
176 abate 5
177 abate 677 let parse_record env loc f r =
178     let r = List.map (fun (l,x) -> (parse_label env loc l, f x)) r in
179     LabelMap.from_list (fun _ _ -> raise_loc_generic loc "Duplicated record field") r
180 abate 140
181 abate 677 let rec const env loc = function
182     | LocatedExpr (loc,e) -> const env loc e
183     | Pair (x,y) -> Types.Pair (const env loc x, const env loc y)
184     | Xml (x,y) -> Types.Xml (const env loc x, const env loc y)
185     | RecordLitt x -> Types.Record (parse_record env loc (const env loc) x)
186     | String (i,j,s,c) -> Types.String (i,j,s,const env loc c)
187     | Atom t -> Types.Atom (parse_atom env loc t)
188     | Integer i -> Types.Integer i
189     | Char c -> Types.Char c
190 abate 722 | Const c -> c
191 abate 677 | _ -> raise_loc_generic loc "This should be a scalar or structured constant"
192    
193     (* I. Transform the abstract syntax of types and patterns into
194     the internal form *)
195    
196 abate 5
197 abate 1190 (* Schema *)
198 abate 9
199 abate 1190 let is_registered_schema env s = UEnv.mem s env.schemas
200    
201     (* uri -> schema binding *)
202 abate 786 let schemas = State.ref "Typer.schemas" (Hashtbl.create 3)
203 abate 508
204 abate 501 let schema_types = State.ref "Typer.schema_types" (Hashtbl.create 51)
205     let schema_elements = State.ref "Typer.schema_elements" (Hashtbl.create 51)
206 abate 508 let schema_attributes = State.ref "Typer.schema_attributes" (Hashtbl.create 51)
207 abate 757 let schema_attribute_groups =
208     State.ref "Typer.schema_attribute_groups" (Hashtbl.create 51)
209     let schema_model_groups =
210     State.ref "Typer.schema_model_groups" (Hashtbl.create 51)
211 abate 501
212 abate 1190
213    
214 abate 786 (* raise Not_found *)
215    
216 abate 1190
217     let get_schema_fwd = ref (fun _ -> assert false)
218    
219     let find_schema_descr_uri kind uri name =
220 abate 786 try
221 abate 1190 ignore (!get_schema_fwd uri);
222     let elt () = Hashtbl.find !schema_elements (uri, name) in
223     let typ () = Hashtbl.find !schema_types (uri, name) in
224     let att () = Hashtbl.find !schema_attributes (uri, name) in
225     let att_group () = Hashtbl.find !schema_attribute_groups (uri, name) in
226     let mod_group () = Hashtbl.find !schema_model_groups (uri, name) in
227     let rec do_try n = function
228     | [] -> raise Not_found
229     | f :: rem -> (try f () with Not_found -> do_try n rem)
230     in
231     match kind with
232     | Some `Element -> do_try "element" [ elt ]
233     | Some `Type -> do_try "type" [ typ ]
234     | Some `Attribute -> do_try "atttribute" [ att ]
235     | Some `Attribute_group -> do_try "attribute group" [ att_group ]
236     | Some `Model_group -> do_try "model group" [ mod_group ]
237     | None ->
238     (* policy for unqualified schema component resolution. This order should
239     * be consistent with Schema_component.get_component *)
240     do_try "component" [ elt; typ; att; att_group; mod_group ]
241     with Not_found ->
242 abate 862 raise (Error (Printf.sprintf "No %s named '%s' found in schema '%s'"
243 abate 1190 (Schema_common.string_of_component_kind kind) (U.get_str name) uri))
244 abate 786
245 abate 1190 let find_schema_descr env kind schema name =
246     let uri = find_schema schema env in
247     find_schema_descr_uri kind uri name
248    
249    
250 abate 278 (* Eliminate Recursion, propagate Sequence Capture Variables *)
251 abate 5
252 abate 278 let rec seq_vars accu = function
253 abate 1328 | Epsilon | Elem _ | Guard _ -> accu
254 abate 278 | Seq (r1,r2) | Alt (r1,r2) -> seq_vars (seq_vars accu r1) r2
255     | Star r | WeakStar r -> seq_vars accu r
256     | SeqCapture (v,r) -> seq_vars (IdSet.add v accu) r
257 abate 71
258 abate 677 (* We use two intermediate representation from AST types/patterns
259     to internal ones:
260    
261     AST -(1)-> derecurs -(2)-> slot -(3)-> internal
262    
263     (1) eliminate recursion, schema,
264     propagate sequence capture variables, keep regexps
265    
266     (2) stratify, detect ill-formed recursion, compile regexps
267    
268     (3) check additional constraints on types / patterns;
269     deep (recursive) hash-consing
270     *)
271    
272 abate 278 type derecurs_slot = {
273     ploc : Location.loc;
274     pid : int;
275     mutable ploop : bool;
276 abate 677 mutable pdescr : derecurs;
277 abate 278 } and derecurs =
278 abate 677 | PDummy
279 abate 278 | PAlias of derecurs_slot
280     | PType of Types.descr
281     | POr of derecurs * derecurs
282     | PAnd of derecurs * derecurs
283     | PDiff of derecurs * derecurs
284     | PTimes of derecurs * derecurs
285     | PXml of derecurs * derecurs
286     | PArrow of derecurs * derecurs
287     | POptional of derecurs
288 abate 1368 | PRecord of bool * (derecurs * derecurs option) label_map
289 abate 278 | PCapture of id
290     | PConstant of id * Types.const
291     | PRegexp of derecurs_regexp * derecurs
292     and derecurs_regexp =
293     | PEpsilon
294     | PElem of derecurs
295 abate 1328 | PGuard of derecurs
296 abate 278 | PSeq of derecurs_regexp * derecurs_regexp
297     | PAlt of derecurs_regexp * derecurs_regexp
298     | PStar of derecurs_regexp
299     | PWeakStar of derecurs_regexp
300 abate 71
301 abate 1328 let pregexp r q = PRegexp (r,q)
302 abate 677
303 abate 1328
304 abate 677 type descr =
305     | IDummy
306     | IType of Types.descr
307     | IOr of descr * descr
308     | IAnd of descr * descr
309     | IDiff of descr * descr
310     | ITimes of slot * slot
311     | IXml of slot * slot
312     | IArrow of slot * slot
313     | IOptional of descr
314 abate 1368 | IRecord of bool * (slot * descr option) label_map
315 abate 677 | ICapture of id
316     | IConstant of id * Types.const
317     and slot = {
318     mutable fv : fv option;
319     mutable hash : int option;
320     mutable rank1: int; mutable rank2: int;
321     mutable gen1 : int; mutable gen2: int;
322     mutable d : descr;
323 abate 529 }
324 abate 677
325 abate 529
326 abate 677 let counter = ref 0
327     let mk_derecurs_slot loc =
328     incr counter;
329     { ploop = false; ploc = loc; pid = !counter; pdescr = PDummy }
330    
331     let mk_slot () =
332     { d=IDummy; fv=None; hash=None; rank1=0; rank2=0; gen1=0; gen2=0 }
333    
334    
335     (* This environment is used in phase (1) to eliminate recursion *)
336     type penv = {
337 abate 691 penv_tenv : t;
338 abate 677 penv_derec : derecurs_slot Env.t;
339     }
340    
341     let penv tenv = { penv_tenv = tenv; penv_derec = Env.empty }
342    
343 abate 278 let rec hash_derecurs = function
344 abate 677 | PDummy -> assert false
345 abate 426 | PAlias s ->
346     s.pid
347     | PType t ->
348 abate 653 1 + 17 * (Types.hash t)
349 abate 426 | POr (p1,p2) ->
350     2 + 17 * (hash_derecurs p1) + 257 * (hash_derecurs p2)
351     | PAnd (p1,p2) ->
352     3 + 17 * (hash_derecurs p1) + 257 * (hash_derecurs p2)
353     | PDiff (p1,p2) ->
354     4 + 17 * (hash_derecurs p1) + 257 * (hash_derecurs p2)
355     | PTimes (p1,p2) ->
356     5 + 17 * (hash_derecurs p1) + 257 * (hash_derecurs p2)
357     | PXml (p1,p2) ->
358     6 + 17 * (hash_derecurs p1) + 257 * (hash_derecurs p2)
359     | PArrow (p1,p2) ->
360     7 + 17 * (hash_derecurs p1) + 257 * (hash_derecurs p2)
361     | POptional p ->
362     8 + 17 * (hash_derecurs p)
363     | PRecord (o,r) ->
364 abate 1368 (if o then 9 else 10) + 17 * (LabelMap.hash hash_derecurs_field r)
365 abate 426 | PCapture x ->
366     11 + 17 * (Id.hash x)
367     | PConstant (x,c) ->
368 abate 691 12 + 17 * (Id.hash x) + 257 * (Types.Const.hash c)
369 abate 426 | PRegexp (p,q) ->
370     13 + 17 * (hash_derecurs_regexp p) + 257 * (hash_derecurs q)
371 abate 1368 and hash_derecurs_field = function
372     | (p, Some e) -> 1 + 17 * hash_derecurs p + 257 * hash_derecurs e
373     | (p, None) -> 2 + 17 * hash_derecurs p
374 abate 278 and hash_derecurs_regexp = function
375 abate 426 | PEpsilon ->
376     1
377     | PElem p ->
378     2 + 17 * (hash_derecurs p)
379     | PSeq (p1,p2) ->
380     3 + 17 * (hash_derecurs_regexp p1) + 257 * (hash_derecurs_regexp p2)
381     | PAlt (p1,p2) ->
382     4 + 17 * (hash_derecurs_regexp p1) + 257 * (hash_derecurs_regexp p2)
383     | PStar p ->
384     5 + 17 * (hash_derecurs_regexp p)
385     | PWeakStar p ->
386     6 + 17 * (hash_derecurs_regexp p)
387 abate 1328 | PGuard p ->
388     7 + 17 * (hash_derecurs p)
389 abate 107
390 abate 278 let rec equal_derecurs p1 p2 = (p1 == p2) || match p1,p2 with
391 abate 426 | PAlias s1, PAlias s2 ->
392     s1 == s2
393     | PType t1, PType t2 ->
394 abate 653 Types.equal t1 t2
395 abate 278 | POr (p1,q1), POr (p2,q2)
396     | PAnd (p1,q1), PAnd (p2,q2)
397     | PDiff (p1,q1), PDiff (p2,q2)
398     | PTimes (p1,q1), PTimes (p2,q2)
399     | PXml (p1,q1), PXml (p2,q2)
400 abate 426 | PArrow (p1,q1), PArrow (p2,q2) ->
401     (equal_derecurs p1 p2) && (equal_derecurs q1 q2)
402     | POptional p1, POptional p2 ->
403     equal_derecurs p1 p2
404     | PRecord (o1,r1), PRecord (o2,r2) ->
405 abate 1368 (o1 == o2) && (LabelMap.equal equal_derecurs_field r1 r2)
406 abate 426 | PCapture x1, PCapture x2 ->
407     Id.equal x1 x2
408     | PConstant (x1,c1), PConstant (x2,c2) ->
409 abate 691 (Id.equal x1 x2) && (Types.Const.equal c1 c2)
410 abate 426 | PRegexp (p1,q1), PRegexp (p2,q2) ->
411     (equal_derecurs_regexp p1 p2) && (equal_derecurs q1 q2)
412 abate 278 | _ -> false
413 abate 1368 and equal_derecurs_field r1 r2 = match (r1,r2) with
414     | (p1,None),(p2,None) -> equal_derecurs p1 p2
415     | (p1, Some e1), (p2, Some e2) -> equal_derecurs p1 p2 && equal_derecurs e1 e2
416     | _ -> false
417 abate 278 and equal_derecurs_regexp r1 r2 = match r1,r2 with
418 abate 426 | PEpsilon, PEpsilon ->
419     true
420     | PElem p1, PElem p2 ->
421     equal_derecurs p1 p2
422 abate 1328 | PGuard p1, PGuard p2 ->
423     equal_derecurs p1 p2
424 abate 278 | PSeq (p1,q1), PSeq (p2,q2)
425 abate 426 | PAlt (p1,q1), PAlt (p2,q2) ->
426     (equal_derecurs_regexp p1 p2) && (equal_derecurs_regexp q1 q2)
427 abate 278 | PStar p1, PStar p2
428 abate 426 | PWeakStar p1, PWeakStar p2 ->
429     equal_derecurs_regexp p1 p2
430 abate 278 | _ -> false
431 abate 5
432 abate 278 module DerecursTable = Hashtbl.Make(
433     struct
434     type t = derecurs
435     let hash = hash_derecurs
436     let equal = equal_derecurs
437     end
438     )
439 abate 5
440 abate 278 module RE = Hashtbl.Make(
441     struct
442     type t = derecurs_regexp * derecurs
443 abate 426 let hash (p,q) =
444     (hash_derecurs_regexp p) + 17 * (hash_derecurs q)
445     let equal (p1,q1) (p2,q2) =
446     (equal_derecurs_regexp p1 p2) && (equal_derecurs q1 q2)
447 abate 278 end
448     )
449 abate 71
450 abate 277 let gen = ref 0
451     let rank = ref 0
452    
453     let rec hash_descr = function
454 abate 677 | IDummy -> assert false
455 abate 653 | IType x -> Types.hash x
456 abate 277 | IOr (d1,d2) -> 1 + 17 * (hash_descr d1) + 257 * (hash_descr d2)
457     | IAnd (d1,d2) -> 2 + 17 * (hash_descr d1) + 257 * (hash_descr d2)
458     | IDiff (d1,d2) -> 3 + 17 * (hash_descr d1) + 257 * (hash_descr d2)
459     | IOptional d -> 4 + 17 * (hash_descr d)
460     | ITimes (s1,s2) -> 5 + 17 * (hash_slot s1) + 257 * (hash_slot s2)
461     | IXml (s1,s2) -> 6 + 17 * (hash_slot s1) + 257 * (hash_slot s2)
462     | IArrow (s1,s2) -> 7 + 17 * (hash_slot s1) + 257 * (hash_slot s2)
463 abate 1368 | IRecord (o,r) -> (if o then 8 else 9) + 17 * (LabelMap.hash hash_descr_field r)
464 abate 277 | ICapture x -> 10 + 17 * (Id.hash x)
465 abate 691 | IConstant (x,y) -> 11 + 17 * (Id.hash x) + 257 * (Types.Const.hash y)
466 abate 1368 and hash_descr_field = function
467     | (d, Some e) -> 1 + 17 * hash_slot d + 257 * hash_descr e
468     | (d, None) -> 2 + 17 * hash_slot d
469 abate 277 and hash_slot s =
470     if s.gen1 = !gen then 13 * s.rank1
471     else (
472     incr rank;
473     s.rank1 <- !rank; s.gen1 <- !gen;
474 abate 677 hash_descr s.d
475 abate 277 )
476    
477     let rec equal_descr d1 d2 =
478     match (d1,d2) with
479 abate 653 | IType x1, IType x2 -> Types.equal x1 x2
480 abate 277 | IOr (x1,y1), IOr (x2,y2)
481     | IAnd (x1,y1), IAnd (x2,y2)
482     | IDiff (x1,y1), IDiff (x2,y2) -> (equal_descr x1 x2) && (equal_descr y1 y2)
483     | IOptional x1, IOptional x2 -> equal_descr x1 x2
484     | ITimes (x1,y1), ITimes (x2,y2)
485     | IXml (x1,y1), IXml (x2,y2)
486     | IArrow (x1,y1), IArrow (x2,y2) -> (equal_slot x1 x2) && (equal_slot y1 y2)
487 abate 426 | IRecord (o1,r1), IRecord (o2,r2) ->
488 abate 1368 (o1 = o2) && (LabelMap.equal equal_descr_field r1 r2)
489 abate 277 | ICapture x1, ICapture x2 -> Id.equal x1 x2
490 abate 426 | IConstant (x1,y1), IConstant (x2,y2) ->
491 abate 691 (Id.equal x1 x2) && (Types.Const.equal y1 y2)
492 abate 277 | _ -> false
493 abate 1368 and equal_descr_field d1 d2 = match (d1,d2) with
494     | (d1,None),(d2,None) -> equal_slot d1 d2
495     | (d1, Some e1), (d2, Some e2) -> equal_slot d1 d2 && equal_descr e1 e2
496     | _ -> false
497 abate 277 and equal_slot s1 s2 =
498     ((s1.gen1 = !gen) && (s2.gen2 = !gen) && (s1.rank1 = s2.rank2))
499     ||
500     ((s1.gen1 <> !gen) && (s2.gen2 <> !gen) && (
501     incr rank;
502     s1.rank1 <- !rank; s1.gen1 <- !gen;
503     s2.rank2 <- !rank; s2.gen2 <- !gen;
504 abate 677 equal_descr s1.d s2.d
505 abate 277 ))
506    
507 abate 677 module SlotTable = Hashtbl.Make(
508     struct
509     type t = slot
510    
511     let hash s =
512     match s.hash with
513     | Some h -> h
514     | None ->
515     incr gen; rank := 0;
516     let h = hash_slot s in
517     s.hash <- Some h;
518     h
519    
520     let equal s1 s2 =
521     (s1 == s2) ||
522     (incr gen; rank := 0;
523     let e = equal_slot s1 s2 in
524     (* if e then Printf.eprintf "Recursive hash-consing: Equal\n"; *)
525     e)
526     end)
527    
528    
529 abate 1328 let pempty = PType Types.empty
530    
531     let por p1 p2 =
532     if p1 == pempty then p2 else
533     if p2 == pempty then p1 else
534     POr (p1,p2)
535    
536     let pand p1 p2 =
537     if (p1 == pempty) || (p2 == pempty) then pempty else PAnd (p1,p2)
538    
539     let rec remove_regexp r q = match r with
540     | PEpsilon ->
541     q
542     | PElem p ->
543     PTimes (p, q)
544     | PGuard p ->
545     pand p q
546     | PSeq (r1,r2) ->
547     remove_regexp r1 (remove_regexp r2 q)
548     | PAlt (r1,r2) ->
549     por (remove_regexp r1 q) (remove_regexp r2 q)
550     | PStar r ->
551     let x = mk_derecurs_slot noloc in
552     let res = POr (PAlias x, q) in
553     x.pdescr <- remove_regexp2 r res pempty;
554     res
555     | PWeakStar r ->
556     let x = mk_derecurs_slot noloc in
557     let res = POr (q, PAlias x) in
558     x.pdescr <- remove_regexp2 r res pempty;
559     res
560    
561     and remove_regexp2 r q_nonempty q_empty =
562     if q_nonempty == q_empty then remove_regexp r q_empty
563     else match r with
564     | PEpsilon ->
565     q_empty
566     | PElem p ->
567     PTimes (p, q_nonempty)
568     | PGuard p ->
569     pand p q_empty
570     | PSeq (r1,r2) ->
571     remove_regexp2 r1
572     (remove_regexp2 r2 q_nonempty q_nonempty)
573     (remove_regexp2 r2 q_nonempty q_empty)
574     | PAlt (r1,r2) ->
575     por
576     (remove_regexp2 r1 q_nonempty q_empty)
577     (remove_regexp2 r2 q_nonempty q_empty)
578     | PStar r ->
579     let x = mk_derecurs_slot noloc in
580     x.pdescr <- remove_regexp2 r (POr (PAlias x, q_nonempty)) pempty;
581     por (PAlias x) q_empty
582     | PWeakStar r ->
583     let x = mk_derecurs_slot noloc in
584     x.pdescr <- remove_regexp2 r (POr (q_nonempty, PAlias x)) pempty;
585     por q_empty (PAlias x)
586    
587 abate 677 let rec derecurs env p = match p.descr with
588 abate 1215 | PatVar v -> derecurs_var env p.loc v
589 abate 786 | SchemaVar (kind, schema_name, component_name) ->
590 abate 1190 PType (find_schema_descr env.penv_tenv kind schema_name component_name)
591 abate 677 | Recurs (p,b) -> derecurs (derecurs_def env b) p
592     | Internal t -> PType t
593     | NsT ns -> PType (Types.atom (Atoms.any_in_ns (parse_ns env.penv_tenv p.loc ns)))
594     | Or (p1,p2) -> POr (derecurs env p1, derecurs env p2)
595     | And (p1,p2) -> PAnd (derecurs env p1, derecurs env p2)
596     | Diff (p1,p2) -> PDiff (derecurs env p1, derecurs env p2)
597     | Prod (p1,p2) -> PTimes (derecurs env p1, derecurs env p2)
598     | XmlT (p1,p2) -> PXml (derecurs env p1, derecurs env p2)
599     | Arrow (p1,p2) -> PArrow (derecurs env p1, derecurs env p2)
600     | Optional p -> POptional (derecurs env p)
601 abate 1368 | Record (o,r) ->
602     let aux = function
603     | (p,Some e) -> (derecurs env p, Some (derecurs env e))
604     | (p,None) -> derecurs env p, None in
605     PRecord (o, parse_record env.penv_tenv p.loc aux r)
606 abate 677 | Constant (x,c) -> PConstant (x,const env.penv_tenv p.loc c)
607     | Cst c -> PType (Types.constant (const env.penv_tenv p.loc c))
608     | Regexp (r,q) ->
609     let constant_nil t v =
610     PAnd (t, PConstant (v, Types.Atom Sequence.nil_atom)) in
611     let vars = seq_vars IdSet.empty r in
612     let q = IdSet.fold constant_nil (derecurs env q) vars in
613     let r = derecurs_regexp (fun p -> p) env r in
614     PRegexp (r, q)
615 abate 1328 (* Note: computing remove_regexp here is slower (because
616     of caching ?) *)
617    
618 abate 677 and derecurs_regexp vars env = function
619     | Epsilon ->
620     PEpsilon
621     | Elem p ->
622     PElem (vars (derecurs env p))
623 abate 1328 | Guard p ->
624     PGuard (vars (derecurs env p))
625 abate 677 | Seq (p1,p2) ->
626     PSeq (derecurs_regexp vars env p1, derecurs_regexp vars env p2)
627     | Alt (p1,p2) ->
628     PAlt (derecurs_regexp vars env p1, derecurs_regexp vars env p2)
629     | Star p ->
630     PStar (derecurs_regexp vars env p)
631     | WeakStar p ->
632     PWeakStar (derecurs_regexp vars env p)
633     | SeqCapture (x,p) ->
634     derecurs_regexp (fun p -> PAnd (vars p, PCapture x)) env p
635    
636 abate 1215 and derecurs_var env loc v =
637     match Ns.split_qname v with
638     | "", v ->
639     let v = ident v in
640     (try PAlias (Env.find v env.penv_derec)
641     with Not_found ->
642     try PType (find_type v env.penv_tenv)
643     with Not_found -> PCapture v)
644     | cu, v ->
645     try
646     let cu = U.mk cu in
647     PType (find_type_global loc cu (ident v) env.penv_tenv)
648     with Not_found ->
649     raise_loc_generic loc
650     ("Unbound external type " ^ cu ^ ":" ^ (U.to_string v))
651 abate 677
652     and derecurs_def env b =
653     let b = List.map (fun (v,p) -> (v,p,mk_derecurs_slot p.loc)) b in
654     let n =
655     List.fold_left (fun env (v,p,s) -> Env.add v s env) env.penv_derec b in
656     let env = { env with penv_derec = n } in
657     List.iter (fun (v,p,s) -> s.pdescr <- derecurs env p) b;
658     env
659    
660 abate 1328
661 abate 277 let rec fv_slot s =
662     match s.fv with
663     | Some x -> x
664     | None ->
665     if s.gen1 = !gen then IdSet.empty
666 abate 677 else (s.gen1 <- !gen; fv_descr s.d)
667 abate 277 and fv_descr = function
668 abate 677 | IDummy -> assert false
669 abate 278 | IType _ -> IdSet.empty
670 abate 277 | IOr (d1,d2)
671     | IAnd (d1,d2)
672     | IDiff (d1,d2) -> IdSet.cup (fv_descr d1) (fv_descr d2)
673     | IOptional d -> fv_descr d
674     | ITimes (s1,s2)
675     | IXml (s1,s2)
676     | IArrow (s1,s2) -> IdSet.cup (fv_slot s1) (fv_slot s2)
677 abate 426 | IRecord (o,r) ->
678 abate 1368 List.fold_left IdSet.cup IdSet.empty (LabelMap.map_to_list fv_field r)
679 abate 277 | ICapture x | IConstant (x,_) -> IdSet.singleton x
680 abate 1368 and fv_field = function
681     | (d,Some e) -> IdSet.cup (fv_slot d) (fv_descr e)
682     | (d,None) -> fv_slot d
683 abate 278
684 abate 1368
685 abate 277 let compute_fv s =
686     match s.fv with
687     | Some x -> ()
688     | None ->
689     incr gen;
690     let x = fv_slot s in
691     s.fv <- Some x
692    
693 abate 656 let check_no_capture loc s =
694     match IdSet.pick s with
695     | Some x ->
696 abate 694 raise_loc_generic loc ("Capture variable not allowed: " ^ (Ident.to_string x))
697 abate 656 | None -> ()
698 abate 277
699 abate 278 let compile_slot_hash = DerecursTable.create 67
700     let compile_hash = DerecursTable.create 67
701    
702 abate 677 let todo_defs = ref []
703     let todo_fv = ref []
704 abate 278
705     let rec compile p =
706     try DerecursTable.find compile_hash p
707 abate 277 with Not_found ->
708 abate 278 let c = real_compile p in
709     DerecursTable.replace compile_hash p c;
710     c
711     and real_compile = function
712 abate 677 | PDummy -> assert false
713 abate 278 | PAlias v ->
714     if v.ploop then
715     raise_loc_generic v.ploc ("Unguarded recursion on type/pattern");
716     v.ploop <- true;
717 abate 677 let r = compile v.pdescr in
718 abate 278 v.ploop <- false;
719     r
720     | PType t -> IType t
721     | POr (t1,t2) -> IOr (compile t1, compile t2)
722     | PAnd (t1,t2) -> IAnd (compile t1, compile t2)
723     | PDiff (t1,t2) -> IDiff (compile t1, compile t2)
724     | PTimes (t1,t2) -> ITimes (compile_slot t1, compile_slot t2)
725     | PXml (t1,t2) -> IXml (compile_slot t1, compile_slot t2)
726     | PArrow (t1,t2) -> IArrow (compile_slot t1, compile_slot t2)
727     | POptional t -> IOptional (compile t)
728 abate 1368 | PRecord (o,r) -> IRecord (o, LabelMap.map compile_field r)
729 abate 278 | PConstant (x,v) -> IConstant (x,v)
730     | PCapture x -> ICapture x
731 abate 1328 | PRegexp (r,q) -> compile (remove_regexp r q)
732    
733 abate 1368 and compile_field = function
734     | (p, Some e) -> (compile_slot p, Some (compile e))
735     | (p, None) -> (compile_slot p, None)
736    
737 abate 278 and compile_slot p =
738     try DerecursTable.find compile_slot_hash p
739     with Not_found ->
740 abate 677 let s = mk_slot () in
741     todo_defs := (s,p) :: !todo_defs;
742     todo_fv := s :: !todo_fv;
743 abate 278 DerecursTable.add compile_slot_hash p s;
744 abate 277 s
745 abate 278
746 abate 277
747 abate 677 let timer_fv = Stats.Timer.create "Typer.fv"
748 abate 277 let rec flush_defs () =
749 abate 677 match !todo_defs with
750     | [] ->
751     Stats.Timer.start timer_fv;
752     List.iter compute_fv !todo_fv;
753 abate 691 todo_fv := [];
754     Stats.Timer.stop timer_fv ()
755 abate 677 | (s,p)::t ->
756     todo_defs := t;
757     s.d <- compile p;
758     flush_defs ()
759 abate 277
760     let typ_nodes = SlotTable.create 67
761     let pat_nodes = SlotTable.create 67
762    
763     let rec typ = function
764     | IType t -> t
765     | IOr (s1,s2) -> Types.cup (typ s1) (typ s2)
766     | IAnd (s1,s2) -> Types.cap (typ s1) (typ s2)
767     | IDiff (s1,s2) -> Types.diff (typ s1) (typ s2)
768     | ITimes (s1,s2) -> Types.times (typ_node s1) (typ_node s2)
769     | IXml (s1,s2) -> Types.xml (typ_node s1) (typ_node s2)
770     | IArrow (s1,s2) -> Types.arrow (typ_node s1) (typ_node s2)
771     | IOptional s -> Types.Record.or_absent (typ s)
772 abate 1368 | IRecord (o,r) -> Types.record' (o, LabelMap.map typ_field r)
773 abate 677 | IDummy | ICapture _ | IConstant (_,_) -> assert false
774 abate 277
775 abate 1368 and typ_field = function
776     | (s, None) -> typ_node s
777     | (s, Some _) ->
778     raise (Patterns.Error "Or-else clauses are not allowed in types")
779    
780 abate 653 and typ_node s : Types.Node.t =
781 abate 277 try SlotTable.find typ_nodes s
782     with Not_found ->
783     let x = Types.make () in
784     SlotTable.add typ_nodes s x;
785 abate 677 Types.define x (typ s.d);
786 abate 277 x
787    
788     let rec pat d : Patterns.descr =
789     if IdSet.is_empty (fv_descr d)
790     then Patterns.constr (typ d)
791     else pat_aux d
792    
793     and pat_aux = function
794 abate 677 | IDummy -> assert false
795 abate 277 | IOr (s1,s2) -> Patterns.cup (pat s1) (pat s2)
796     | IAnd (s1,s2) -> Patterns.cap (pat s1) (pat s2)
797     | IDiff (s1,s2) when IdSet.is_empty (fv_descr s2) ->
798     let s2 = Types.neg (typ s2) in
799     Patterns.cap (pat s1) (Patterns.constr s2)
800     | IDiff _ ->
801 abate 677 raise (Patterns.Error "Differences are not allowed in patterns")
802 abate 277 | ITimes (s1,s2) -> Patterns.times (pat_node s1) (pat_node s2)
803     | IXml (s1,s2) -> Patterns.xml (pat_node s1) (pat_node s2)
804     | IOptional _ ->
805 abate 677 raise (Patterns.Error "Optional fields are not allowed in record patterns")
806 abate 277 | IRecord (o,r) ->
807     let pats = ref [] in
808 abate 1368 let aux l = function
809     | (s,None) ->
810     if IdSet.is_empty (fv_slot s) then typ_node s
811     else
812     ( pats := Patterns.record l (pat_node s) :: !pats;
813     Types.any_node )
814     | (s,Some e) ->
815     if IdSet.is_empty (fv_slot s) then
816     raise (Patterns.Error "Or-else clauses are not allowed in types")
817     else
818     ( pats := Patterns.cup
819     (Patterns.record l (pat_node s))
820     (pat e) :: !pats;
821     Types.Record.any_or_absent_node )
822 abate 277 in
823     let constr = Types.record' (o,LabelMap.mapi aux r) in
824     List.fold_left Patterns.cap (Patterns.constr constr) !pats
825     (* TODO: can avoid constr when o=true, and all fields have fv *)
826     | ICapture x -> Patterns.capture x
827     | IConstant (x,c) -> Patterns.constant x c
828     | IArrow _ ->
829 abate 677 raise (Patterns.Error "Arrows are not allowed in patterns")
830 abate 277 | IType _ -> assert false
831    
832     and pat_node s : Patterns.node =
833     try SlotTable.find pat_nodes s
834     with Not_found ->
835     let x = Patterns.make (fv_slot s) in
836 abate 640 try
837     SlotTable.add pat_nodes s x;
838 abate 677 Patterns.define x (pat s.d);
839 abate 640 x
840     with exn -> SlotTable.remove pat_nodes s; raise exn
841     (* For the toplevel ... *)
842 abate 431
843 abate 677
844 abate 1102 module Ids = Set.Make(Id)
845 abate 686 let type_defs env b =
846 abate 1102 ignore
847     (List.fold_left
848     (fun seen (v,p) ->
849     if Ids.mem v seen then
850     raise_loc_generic p.loc
851     ("Multiple definitions for the type identifer " ^
852     (Ident.to_string v));
853     Ids.add v seen
854     ) Ids.empty b);
855    
856 abate 686 let penv = derecurs_def (penv env) b in
857     let b = List.map (fun (v,p) -> (v,p,compile (derecurs penv p))) b in
858 abate 529 flush_defs ();
859     let b =
860     List.map
861     (fun (v,p,s) ->
862 abate 656 check_no_capture p.loc (fv_descr s);
863 abate 529 let t = typ s in
864     if (p.loc <> noloc) && (Types.is_empty t) then
865     warning p.loc
866 abate 677 ("This definition yields an empty type for " ^ (Ident.to_string v));
867 abate 529 (v,t)) b in
868 abate 677 List.iter (fun (v,t) -> Types.Print.register_global (Id.value v) t) b;
869 abate 686 b
870 abate 278
871 abate 505
872 abate 686 let dump_types ppf env =
873     Env.iter (fun v ->
874     function
875     (Type _) -> Format.fprintf ppf " %a" Ident.print v
876     | _ -> ()) env.ids
877 abate 786 let dump_type ppf env name =
878     try
879 abate 812 (match Env.find (Ident.ident name) env.ids with
880 abate 786 | Type t -> Types.Print.print ppf t
881     | _ -> raise Not_found)
882 abate 812 with Not_found ->
883     raise (Error (Printf.sprintf "Type %s not found" (U.get_str name)))
884 abate 529
885 abate 1190 let dump_schema_type ppf env (k, s, n) =
886     let uri = find_schema s env in
887     let descr = find_schema_descr_uri k uri n in
888 abate 786 Types.Print.print ppf descr
889    
890 abate 686 let dump_ns ppf env =
891 abate 713 Ns.dump_table ppf env.ns
892 abate 552
893 abate 656
894 abate 505 let do_typ loc r =
895     let s = compile_slot r in
896 abate 277 flush_defs ();
897 abate 656 check_no_capture loc (fv_slot s);
898     typ_node s
899 abate 505
900 abate 686 let typ env p =
901     do_typ p.loc (derecurs (penv env) p)
902 abate 277
903 abate 686 let pat env p =
904     let s = compile_slot (derecurs (penv env) p) in
905 abate 277 flush_defs ();
906     try pat_node s
907     with Patterns.Error e -> raise_loc_generic p.loc e
908 abate 522 | Location (loc,_,exn) when loc = noloc -> raise (Location (p.loc, `Full, exn))
909 abate 5
910    
911     (* II. Build skeleton *)
912    
913 abate 542
914 abate 691 type type_fun = Types.t -> bool -> Types.t
915 abate 542
916 abate 225 module Fv = IdSet
917 abate 6
918 abate 427 type branch = Branch of Typed.branch * branch list
919 abate 314
920 abate 427 let cur_branch : branch list ref = ref []
921    
922 abate 316 let exp loc fv e =
923 abate 6 fv,
924     { Typed.exp_loc = loc;
925 abate 5 Typed.exp_typ = Types.empty;
926 abate 316 Typed.exp_descr = e;
927 abate 5 }
928 abate 316
929 abate 1237 let ops = Hashtbl.create 13
930 abate 1238 let register_op op arity f = Hashtbl.add ops op (arity,f)
931     let typ_op op = snd (Hashtbl.find ops op)
932 abate 316
933 abate 1238 let is_op env s =
934     if (Env.mem (ident s) env.ids) then None
935     else
936     try let s = U.get_str s in Some (s, fst (Hashtbl.find ops s))
937     with Not_found -> None
938 abate 1237
939 abate 686 let rec expr env loc = function
940     | LocatedExpr (loc,e) -> expr env loc e
941 abate 316 | Forget (e,t) ->
942 abate 686 let (fv,e) = expr env loc e and t = typ env t in
943 abate 316 exp loc fv (Typed.Forget (e,t))
944 abate 1215 | Var s -> var env loc s
945 abate 316 | Apply (e1,e2) ->
946 abate 1238 let (fv1,e1) = expr env loc e1 and (fv2,e2) = expr env loc e2 in
947     let fv = Fv.cup fv1 fv2 in
948     (match e1.Typed.exp_descr with
949     | Typed.Op (op,arity,args) when arity > 0 ->
950     exp loc fv (Typed.Op (op,arity - 1,args @ [e2]))
951     | _ ->
952     exp loc fv (Typed.Apply (e1,e2)))
953     | Abstraction a -> abstraction env loc a
954 abate 722 | (Integer _ | Char _ | Atom _ | Const _) as c ->
955 abate 686 exp loc Fv.empty (Typed.Cst (const env loc c))
956 abate 316 | Pair (e1,e2) ->
957 abate 686 let (fv1,e1) = expr env loc e1 and (fv2,e2) = expr env loc e2 in
958 abate 316 exp loc (Fv.cup fv1 fv2) (Typed.Pair (e1,e2))
959     | Xml (e1,e2) ->
960 abate 686 let (fv1,e1) = expr env loc e1 and (fv2,e2) = expr env loc e2 in
961 abate 316 exp loc (Fv.cup fv1 fv2) (Typed.Xml (e1,e2))
962     | Dot (e,l) ->
963 abate 686 let (fv,e) = expr env loc e in
964     exp loc fv (Typed.Dot (e,parse_label env loc l))
965 abate 316 | RemoveField (e,l) ->
966 abate 686 let (fv,e) = expr env loc e in
967     exp loc fv (Typed.RemoveField (e,parse_label env loc l))
968 abate 316 | RecordLitt r ->
969     let fv = ref Fv.empty in
970 abate 686 let r = parse_record env loc
971 abate 316 (fun e ->
972 abate 686 let (fv2,e) = expr env loc e
973 abate 316 in fv := Fv.cup !fv fv2; e)
974     r in
975     exp loc !fv (Typed.RecordLitt r)
976 abate 522 | String (i,j,s,e) ->
977 abate 686 let (fv,e) = expr env loc e in
978 abate 522 exp loc fv (Typed.String (i,j,s,e))
979 abate 316 | Match (e,b) ->
980 abate 686 let (fv1,e) = expr env loc e
981     and (fv2,b) = branches env b in
982 abate 316 exp loc (Fv.cup fv1 fv2) (Typed.Match (e, b))
983 abate 421 | Map (e,b) ->
984 abate 686 let (fv1,e) = expr env loc e
985     and (fv2,b) = branches env b in
986 abate 421 exp loc (Fv.cup fv1 fv2) (Typed.Map (e, b))
987     | Transform (e,b) ->
988 abate 686 let (fv1,e) = expr env loc e
989     and (fv2,b) = branches env b in
990 abate 421 exp loc (Fv.cup fv1 fv2) (Typed.Transform (e, b))
991 abate 331 | Xtrans (e,b) ->
992 abate 686 let (fv1,e) = expr env loc e
993     and (fv2,b) = branches env b in
994 abate 331 exp loc (Fv.cup fv1 fv2) (Typed.Xtrans (e, b))
995 abate 786 | Validate (e,kind,schema,elt) ->
996 abate 686 let (fv,e) = expr env loc e in
997 abate 1190 let uri = find_schema schema env in
998     exp loc fv (Typed.Validate (e, kind, uri, elt))
999 abate 316 | Try (e,b) ->
1000 abate 686 let (fv1,e) = expr env loc e
1001     and (fv2,b) = branches env b in
1002 abate 316 exp loc (Fv.cup fv1 fv2) (Typed.Try (e, b))
1003 abate 530 | NamespaceIn (pr,ns,e) ->
1004 abate 686 let env = enter_ns pr ns env in
1005     expr env loc e
1006 abate 623 | Ref (e,t) ->
1007 abate 686 let (fv,e) = expr env loc e and t = typ env t in
1008 abate 623 exp loc fv (Typed.Ref (e,t))
1009 abate 1177 | External (s,args) ->
1010 abate 1178 extern loc env s args
1011 abate 1238
1012     and extern loc env s args =
1013     let args = List.map (typ env) args in
1014     try
1015     let (i,t) = Externals.resolve s args in
1016     exp loc Fv.empty (Typed.External (t,i))
1017     with exn -> raise_loc loc exn
1018    
1019     and var env loc s =
1020     match is_op env s with
1021 abate 1239 | Some (s,arity) ->
1022     let need_ns = s = "print_xml" || s = "print_xml_utf8" in
1023     let e = Typed.Op (s, arity, []) in
1024     let e = if need_ns then Typed.NsTable (env.ns,e) else e in
1025     exp loc Fv.empty e
1026 abate 1238 | None ->
1027     match Ns.split_qname s with
1028     | "", id ->
1029     let s = U.get_str id in
1030     if String.contains s '.' then
1031     extern loc env s []
1032     else
1033     let id = ident id in
1034     (try ignore (find_value id env)
1035     with Not_found -> raise_loc loc (UnboundId (id, Env.mem id env.ids)));
1036     exp loc (Fv.singleton id) (Typed.Var id)
1037     | cu, id ->
1038     let cu = find_cu (U.mk cu) env in
1039     let id = ident id in
1040     let t =
1041     try find_value_global cu id env
1042     with Not_found ->
1043     raise_loc loc (UnboundExtId (cu,id) ) in
1044     exp loc Fv.empty (Typed.ExtVar (cu, id, t))
1045 abate 1178
1046 abate 1238 and abstraction env loc a =
1047     let iface =
1048     List.map
1049     (fun (t1,t2) -> (typ env t1, typ env t2)) a.fun_iface in
1050     let t =
1051     List.fold_left
1052     (fun accu (t1,t2) -> Types.cap accu (Types.arrow t1 t2))
1053     Types.any iface in
1054     let iface =
1055     List.map
1056     (fun (t1,t2) -> (Types.descr t1, Types.descr t2))
1057     iface in
1058     let env' =
1059     match a.fun_name with
1060     | None -> env
1061     | Some f -> enter_values_dummy [ f ] env
1062     in
1063     let (fv0,body) = branches env' a.fun_body in
1064     let fv = match a.fun_name with
1065     | None -> fv0
1066     | Some f -> Fv.remove f fv0 in
1067     let e = Typed.Abstraction
1068     { Typed.fun_name = a.fun_name;
1069     Typed.fun_iface = iface;
1070     Typed.fun_body = body;
1071     Typed.fun_typ = t;
1072     Typed.fun_fv = fv
1073     } in
1074     exp loc fv e
1075    
1076     and branches env b =
1077     let fv = ref Fv.empty in
1078     let accept = ref Types.empty in
1079     let branch (p,e) =
1080     let cur_br = !cur_branch in
1081     cur_branch := [];
1082     let p' = pat env p in
1083     let fvp = Patterns.fv p' in
1084     let env' = enter_values_dummy fvp env in
1085     let (fv2,e) = expr env' noloc e in
1086     let br_loc = merge_loc p.loc e.Typed.exp_loc in
1087     (match Fv.pick (Fv.diff fvp fv2) with
1088     | None -> ()
1089     | Some x ->
1090     let x = U.to_string (Id.value x) in
1091     warning br_loc
1092     ("The capture variable " ^ x ^
1093     " is declared in the pattern but not used in the body of this branch. It might be a misspelled or undeclared type or name (if it isn't, use _ instead)."));
1094     let fv2 = Fv.diff fv2 fvp in
1095     fv := Fv.cup !fv fv2;
1096     accept := Types.cup !accept (Types.descr (Patterns.accept p'));
1097     let br =
1098     {
1099     Typed.br_loc = br_loc;
1100     Typed.br_used = br_loc = noloc;
1101     Typed.br_pat = p';
1102     Typed.br_body = e } in
1103     cur_branch := Branch (br, !cur_branch) :: cur_br;
1104     br in
1105     let b = List.map branch b in
1106     (!fv,
1107     {
1108     Typed.br_typ = Types.empty;
1109     Typed.br_branches = b;
1110     Typed.br_accept = !accept;
1111     Typed.br_compiled = None;
1112     }
1113     )
1114 abate 1215
1115 abate 695 let expr env e = snd (expr env noloc e)
1116 abate 122
1117 abate 686 let let_decl env p e =
1118     { Typed.let_pat = pat env p;
1119 abate 695 Typed.let_body = expr env e;
1120 abate 66 Typed.let_compiled = None }
1121    
1122 abate 529
1123     (* Hide global "typing/parsing" environment *)
1124    
1125    
1126 abate 66 (* III. Type-checks *)
1127    
1128 abate 6 open Typed
1129    
1130 abate 1238 let localize loc f x =
1131     try f x
1132     with
1133     | (Error _ | Constraint (_,_)) as exn -> raise (Location.Location (loc,`Full,exn))
1134     | Warning (s,t) -> warning loc s; t
1135    
1136 abate 421 let require loc t s =
1137     if not (Types.subtype t s) then raise_loc loc (Constraint (t, s))
1138 abate 17
1139 abate 691 let verify loc t s =
1140 abate 421 require loc t s; t
1141 abate 17
1142 abate 1238 let verify_noloc t s =
1143     if not (Types.subtype t s) then raise (Constraint (t, s));
1144     t
1145    
1146 abate 522 let check_str loc ofs t s =
1147     if not (Types.subtype t s) then raise_loc_str loc ofs (Constraint (t, s));
1148     t
1149    
1150     let should_have loc constr s =
1151 abate 421 raise_loc loc (ShouldHave (constr,s))
1152    
1153 abate 522 let should_have_str loc ofs constr s =
1154     raise_loc_str loc ofs (ShouldHave (constr,s))
1155    
1156 abate 1238 let flatten arg constr precise =
1157 abate 421 let constr' = Sequence.star
1158     (Sequence.approx (Types.cap Sequence.any constr)) in
1159     let sconstr' = Sequence.star constr' in
1160     let exact = Types.subtype constr' constr in
1161     if exact then
1162     let t = arg sconstr' precise in
1163     if precise then Sequence.flatten t else constr
1164     else
1165     let t = arg sconstr' true in
1166 abate 1238 verify_noloc (Sequence.flatten t) constr
1167 abate 421
1168 abate 19 let rec type_check env e constr precise =
1169     let d = type_check' e.exp_loc env e.exp_descr constr precise in
1170 abate 421 let d = if precise then d else constr in
1171 abate 6 e.exp_typ <- Types.cup e.exp_typ d;
1172     d
1173    
1174 abate 19 and type_check' loc env e constr precise = match e with
1175 abate 54 | Forget (e,t) ->
1176     let t = Types.descr t in
1177     ignore (type_check env e t false);
1178 abate 691 verify loc t constr
1179 abate 421
1180 abate 19 | Abstraction a ->
1181     let t =
1182     try Types.Arrow.check_strenghten a.fun_typ constr
1183     with Not_found ->
1184 abate 421 should_have loc constr
1185     "but the interface of the abstraction is not compatible"
1186 abate 19 in
1187     let env = match a.fun_name with
1188     | None -> env
1189 abate 686 | Some f -> enter_value f a.fun_typ env in
1190 abate 19 List.iter
1191     (fun (t1,t2) ->
1192 abate 374 let acc = a.fun_body.br_accept in
1193     if not (Types.subtype t1 acc) then
1194     raise_loc loc (NonExhaustive (Types.diff t1 acc));
1195 abate 65 ignore (type_check_branches loc env t1 a.fun_body t2 false)
1196 abate 19 ) a.fun_iface;
1197     t
1198 abate 64
1199 abate 19 | Match (e,b) ->
1200     let t = type_check env e b.br_accept true in
1201 abate 65 type_check_branches loc env t b constr precise
1202 abate 30
1203 abate 64 | Try (e,b) ->
1204     let te = type_check env e constr precise in
1205 abate 65 let tb = type_check_branches loc env Types.any b constr precise in
1206 abate 64 Types.cup te tb
1207    
1208 abate 110 | Pair (e1,e2) ->
1209     type_check_pair loc env e1 e2 constr precise
1210 abate 421
1211 abate 110 | Xml (e1,e2) ->
1212     type_check_pair ~kind:`XML loc env e1 e2 constr precise
1213 abate 159
1214 abate 29 | RecordLitt r ->
1215 abate 421 type_record loc env r constr precise
1216 abate 31
1217 abate 421 | Map (e,b) ->
1218     type_map loc env false e b constr precise
1219    
1220     | Transform (e,b) ->
1221 abate 1238 localize loc (flatten (type_map loc env true e b) constr) precise
1222 abate 421
1223 abate 86 | Apply (e1,e2) ->
1224     let t1 = type_check env e1 Types.Arrow.any true in
1225     let t1 = Types.Arrow.get t1 in
1226     let dom = Types.Arrow.domain t1 in
1227 abate 110 let res =
1228     if Types.Arrow.need_arg t1 then
1229     let t2 = type_check env e2 dom true in
1230     Types.Arrow.apply t1 t2
1231     else
1232     (ignore (type_check env e2 dom false); Types.Arrow.apply_noarg t1)
1233     in
1234 abate 691 verify loc res constr
1235 abate 19
1236 abate 421 | Var s ->
1237 abate 1238 verify loc (find_value s env) constr
1238 abate 713
1239 abate 1238 | ExtVar (cu,s,t) ->
1240 abate 713 verify loc t constr
1241 abate 421 | Cst c ->
1242 abate 691 verify loc (Types.constant c) constr
1243 abate 421
1244 abate 522 | String (i,j,s,e) ->
1245     type_check_string loc env 0 s i j e constr precise
1246    
1247 abate 421 | Dot (e,l) ->
1248     let t = type_check env e Types.Record.any true in
1249     let t =
1250     try (Types.Record.project t l)
1251     with Not_found -> raise_loc loc (WrongLabel(t,l))
1252     in
1253 abate 691 verify loc t constr
1254 abate 421
1255     | RemoveField (e,l) ->
1256     let t = type_check env e Types.Record.any true in
1257     let t = Types.Record.remove_field t l in
1258 abate 691 verify loc t constr
1259 abate 421
1260     | Xtrans (e,b) ->
1261     let t = type_check env e Sequence.any true in
1262     let t =
1263     Sequence.map_tree
1264     (fun t ->
1265     let resid = Types.diff t b.br_accept in
1266     let res = type_check_branches loc env t b Sequence.any true in
1267     (res,resid)
1268     ) t in
1269 abate 691 verify loc t constr
1270 abate 421
1271 abate 1190 | Validate (e, kind, uri, name) ->
1272 abate 501 ignore (type_check env e Types.any false);
1273 abate 1190 let t = find_schema_descr_uri kind uri name in
1274 abate 691 verify loc t constr
1275 abate 421
1276 abate 623 | Ref (e,t) ->
1277     ignore (type_check env e (Types.descr t) false);
1278 abate 691 verify loc (Builtin_defs.ref_type t) constr
1279 abate 623
1280 abate 1156 | External (t,i) ->
1281     verify loc t constr
1282    
1283 abate 1238 | Op (op,_,args) ->
1284 abate 1237 let args = List.map (type_check env) args in
1285 abate 1238 let t = localize loc (typ_op op args constr) precise in
1286 abate 1237 verify loc t constr
1287    
1288 abate 1239 | NsTable (ns,e) ->
1289     type_check' loc env e constr precise
1290    
1291 abate 110 and type_check_pair ?(kind=`Normal) loc env e1 e2 constr precise =
1292 abate 361 let rects = Types.Product.normal ~kind constr in
1293 abate 110 if Types.Product.is_empty rects then
1294     (match kind with
1295 abate 421 | `Normal -> should_have loc constr "but it is a pair"
1296     | `XML -> should_have loc constr "but it is an XML element");
1297 abate 334 let need_s = Types.Product.need_second rects in
1298 abate 355 let t1 = type_check env e1 (Types.Product.pi1 rects) (precise || need_s) in
1299     let c2 = Types.Product.constraint_on_2 rects t1 in
1300     if Types.is_empty c2 then
1301     raise_loc loc (ShouldHave2 (constr,"but the first component has type",t1));
1302     let t2 = type_check env e2 c2 precise in
1303 abate 334
1304 abate 110 if precise then
1305 abate 355 match kind with
1306     | `Normal -> Types.times (Types.cons t1) (Types.cons t2)
1307     | `XML -> Types.xml (Types.cons t1) (Types.cons t2)
1308 abate 110 else
1309     constr
1310    
1311 abate 522 and type_check_string loc env ofs s i j e constr precise =
1312     if U.equal_index i j then type_check env e constr precise
1313     else
1314     let rects = Types.Product.normal constr in
1315     if Types.Product.is_empty rects
1316     then should_have_str loc ofs constr "but it is a string"
1317     else
1318     let need_s = Types.Product.need_second rects in
1319     let (ch,i') = U.next s i in
1320 abate 656 let ch = Chars.V.mk_int ch in
1321 abate 522 let tch = Types.constant (Types.Char ch) in
1322     let t1 = check_str loc ofs tch (Types.Product.pi1 rects) in
1323     let c2 = Types.Product.constraint_on_2 rects t1 in
1324     let t2 = type_check_string loc env (ofs + 1) s i' j e c2 precise in
1325     if precise then Types.times (Types.cons t1) (Types.cons t2)
1326     else constr
1327    
1328 abate 421 and type_record loc env r constr precise =
1329     (* try to get rid of precise = true for values of fields *)
1330     (* also: the use equivalent of need_second to optimize... *)
1331     if not (Types.Record.has_record constr) then
1332     should_have loc constr "but it is a record";
1333     let (rconstr,res) =
1334     List.fold_left
1335     (fun (rconstr,res) (l,e) ->
1336     (* could compute (split l e) once... *)
1337     let pi = Types.Record.project_opt rconstr l in
1338     if Types.is_empty pi then
1339 abate 542 (let l = Label.to_string (LabelPool.value l) in
1340 abate 421 should_have loc constr
1341     (Printf.sprintf "Field %s is not allowed here." l));
1342     let t = type_check env e pi true in
1343     let rconstr = Types.Record.condition rconstr l t in
1344     let res = (l,Types.cons t) :: res in
1345     (rconstr,res)
1346     ) (constr, []) (LabelMap.get r)
1347     in
1348     if not (Types.Record.has_empty_record rconstr) then
1349     should_have loc constr "More fields should be present";
1350     let t =
1351     Types.record' (false, LabelMap.from_list (fun _ _ -> assert false) res)
1352     in
1353 abate 691 verify loc t constr
1354 abate 110
1355 abate 19
1356 abate 65 and type_check_branches loc env targ brs constr precise =
1357 abate 374 if Types.is_empty targ then Types.empty
1358 abate 9 else (
1359     brs.br_typ <- Types.cup brs.br_typ targ;
1360 abate 65 branches_aux loc env targ
1361 abate 19 (if precise then Types.empty else constr)
1362     constr precise brs.br_branches
1363 abate 9 )
1364 abate 6
1365 abate 65 and branches_aux loc env targ tres constr precise = function
1366 abate 374 | [] -> tres
1367 abate 6 | b :: rem ->
1368     let p = b.br_pat in
1369     let acc = Types.descr (Patterns.accept p) in
1370    
1371     let targ' = Types.cap targ acc in
1372     if Types.is_empty targ'
1373 abate 65 then branches_aux loc env targ tres constr precise rem
1374 abate 6 else
1375     ( b.br_used <- true;
1376     let res = Patterns.filter targ' p in
1377 abate 686 let res = List.map (fun (x,t) -> (x,Types.descr t)) res in
1378     let env' = enter_values res env in
1379 abate 19 let t = type_check env' b.br_body constr precise in
1380     let tres = if precise then Types.cup t tres else tres in
1381 abate 9 let targ'' = Types.diff targ acc in
1382     if (Types.non_empty targ'') then
1383 abate 65 branches_aux loc env targ'' tres constr precise rem
1384 abate 9 else
1385     tres
1386 abate 6 )
1387 abate 16
1388 abate 421 and type_map loc env def e b constr precise =
1389     let acc = if def then Sequence.any else Sequence.star b.br_accept in
1390     let t = type_check env e acc true in
1391    
1392     let constr' = Sequence.approx (Types.cap Sequence.any constr) in
1393     let exact = Types.subtype (Sequence.star constr') constr in
1394     (* Note:
1395     - could be more precise by integrating the decomposition
1396     of constr inside Sequence.map.
1397     *)
1398     let res =
1399     Sequence.map
1400     (fun t ->
1401     let res =
1402     type_check_branches loc env t b constr' (precise || (not exact)) in
1403     if def && not (Types.subtype t b.br_accept)
1404 abate 969 then (require loc Sequence.nil_type constr'; Types.cup res Sequence.nil_type)
1405 abate 421 else res)
1406     t in
1407 abate 691 if exact then res else verify loc res constr
1408 abate 421
1409 abate 66 and type_let_decl env l =
1410     let acc = Types.descr (Patterns.accept l.let_pat) in
1411     let t = type_check env l.let_body acc true in
1412     let res = Patterns.filter t l.let_pat in
1413     List.map (fun (x,t) -> (x, Types.descr t)) res
1414    
1415     and type_rec_funs env l =
1416 abate 698 let typs =
1417 abate 66 List.fold_left
1418 abate 431 (fun accu -> function
1419 abate 656 | { exp_descr=Abstraction { fun_typ = t; fun_name = Some f };
1420     exp_loc=loc } ->
1421 abate 692 if not (value_name_ok f env) then
1422 abate 656 error loc "This function name clashes with a type name";
1423 abate 698 (f,t)::accu
1424 abate 431 | _ -> assert false
1425     ) [] l
1426 abate 66 in
1427 abate 698 let env = enter_values typs env in
1428     List.iter (fun e -> ignore (type_check env e Types.any false)) l;
1429     typs
1430 abate 66
1431 abate 427 let rec unused_branches b =
1432 abate 314 List.iter
1433 abate 427 (fun (Branch (br,s)) ->
1434     if not br.br_used
1435     then warning br.br_loc "This branch is not used"
1436     else unused_branches s
1437     )
1438     b
1439 abate 314
1440 abate 427 let report_unused_branches () =
1441     unused_branches !cur_branch;
1442     cur_branch := []
1443 abate 637
1444     let clear_unused_branches () =
1445     cur_branch := []
1446 abate 427
1447 abate 698
1448    
1449     (* API *)
1450    
1451     let type_expr env e =
1452     clear_unused_branches ();
1453     let e = expr env e in
1454     let t = type_check env e Types.any true in
1455     report_unused_branches ();
1456     (e,t)
1457    
1458     let type_let_decl env p e =
1459     clear_unused_branches ();
1460     let decl = let_decl env p e in
1461     let typs = type_let_decl env decl in
1462     report_unused_branches ();
1463     let env = enter_values typs env in
1464     (env,decl,typs)
1465    
1466     let type_let_funs env funs =
1467     clear_unused_branches ();
1468 abate 1238 let rec id = function
1469     | Ast.LocatedExpr (_,e) -> id e
1470     | Ast.Abstraction a -> a.Ast.fun_name
1471     | _ -> assert false
1472     in
1473     let ids =
1474     List.fold_left (fun accu f -> match id f with Some x -> x::accu | None -> accu)
1475     [] funs in
1476     let env' = enter_values_dummy ids env in
1477     let funs = List.map (expr env') funs in
1478 abate 698 let typs = type_rec_funs env funs in
1479     report_unused_branches ();
1480     let env = enter_values typs env in
1481     (env,funs,typs)
1482    
1483    
1484 abate 501 (* Schema stuff from now on ... *)
1485    
1486     (** convertion from XML Schema types (including global elements and
1487     attributes) to CDuce Types.descr *)
1488     module Schema_converter =
1489     struct
1490    
1491 abate 508 open Printf
1492     open Schema_types
1493 abate 501
1494     (* auxiliary functions *)
1495    
1496 abate 757 let nil_type = PType Sequence.nil_type
1497 abate 501
1498 abate 757 let mk_len_regexp ?min ?max base =
1499     let rec repeat_regexp re = function
1500     | z when Intervals.V.is_zero z -> PEpsilon
1501     | n when Intervals.V.gt n Intervals.V.zero ->
1502     PSeq (re, repeat_regexp re (Intervals.V.pred n))
1503     | _ -> assert false
1504     in
1505     let min = match min with Some min -> min | _ -> Intervals.V.one in
1506     let min_regexp = repeat_regexp base min in
1507     match max with
1508     | Some max ->
1509 abate 1292 (* assert (max >= min); Need to use Bigint comparison ! -- AF *)
1510     let rec aux acc = function
1511 abate 757 | z when Intervals.V.is_zero z -> acc
1512     | n ->
1513     aux (PAlt (PEpsilon, (PSeq (base, acc)))) (Intervals.V.pred n)
1514     in
1515     PSeq (min_regexp, aux PEpsilon (Intervals.V.sub max min))
1516     | None -> PSeq (min_regexp, PStar base)
1517    
1518     (* given a base derecurs create a derecurs value representing a sequence
1519     * type according to length constraints members of facets *)
1520     let mk_seq_derecurs ~base facets =
1521     match facets with
1522     | { length = Some (v, _) } ->
1523 abate 1328 pregexp (mk_len_regexp ~min:v ~max:v base) nil_type
1524 abate 757 | { minLength = Some (v, _); maxLength = None } ->
1525 abate 1328 pregexp (mk_len_regexp ~min:v base) nil_type
1526 abate 757 | { minLength = None; maxLength = Some (v, _) } ->
1527 abate 1328 pregexp (mk_len_regexp ~max:v base) nil_type
1528     | _ -> pregexp base nil_type
1529 abate 757
1530 abate 812 let mix_regexp =
1531     let pcdata = PStar (PElem (PType Builtin_defs.string)) in
1532     let rec aux = function
1533     | PEpsilon -> PEpsilon
1534     | PElem re -> PElem re
1535 abate 1328 | PGuard re -> PGuard re
1536 abate 812 | PSeq (re1, re2) -> PSeq (aux re1, PSeq (pcdata, aux re2))
1537     | PAlt (re1, re2) -> PAlt (aux re1, aux re2)
1538     | PStar re -> PStar (aux re)
1539     | PWeakStar re -> PWeakStar (aux re)
1540     in
1541     let rec simplify = function
1542     | PSeq (x1, PSeq (x2, y)) when x1 = pcdata && x2 = pcdata ->
1543     simplify (PSeq (x2, y))
1544     | re -> re
1545     in
1546     fun regexp -> simplify (PSeq (pcdata, aux regexp))
1547    
1548 abate 501 (* conversion functions *)
1549    
1550 abate 803 let rec cd_type_of_simple_type ~schema = function
1551 abate 757 | Primitive name | Derived (Some name, _, _, _)
1552     when Schema_builtin.is_builtin name ->
1553     PType (Schema_builtin.cd_type_of_builtin name)
1554     | Primitive _ -> assert false (* all primitives are built-in *)
1555     | Derived (_, _, { enumeration = Some values }, _) -> (* enumeration *)
1556     PType (Types.choice_of_list
1557     (List.map (fun c -> Types.constant (Value.inv_const c))
1558     (Value.ValueSet.elements values)))
1559     | Derived (_, _, ({ maxInclusive = Some _ } as facets), _)(* boundaries *)
1560     | Derived (_, _, ({ maxExclusive = Some _ } as facets), _)
1561     | Derived (_, _, ({ minInclusive = Some _ } as facets), _)
1562     | Derived (_, _, ({ minExclusive = Some _ } as facets),