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

Contents of /typing/typer.ml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 686 - (hide annotations)
Tue Jul 10 17:54:32 2007 UTC (5 years, 10 months ago) by abate
File size: 41994 byte(s)
[r2003-09-25 22:48:47 by cvscast] Cleaning

Original author: cvscast
Date: 2003-09-25 22:48:47+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 320 let warning loc msg =
12     Format.fprintf !Location.warning_ppf "Warning %a:@\n%a%s@\n"
13 abate 522 Location.print_loc (loc,`Full)
14     Location.html_hilight (loc,`Full)
15 abate 320 msg
16    
17 abate 686 type item =
18     | Type of Types.t
19     | Value of Types.t
20    
21     type env = {
22     ids : item Env.t;
23 abate 677 tenv_nspref: Ns.table;
24     }
25 abate 542
26 abate 686 let empty_env = {
27     ids = Env.empty;
28     tenv_nspref = Ns.empty_table;
29     }
30    
31     let enter_type id t env =
32     { env with ids = Env.add id (Type t) env.ids }
33     let enter_types l env =
34     { env with ids =
35     List.fold_left (fun accu (id,t) -> Env.add id (Type t) accu) env.ids l }
36     let find_type id env =
37     match Env.find id env.ids with
38     | Type t -> t
39     | Value _ -> raise Not_found
40    
41     let enter_value id t env =
42     { env with ids = Env.add id (Value t) env.ids }
43     let enter_values l env =
44     { env with ids =
45     List.fold_left (fun accu (id,t) -> Env.add id (Value t) accu) env.ids l }
46     let find_value id env =
47     match Env.find id env.ids with
48     | Value t -> t
49     | _ -> raise Not_found
50    
51    
52 abate 677 (* Namespaces *)
53 abate 542
54 abate 686 let set_ns_table_for_printer env =
55     Ns.InternalPrinter.set_table env.tenv_nspref
56    
57 abate 677 let get_ns_table tenv = tenv.tenv_nspref
58 abate 542
59 abate 686 let enter_ns p ns env =
60     { env with tenv_nspref = Ns.add_prefix p ns env.tenv_nspref }
61    
62 abate 677 let protect_error_ns loc f x =
63     try f x
64     with Ns.UnknownPrefix ns ->
65     raise_loc_generic loc
66     ("Undefined namespace prefix " ^ (U.to_string ns))
67 abate 542
68 abate 677 let parse_atom env loc t =
69     let (ns,l) = protect_error_ns loc (Ns.map_tag env.tenv_nspref) t in
70     Atoms.V.mk ns l
71    
72     let parse_ns env loc ns =
73     protect_error_ns loc (Ns.map_prefix env.tenv_nspref) ns
74 abate 5
75 abate 677 let parse_label env loc t =
76     let (ns,l) = protect_error_ns loc (Ns.map_attr env.tenv_nspref) t in
77     LabelPool.mk (ns,l)
78 abate 5
79 abate 677 let parse_record env loc f r =
80     let r = List.map (fun (l,x) -> (parse_label env loc l, f x)) r in
81     LabelMap.from_list (fun _ _ -> raise_loc_generic loc "Duplicated record field") r
82 abate 140
83 abate 677 let rec const env loc = function
84     | LocatedExpr (loc,e) -> const env loc e
85     | Pair (x,y) -> Types.Pair (const env loc x, const env loc y)
86     | Xml (x,y) -> Types.Xml (const env loc x, const env loc y)
87     | RecordLitt x -> Types.Record (parse_record env loc (const env loc) x)
88     | String (i,j,s,c) -> Types.String (i,j,s,const env loc c)
89     | Atom t -> Types.Atom (parse_atom env loc t)
90     | Integer i -> Types.Integer i
91     | Char c -> Types.Char c
92     | _ -> raise_loc_generic loc "This should be a scalar or structured constant"
93    
94     (* I. Transform the abstract syntax of types and patterns into
95     the internal form *)
96    
97 abate 9 exception NonExhaustive of Types.descr
98 abate 421 exception Constraint of Types.descr * Types.descr
99 abate 19 exception ShouldHave of Types.descr * string
100 abate 355 exception ShouldHave2 of Types.descr * string * Types.descr
101 abate 233 exception WrongLabel of Types.descr * label
102 abate 656 exception UnboundId of id * bool
103 abate 421 exception Error of string
104 abate 5
105 abate 522 let raise_loc loc exn = raise (Location (loc,`Full,exn))
106     let raise_loc_str loc ofs exn = raise (Location (loc,`Char ofs,exn))
107 abate 421 let error loc msg = raise_loc loc (Error msg)
108 abate 9
109 abate 501 (* Schema datastructures *)
110 abate 5
111 abate 501 module StringSet = Set.Make (String)
112    
113 abate 508 (* just to remember imported schemas *)
114     let schemas = State.ref "Typer.schemas" StringSet.empty
115    
116 abate 501 let schema_types = State.ref "Typer.schema_types" (Hashtbl.create 51)
117     let schema_elements = State.ref "Typer.schema_elements" (Hashtbl.create 51)
118 abate 508 let schema_attributes = State.ref "Typer.schema_attributes" (Hashtbl.create 51)
119 abate 501
120 abate 278 (* Eliminate Recursion, propagate Sequence Capture Variables *)
121 abate 5
122 abate 278 let rec seq_vars accu = function
123     | Epsilon | Elem _ -> accu
124     | Seq (r1,r2) | Alt (r1,r2) -> seq_vars (seq_vars accu r1) r2
125     | Star r | WeakStar r -> seq_vars accu r
126     | SeqCapture (v,r) -> seq_vars (IdSet.add v accu) r
127 abate 71
128 abate 677 (* We use two intermediate representation from AST types/patterns
129     to internal ones:
130    
131     AST -(1)-> derecurs -(2)-> slot -(3)-> internal
132    
133     (1) eliminate recursion, schema,
134     propagate sequence capture variables, keep regexps
135    
136     (2) stratify, detect ill-formed recursion, compile regexps
137    
138     (3) check additional constraints on types / patterns;
139     deep (recursive) hash-consing
140     *)
141    
142 abate 278 type derecurs_slot = {
143     ploc : Location.loc;
144     pid : int;
145     mutable ploop : bool;
146 abate 677 mutable pdescr : derecurs;
147 abate 278 } and derecurs =
148 abate 677 | PDummy
149 abate 278 | PAlias of derecurs_slot
150     | PType of Types.descr
151     | POr of derecurs * derecurs
152     | PAnd of derecurs * derecurs
153     | PDiff of derecurs * derecurs
154     | PTimes of derecurs * derecurs
155     | PXml of derecurs * derecurs
156     | PArrow of derecurs * derecurs
157     | POptional of derecurs
158     | PRecord of bool * derecurs label_map
159     | PCapture of id
160     | PConstant of id * Types.const
161     | PRegexp of derecurs_regexp * derecurs
162     and derecurs_regexp =
163     | PEpsilon
164     | PElem of derecurs
165     | PSeq of derecurs_regexp * derecurs_regexp
166     | PAlt of derecurs_regexp * derecurs_regexp
167     | PStar of derecurs_regexp
168     | PWeakStar of derecurs_regexp
169 abate 71
170 abate 677
171     type descr =
172     | IDummy
173     | IType of Types.descr
174     | IOr of descr * descr
175     | IAnd of descr * descr
176     | IDiff of descr * descr
177     | ITimes of slot * slot
178     | IXml of slot * slot
179     | IArrow of slot * slot
180     | IOptional of descr
181     | IRecord of bool * slot label_map
182     | ICapture of id
183     | IConstant of id * Types.const
184     and slot = {
185     mutable fv : fv option;
186     mutable hash : int option;
187     mutable rank1: int; mutable rank2: int;
188     mutable gen1 : int; mutable gen2: int;
189     mutable d : descr;
190 abate 529 }
191 abate 677
192 abate 529
193 abate 677 let counter = ref 0
194     let mk_derecurs_slot loc =
195     incr counter;
196     { ploop = false; ploc = loc; pid = !counter; pdescr = PDummy }
197    
198     let mk_slot () =
199     { d=IDummy; fv=None; hash=None; rank1=0; rank2=0; gen1=0; gen2=0 }
200    
201    
202     (* This environment is used in phase (1) to eliminate recursion *)
203     type penv = {
204 abate 686 penv_tenv : env;
205 abate 677 penv_derec : derecurs_slot Env.t;
206     }
207    
208     let penv tenv = { penv_tenv = tenv; penv_derec = Env.empty }
209    
210 abate 278 let rec hash_derecurs = function
211 abate 677 | PDummy -> assert false
212 abate 426 | PAlias s ->
213     s.pid
214     | PType t ->
215 abate 653 1 + 17 * (Types.hash t)
216 abate 426 | POr (p1,p2) ->
217     2 + 17 * (hash_derecurs p1) + 257 * (hash_derecurs p2)
218     | PAnd (p1,p2) ->
219     3 + 17 * (hash_derecurs p1) + 257 * (hash_derecurs p2)
220     | PDiff (p1,p2) ->
221     4 + 17 * (hash_derecurs p1) + 257 * (hash_derecurs p2)
222     | PTimes (p1,p2) ->
223     5 + 17 * (hash_derecurs p1) + 257 * (hash_derecurs p2)
224     | PXml (p1,p2) ->
225     6 + 17 * (hash_derecurs p1) + 257 * (hash_derecurs p2)
226     | PArrow (p1,p2) ->
227     7 + 17 * (hash_derecurs p1) + 257 * (hash_derecurs p2)
228     | POptional p ->
229     8 + 17 * (hash_derecurs p)
230     | PRecord (o,r) ->
231     (if o then 9 else 10) + 17 * (LabelMap.hash hash_derecurs r)
232     | PCapture x ->
233     11 + 17 * (Id.hash x)
234     | PConstant (x,c) ->
235     12 + 17 * (Id.hash x) + 257 * (Types.hash_const c)
236     | PRegexp (p,q) ->
237     13 + 17 * (hash_derecurs_regexp p) + 257 * (hash_derecurs q)
238 abate 278 and hash_derecurs_regexp = function
239 abate 426 | PEpsilon ->
240     1
241     | PElem p ->
242     2 + 17 * (hash_derecurs p)
243     | PSeq (p1,p2) ->
244     3 + 17 * (hash_derecurs_regexp p1) + 257 * (hash_derecurs_regexp p2)
245     | PAlt (p1,p2) ->
246     4 + 17 * (hash_derecurs_regexp p1) + 257 * (hash_derecurs_regexp p2)
247     | PStar p ->
248     5 + 17 * (hash_derecurs_regexp p)
249     | PWeakStar p ->
250     6 + 17 * (hash_derecurs_regexp p)
251 abate 107
252 abate 278 let rec equal_derecurs p1 p2 = (p1 == p2) || match p1,p2 with
253 abate 426 | PAlias s1, PAlias s2 ->
254     s1 == s2
255     | PType t1, PType t2 ->
256 abate 653 Types.equal t1 t2
257 abate 278 | POr (p1,q1), POr (p2,q2)
258     | PAnd (p1,q1), PAnd (p2,q2)
259     | PDiff (p1,q1), PDiff (p2,q2)
260     | PTimes (p1,q1), PTimes (p2,q2)
261     | PXml (p1,q1), PXml (p2,q2)
262 abate 426 | PArrow (p1,q1), PArrow (p2,q2) ->
263     (equal_derecurs p1 p2) && (equal_derecurs q1 q2)
264     | POptional p1, POptional p2 ->
265     equal_derecurs p1 p2
266     | PRecord (o1,r1), PRecord (o2,r2) ->
267     (o1 == o2) && (LabelMap.equal equal_derecurs r1 r2)
268     | PCapture x1, PCapture x2 ->
269     Id.equal x1 x2
270     | PConstant (x1,c1), PConstant (x2,c2) ->
271     (Id.equal x1 x2) && (Types.equal_const c1 c2)
272     | PRegexp (p1,q1), PRegexp (p2,q2) ->
273     (equal_derecurs_regexp p1 p2) && (equal_derecurs q1 q2)
274 abate 278 | _ -> false
275     and equal_derecurs_regexp r1 r2 = match r1,r2 with
276 abate 426 | PEpsilon, PEpsilon ->
277     true
278     | PElem p1, PElem p2 ->
279     equal_derecurs p1 p2
280 abate 278 | PSeq (p1,q1), PSeq (p2,q2)
281 abate 426 | PAlt (p1,q1), PAlt (p2,q2) ->
282     (equal_derecurs_regexp p1 p2) && (equal_derecurs_regexp q1 q2)
283 abate 278 | PStar p1, PStar p2
284 abate 426 | PWeakStar p1, PWeakStar p2 ->
285     equal_derecurs_regexp p1 p2
286 abate 278 | _ -> false
287 abate 5
288 abate 278 module DerecursTable = Hashtbl.Make(
289     struct
290     type t = derecurs
291     let hash = hash_derecurs
292     let equal = equal_derecurs
293     end
294     )
295 abate 5
296 abate 278 module RE = Hashtbl.Make(
297     struct
298     type t = derecurs_regexp * derecurs
299 abate 426 let hash (p,q) =
300     (hash_derecurs_regexp p) + 17 * (hash_derecurs q)
301     let equal (p1,q1) (p2,q2) =
302     (equal_derecurs_regexp p1 p2) && (equal_derecurs q1 q2)
303 abate 278 end
304     )
305 abate 71
306 abate 277 let gen = ref 0
307     let rank = ref 0
308    
309     let rec hash_descr = function
310 abate 677 | IDummy -> assert false
311 abate 653 | IType x -> Types.hash x
312 abate 277 | IOr (d1,d2) -> 1 + 17 * (hash_descr d1) + 257 * (hash_descr d2)
313     | IAnd (d1,d2) -> 2 + 17 * (hash_descr d1) + 257 * (hash_descr d2)
314     | IDiff (d1,d2) -> 3 + 17 * (hash_descr d1) + 257 * (hash_descr d2)
315     | IOptional d -> 4 + 17 * (hash_descr d)
316     | ITimes (s1,s2) -> 5 + 17 * (hash_slot s1) + 257 * (hash_slot s2)
317     | IXml (s1,s2) -> 6 + 17 * (hash_slot s1) + 257 * (hash_slot s2)
318     | IArrow (s1,s2) -> 7 + 17 * (hash_slot s1) + 257 * (hash_slot s2)
319     | IRecord (o,r) -> (if o then 8 else 9) + 17 * (LabelMap.hash hash_slot r)
320     | ICapture x -> 10 + 17 * (Id.hash x)
321     | IConstant (x,y) -> 11 + 17 * (Id.hash x) + 257 * (Types.hash_const y)
322     and hash_slot s =
323     if s.gen1 = !gen then 13 * s.rank1
324     else (
325     incr rank;
326     s.rank1 <- !rank; s.gen1 <- !gen;
327 abate 677 hash_descr s.d
328 abate 277 )
329    
330     let rec equal_descr d1 d2 =
331     match (d1,d2) with
332 abate 653 | IType x1, IType x2 -> Types.equal x1 x2
333 abate 277 | IOr (x1,y1), IOr (x2,y2)
334     | IAnd (x1,y1), IAnd (x2,y2)
335     | IDiff (x1,y1), IDiff (x2,y2) -> (equal_descr x1 x2) && (equal_descr y1 y2)
336     | IOptional x1, IOptional x2 -> equal_descr x1 x2
337     | ITimes (x1,y1), ITimes (x2,y2)
338     | IXml (x1,y1), IXml (x2,y2)
339     | IArrow (x1,y1), IArrow (x2,y2) -> (equal_slot x1 x2) && (equal_slot y1 y2)
340 abate 426 | IRecord (o1,r1), IRecord (o2,r2) ->
341     (o1 = o2) && (LabelMap.equal equal_slot r1 r2)
342 abate 277 | ICapture x1, ICapture x2 -> Id.equal x1 x2
343 abate 426 | IConstant (x1,y1), IConstant (x2,y2) ->
344     (Id.equal x1 x2) && (Types.equal_const y1 y2)
345 abate 277 | _ -> false
346     and equal_slot s1 s2 =
347     ((s1.gen1 = !gen) && (s2.gen2 = !gen) && (s1.rank1 = s2.rank2))
348     ||
349     ((s1.gen1 <> !gen) && (s2.gen2 <> !gen) && (
350     incr rank;
351     s1.rank1 <- !rank; s1.gen1 <- !gen;
352     s2.rank2 <- !rank; s2.gen2 <- !gen;
353 abate 677 equal_descr s1.d s2.d
354 abate 277 ))
355    
356 abate 677 module SlotTable = Hashtbl.Make(
357     struct
358     type t = slot
359    
360     let hash s =
361     match s.hash with
362     | Some h -> h
363     | None ->
364     incr gen; rank := 0;
365     let h = hash_slot s in
366     s.hash <- Some h;
367     h
368    
369     let equal s1 s2 =
370     (s1 == s2) ||
371     (incr gen; rank := 0;
372     let e = equal_slot s1 s2 in
373     (* if e then Printf.eprintf "Recursive hash-consing: Equal\n"; *)
374     e)
375     end)
376    
377    
378     let rec derecurs env p = match p.descr with
379     | PatVar v ->
380     (try PAlias (Env.find v env.penv_derec)
381     with Not_found ->
382 abate 686 try PType (find_type v env.penv_tenv)
383 abate 677 with Not_found -> PCapture v)
384     | SchemaVar (kind, schema, item) ->
385     PType (derecurs_schema env kind schema item)
386     | Recurs (p,b) -> derecurs (derecurs_def env b) p
387     | Internal t -> PType t
388     | NsT ns -> PType (Types.atom (Atoms.any_in_ns (parse_ns env.penv_tenv p.loc ns)))
389     | Or (p1,p2) -> POr (derecurs env p1, derecurs env p2)
390     | And (p1,p2) -> PAnd (derecurs env p1, derecurs env p2)
391     | Diff (p1,p2) -> PDiff (derecurs env p1, derecurs env p2)
392     | Prod (p1,p2) -> PTimes (derecurs env p1, derecurs env p2)
393     | XmlT (p1,p2) -> PXml (derecurs env p1, derecurs env p2)
394     | Arrow (p1,p2) -> PArrow (derecurs env p1, derecurs env p2)
395     | Optional p -> POptional (derecurs env p)
396     | Record (o,r) -> PRecord (o, parse_record env.penv_tenv p.loc (derecurs env) r)
397     | Constant (x,c) -> PConstant (x,const env.penv_tenv p.loc c)
398     | Cst c -> PType (Types.constant (const env.penv_tenv p.loc c))
399     | Regexp (r,q) ->
400     let constant_nil t v =
401     PAnd (t, PConstant (v, Types.Atom Sequence.nil_atom)) in
402     let vars = seq_vars IdSet.empty r in
403     let q = IdSet.fold constant_nil (derecurs env q) vars in
404     let r = derecurs_regexp (fun p -> p) env r in
405     PRegexp (r, q)
406     and derecurs_regexp vars env = function
407     | Epsilon ->
408     PEpsilon
409     | Elem p ->
410     PElem (vars (derecurs env p))
411     | Seq (p1,p2) ->
412     PSeq (derecurs_regexp vars env p1, derecurs_regexp vars env p2)
413     | Alt (p1,p2) ->
414     PAlt (derecurs_regexp vars env p1, derecurs_regexp vars env p2)
415     | Star p ->
416     PStar (derecurs_regexp vars env p)
417     | WeakStar p ->
418     PWeakStar (derecurs_regexp vars env p)
419     | SeqCapture (x,p) ->
420     derecurs_regexp (fun p -> PAnd (vars p, PCapture x)) env p
421    
422    
423     and derecurs_def env b =
424     let b = List.map (fun (v,p) -> (v,p,mk_derecurs_slot p.loc)) b in
425     let n =
426     List.fold_left (fun env (v,p,s) -> Env.add v s env) env.penv_derec b in
427     let env = { env with penv_derec = n } in
428     List.iter (fun (v,p,s) -> s.pdescr <- derecurs env p) b;
429     env
430    
431     and derecurs_schema env kind schema item =
432     let elt () = fst (Hashtbl.find !schema_elements (schema, item)) in
433     let typ () = Hashtbl.find !schema_types (schema, item) in
434     let att () = Hashtbl.find !schema_attributes (schema, item) in
435     let rec do_try n = function
436     | [] ->
437     let s = Printf.sprintf
438     "No %s named '%s' found in schema '%s'" n item schema in
439     failwith s
440     | f :: rem -> (try f () with Not_found -> do_try n rem) in
441     match kind with
442     | `Element -> do_try "element" [ elt ]
443     | `Type -> do_try "type" [ typ ]
444     | `Attribute -> do_try "atttribute" [ att ]
445     | `Any -> do_try "item" [ elt; typ; att ]
446    
447    
448 abate 277 let rec fv_slot s =
449     match s.fv with
450     | Some x -> x
451     | None ->
452     if s.gen1 = !gen then IdSet.empty
453 abate 677 else (s.gen1 <- !gen; fv_descr s.d)
454 abate 277 and fv_descr = function
455 abate 677 | IDummy -> assert false
456 abate 278 | IType _ -> IdSet.empty
457 abate 277 | IOr (d1,d2)
458     | IAnd (d1,d2)
459     | IDiff (d1,d2) -> IdSet.cup (fv_descr d1) (fv_descr d2)
460     | IOptional d -> fv_descr d
461     | ITimes (s1,s2)
462     | IXml (s1,s2)
463     | IArrow (s1,s2) -> IdSet.cup (fv_slot s1) (fv_slot s2)
464 abate 426 | IRecord (o,r) ->
465     List.fold_left IdSet.cup IdSet.empty (LabelMap.map_to_list fv_slot r)
466 abate 277 | ICapture x | IConstant (x,_) -> IdSet.singleton x
467 abate 278
468 abate 277 let compute_fv s =
469     match s.fv with
470     | Some x -> ()
471     | None ->
472     incr gen;
473     let x = fv_slot s in
474     s.fv <- Some x
475    
476 abate 656 let check_no_capture loc s =
477     match IdSet.pick s with
478     | Some x ->
479 abate 677 raise_loc_generic loc ("Unbound type name " ^ (Ident.to_string x))
480 abate 656 | None -> ()
481 abate 277
482 abate 278 let compile_slot_hash = DerecursTable.create 67
483     let compile_hash = DerecursTable.create 67
484    
485 abate 677 let todo_defs = ref []
486     let todo_fv = ref []
487 abate 278
488     let rec compile p =
489     try DerecursTable.find compile_hash p
490 abate 277 with Not_found ->
491 abate 278 let c = real_compile p in
492     DerecursTable.replace compile_hash p c;
493     c
494     and real_compile = function
495 abate 677 | PDummy -> assert false
496 abate 278 | PAlias v ->
497     if v.ploop then
498     raise_loc_generic v.ploc ("Unguarded recursion on type/pattern");
499     v.ploop <- true;
500 abate 677 let r = compile v.pdescr in
501 abate 278 v.ploop <- false;
502     r
503     | PType t -> IType t
504     | POr (t1,t2) -> IOr (compile t1, compile t2)
505     | PAnd (t1,t2) -> IAnd (compile t1, compile t2)
506     | PDiff (t1,t2) -> IDiff (compile t1, compile t2)
507     | PTimes (t1,t2) -> ITimes (compile_slot t1, compile_slot t2)
508     | PXml (t1,t2) -> IXml (compile_slot t1, compile_slot t2)
509     | PArrow (t1,t2) -> IArrow (compile_slot t1, compile_slot t2)
510     | POptional t -> IOptional (compile t)
511     | PRecord (o,r) -> IRecord (o, LabelMap.map compile_slot r)
512     | PConstant (x,v) -> IConstant (x,v)
513     | PCapture x -> ICapture x
514     | PRegexp (r,q) -> compile_regexp r q
515     and compile_regexp r q =
516     let memo = RE.create 17 in
517     let rec aux accu r q =
518     if RE.mem memo (r,q) then accu
519     else (
520     RE.add memo (r,q) ();
521     match r with
522 abate 677 | PEpsilon ->
523 abate 426 (match q with
524     | PRegexp (r,q) -> aux accu r q
525     | _ -> (compile q) :: accu)
526 abate 278 | PElem p -> ITimes (compile_slot p, compile_slot q) :: accu
527     | PSeq (r1,r2) -> aux accu r1 (PRegexp (r2,q))
528     | PAlt (r1,r2) -> aux (aux accu r1 q) r2 q
529     | PStar r1 -> aux (aux accu r1 (PRegexp (r,q))) PEpsilon q
530     | PWeakStar r1 -> aux (aux accu PEpsilon q) r1 (PRegexp (r,q))
531     )
532     in
533     let accu = aux [] r q in
534     match accu with
535     | [] -> assert false
536     | p::l -> List.fold_left (fun acc p -> IOr (p,acc)) p l
537     and compile_slot p =
538     try DerecursTable.find compile_slot_hash p
539     with Not_found ->
540 abate 677 let s = mk_slot () in
541     todo_defs := (s,p) :: !todo_defs;
542     todo_fv := s :: !todo_fv;
543 abate 278 DerecursTable.add compile_slot_hash p s;
544 abate 277 s
545 abate 278
546 abate 277
547 abate 677 let timer_fv = Stats.Timer.create "Typer.fv"
548 abate 277 let rec flush_defs () =
549 abate 677 match !todo_defs with
550     | [] ->
551     Stats.Timer.start timer_fv;
552     List.iter compute_fv !todo_fv;
553     Stats.Timer.stop timer_fv;
554     todo_fv := []
555     | (s,p)::t ->
556     todo_defs := t;
557     s.d <- compile p;
558     flush_defs ()
559 abate 277
560     let typ_nodes = SlotTable.create 67
561     let pat_nodes = SlotTable.create 67
562    
563     let rec typ = function
564     | IType t -> t
565     | IOr (s1,s2) -> Types.cup (typ s1) (typ s2)
566     | IAnd (s1,s2) -> Types.cap (typ s1) (typ s2)
567     | IDiff (s1,s2) -> Types.diff (typ s1) (typ s2)
568     | ITimes (s1,s2) -> Types.times (typ_node s1) (typ_node s2)
569     | IXml (s1,s2) -> Types.xml (typ_node s1) (typ_node s2)
570     | IArrow (s1,s2) -> Types.arrow (typ_node s1) (typ_node s2)
571     | IOptional s -> Types.Record.or_absent (typ s)
572     | IRecord (o,r) -> Types.record' (o, LabelMap.map typ_node r)
573 abate 677 | IDummy | ICapture _ | IConstant (_,_) -> assert false
574 abate 277
575 abate 653 and typ_node s : Types.Node.t =
576 abate 277 try SlotTable.find typ_nodes s
577     with Not_found ->
578     let x = Types.make () in
579     SlotTable.add typ_nodes s x;
580 abate 677 Types.define x (typ s.d);
581 abate 277 x
582    
583     let rec pat d : Patterns.descr =
584     if IdSet.is_empty (fv_descr d)
585     then Patterns.constr (typ d)
586     else pat_aux d
587    
588     and pat_aux = function
589 abate 677 | IDummy -> assert false
590 abate 277 | IOr (s1,s2) -> Patterns.cup (pat s1) (pat s2)
591     | IAnd (s1,s2) -> Patterns.cap (pat s1) (pat s2)
592     | IDiff (s1,s2) when IdSet.is_empty (fv_descr s2) ->
593     let s2 = Types.neg (typ s2) in
594     Patterns.cap (pat s1) (Patterns.constr s2)
595     | IDiff _ ->
596 abate 677 raise (Patterns.Error "Differences are not allowed in patterns")
597 abate 277 | ITimes (s1,s2) -> Patterns.times (pat_node s1) (pat_node s2)
598     | IXml (s1,s2) -> Patterns.xml (pat_node s1) (pat_node s2)
599     | IOptional _ ->
600 abate 677 raise (Patterns.Error "Optional fields are not allowed in record patterns")
601 abate 277 | IRecord (o,r) ->
602     let pats = ref [] in
603     let aux l s =
604     if IdSet.is_empty (fv_slot s) then typ_node s
605     else
606     ( pats := Patterns.record l (pat_node s) :: !pats;
607     Types.any_node )
608     in
609     let constr = Types.record' (o,LabelMap.mapi aux r) in
610     List.fold_left Patterns.cap (Patterns.constr constr) !pats
611     (* TODO: can avoid constr when o=true, and all fields have fv *)
612     | ICapture x -> Patterns.capture x
613     | IConstant (x,c) -> Patterns.constant x c
614     | IArrow _ ->
615 abate 677 raise (Patterns.Error "Arrows are not allowed in patterns")
616 abate 277 | IType _ -> assert false
617    
618     and pat_node s : Patterns.node =
619     try SlotTable.find pat_nodes s
620     with Not_found ->
621     let x = Patterns.make (fv_slot s) in
622 abate 640 try
623     SlotTable.add pat_nodes s x;
624 abate 677 Patterns.define x (pat s.d);
625 abate 640 x
626     with exn -> SlotTable.remove pat_nodes s; raise exn
627     (* For the toplevel ... *)
628 abate 431
629 abate 677
630 abate 686 let type_defs env b =
631 abate 278 List.iter
632     (fun (v,p) ->
633 abate 686 if Env.mem v env.ids
634     then raise_loc_generic p.loc ("Identifier " ^ (Ident.to_string v) ^ " is already bound")
635 abate 278 ) b;
636 abate 686 let penv = derecurs_def (penv env) b in
637     let b = List.map (fun (v,p) -> (v,p,compile (derecurs penv p))) b in
638 abate 529 flush_defs ();
639     let b =
640     List.map
641     (fun (v,p,s) ->
642 abate 656 check_no_capture p.loc (fv_descr s);
643 abate 529 let t = typ s in
644     if (p.loc <> noloc) && (Types.is_empty t) then
645     warning p.loc
646 abate 677 ("This definition yields an empty type for " ^ (Ident.to_string v));
647 abate 529 (v,t)) b in
648 abate 677 List.iter (fun (v,t) -> Types.Print.register_global (Id.value v) t) b;
649 abate 686 b
650 abate 278
651 abate 505
652 abate 686 let dump_types ppf env =
653     Env.iter (fun v ->
654     function
655     (Type _) -> Format.fprintf ppf " %a" Ident.print v
656     | _ -> ()) env.ids
657 abate 529
658 abate 686 let dump_ns ppf env =
659     Ns.dump_table ppf env.tenv_nspref
660 abate 552
661 abate 656
662 abate 505 let do_typ loc r =
663     let s = compile_slot r in
664 abate 277 flush_defs ();
665 abate 656 check_no_capture loc (fv_slot s);
666     typ_node s
667 abate 505
668 abate 686 let typ env p =
669     do_typ p.loc (derecurs (penv env) p)
670 abate 277
671 abate 686 let pat env p =
672     let s = compile_slot (derecurs (penv env) p) in
673 abate 277 flush_defs ();
674     try pat_node s
675     with Patterns.Error e -> raise_loc_generic p.loc e
676 abate 522 | Location (loc,_,exn) when loc = noloc -> raise (Location (p.loc, `Full, exn))
677 abate 5
678    
679     (* II. Build skeleton *)
680    
681 abate 542
682 abate 686 type op = [ `Unary of env -> Typed.unary_op | `Binary of env -> Typed.binary_op ]
683 abate 542 let op_table : (string,op) Hashtbl.t = Hashtbl.create 31
684     let register_unary_op s f = Hashtbl.add op_table s (`Unary f)
685     let register_binary_op s f = Hashtbl.add op_table s (`Binary f)
686     let find_op s = Hashtbl.find op_table s
687    
688    
689 abate 225 module Fv = IdSet
690 abate 6
691 abate 427 type branch = Branch of Typed.branch * branch list
692 abate 314
693 abate 427 let cur_branch : branch list ref = ref []
694    
695 abate 316 let exp loc fv e =
696 abate 6 fv,
697     { Typed.exp_loc = loc;
698 abate 5 Typed.exp_typ = Types.empty;
699 abate 316 Typed.exp_descr = e;
700 abate 5 }
701 abate 316
702    
703 abate 686 let rec expr env loc = function
704     | LocatedExpr (loc,e) -> expr env loc e
705 abate 316 | Forget (e,t) ->
706 abate 686 let (fv,e) = expr env loc e and t = typ env t in
707 abate 316 exp loc fv (Typed.Forget (e,t))
708     | Var s ->
709     exp loc (Fv.singleton s) (Typed.Var s)
710     | Apply (e1,e2) ->
711 abate 686 let (fv1,e1) = expr env loc e1 and (fv2,e2) = expr env loc e2 in
712 abate 316 exp loc (Fv.cup fv1 fv2) (Typed.Apply (e1,e2))
713     | Abstraction a ->
714 abate 686 let iface = List.map (fun (t1,t2) -> (typ env t1, typ env t2))
715 abate 316 a.fun_iface in
716     let t = List.fold_left
717     (fun accu (t1,t2) -> Types.cap accu (Types.arrow t1 t2))
718     Types.any iface in
719     let iface = List.map
720     (fun (t1,t2) -> (Types.descr t1, Types.descr t2))
721     iface in
722 abate 686 let (fv0,body) = branches env a.fun_body in
723 abate 316 let fv = match a.fun_name with
724     | None -> fv0
725     | Some f -> Fv.remove f fv0 in
726     let e = Typed.Abstraction
727     { Typed.fun_name = a.fun_name;
728     Typed.fun_iface = iface;
729     Typed.fun_body = body;
730     Typed.fun_typ = t;
731     Typed.fun_fv = fv
732     } in
733     exp loc fv e
734 abate 672 | (Integer _ | Char _ | Atom _) as c ->
735 abate 686 exp loc Fv.empty (Typed.Cst (const env loc c))
736 abate 316 | Pair (e1,e2) ->
737 abate 686 let (fv1,e1) = expr env loc e1 and (fv2,e2) = expr env loc e2 in
738 abate 316 exp loc (Fv.cup fv1 fv2) (Typed.Pair (e1,e2))
739     | Xml (e1,e2) ->
740 abate 686 let (fv1,e1) = expr env loc e1 and (fv2,e2) = expr env loc e2 in
741 abate 316 exp loc (Fv.cup fv1 fv2) (Typed.Xml (e1,e2))
742     | Dot (e,l) ->
743 abate 686 let (fv,e) = expr env loc e in
744     exp loc fv (Typed.Dot (e,parse_label env loc l))
745 abate 316 | RemoveField (e,l) ->
746 abate 686 let (fv,e) = expr env loc e in
747     exp loc fv (Typed.RemoveField (e,parse_label env loc l))
748 abate 316 | RecordLitt r ->
749     let fv = ref Fv.empty in
750 abate 686 let r = parse_record env loc
751 abate 316 (fun e ->
752 abate 686 let (fv2,e) = expr env loc e
753 abate 316 in fv := Fv.cup !fv fv2; e)
754     r in
755     exp loc !fv (Typed.RecordLitt r)
756 abate 522 | String (i,j,s,e) ->
757 abate 686 let (fv,e) = expr env loc e in
758 abate 522 exp loc fv (Typed.String (i,j,s,e))
759 abate 316 | Op (op,le) ->
760 abate 686 let (fvs,ltes) = List.split (List.map (expr env loc) le) in
761 abate 316 let fv = List.fold_left Fv.cup Fv.empty fvs in
762 abate 421 (try
763 abate 542 (match (ltes,find_op op) with
764 abate 686 | [e], `Unary op -> exp loc fv (Typed.UnaryOp (op env, e))
765     | [e1;e2], `Binary op -> exp loc fv (Typed.BinaryOp (op env, e1,e2))
766 abate 421 | _ -> assert false)
767     with Not_found -> assert false)
768    
769 abate 316 | Match (e,b) ->
770 abate 686 let (fv1,e) = expr env loc e
771     and (fv2,b) = branches env b in
772 abate 316 exp loc (Fv.cup fv1 fv2) (Typed.Match (e, b))
773 abate 421 | Map (e,b) ->
774 abate 686 let (fv1,e) = expr env loc e
775     and (fv2,b) = branches env b in
776 abate 421 exp loc (Fv.cup fv1 fv2) (Typed.Map (e, b))
777     | Transform (e,b) ->
778 abate 686 let (fv1,e) = expr env loc e
779     and (fv2,b) = branches env b in
780 abate 421 exp loc (Fv.cup fv1 fv2) (Typed.Transform (e, b))
781 abate 331 | Xtrans (e,b) ->
782 abate 686 let (fv1,e) = expr env loc e
783     and (fv2,b) = branches env b in
784 abate 331 exp loc (Fv.cup fv1 fv2) (Typed.Xtrans (e, b))
785 abate 501 | Validate (e,schema,elt) ->
786 abate 686 let (fv,e) = expr env loc e in
787 abate 501 exp loc fv (Typed.Validate (e, schema, elt))
788 abate 316 | Try (e,b) ->
789 abate 686 let (fv1,e) = expr env loc e
790     and (fv2,b) = branches env b in
791 abate 316 exp loc (Fv.cup fv1 fv2) (Typed.Try (e, b))
792 abate 530 | NamespaceIn (pr,ns,e) ->
793 abate 686 let env = enter_ns pr ns env in
794     expr env loc e
795 abate 623 | Ref (e,t) ->
796 abate 686 let (fv,e) = expr env loc e and t = typ env t in
797 abate 623 exp loc fv (Typed.Ref (e,t))
798 abate 5
799 abate 686 and branches env b =
800 abate 6 let fv = ref Fv.empty in
801 abate 19 let accept = ref Types.empty in
802 abate 314 let branch (p,e) =
803 abate 427 let cur_br = !cur_branch in
804     cur_branch := [];
805 abate 686 let (fv2,e) = expr env noloc e in
806 abate 316 let br_loc = merge_loc p.loc e.Typed.exp_loc in
807 abate 686 let p = pat env p in
808 abate 656 (match Fv.pick (Fv.diff (Patterns.fv p) fv2) with
809     | None -> ()
810     | Some x ->
811     let x = U.to_string (Id.value x) in
812     warning br_loc
813     ("The capture variable " ^ x ^
814 abate 667 " is declared in the pattern but not used in the body of this branch. It might be a misspelled type or name (if not use _ instead)."));
815 abate 314 let fv2 = Fv.diff fv2 (Patterns.fv p) in
816     fv := Fv.cup !fv fv2;
817     accept := Types.cup !accept (Types.descr (Patterns.accept p));
818     let br =
819     {
820     Typed.br_loc = br_loc;
821     Typed.br_used = br_loc = noloc;
822     Typed.br_pat = p;
823     Typed.br_body = e } in
824 abate 427 cur_branch := Branch (br, !cur_branch) :: cur_br;
825 abate 314 br in
826     let b = List.map branch b in
827 abate 19 (!fv,
828     {
829     Typed.br_typ = Types.empty;
830     Typed.br_branches = b;
831 abate 45 Typed.br_accept = !accept;
832     Typed.br_compiled = None;
833 abate 19 }
834     )
835 abate 5
836 abate 686 let expr env = expr env noloc
837 abate 122
838 abate 686 let let_decl env p e =
839     let (_,e) = expr env e in
840     { Typed.let_pat = pat env p;
841 abate 66 Typed.let_body = e;
842     Typed.let_compiled = None }
843    
844 abate 529
845     (* Hide global "typing/parsing" environment *)
846    
847    
848 abate 66 (* III. Type-checks *)
849    
850 abate 6 open Typed
851    
852 abate 421 let require loc t s =
853     if not (Types.subtype t s) then raise_loc loc (Constraint (t, s))
854 abate 17
855 abate 421 let check loc t s =
856     require loc t s; t
857 abate 17
858 abate 522 let check_str loc ofs t s =
859     if not (Types.subtype t s) then raise_loc_str loc ofs (Constraint (t, s));
860     t
861    
862     let should_have loc constr s =
863 abate 421 raise_loc loc (ShouldHave (constr,s))
864    
865 abate 522 let should_have_str loc ofs constr s =
866     raise_loc_str loc ofs (ShouldHave (constr,s))
867    
868 abate 421 let flatten loc arg constr precise =
869     let constr' = Sequence.star
870     (Sequence.approx (Types.cap Sequence.any constr)) in
871     let sconstr' = Sequence.star constr' in
872     let exact = Types.subtype constr' constr in
873     if exact then
874     let t = arg sconstr' precise in
875     if precise then Sequence.flatten t else constr
876     else
877     let t = arg sconstr' true in
878     Sequence.flatten t
879    
880 abate 19 let rec type_check env e constr precise =
881     let d = type_check' e.exp_loc env e.exp_descr constr precise in
882 abate 421 let d = if precise then d else constr in
883 abate 6 e.exp_typ <- Types.cup e.exp_typ d;
884     d
885    
886 abate 19 and type_check' loc env e constr precise = match e with
887 abate 54 | Forget (e,t) ->
888     let t = Types.descr t in
889     ignore (type_check env e t false);
890 abate 421 check loc t constr
891    
892 abate 19 | Abstraction a ->
893     let t =
894     try Types.Arrow.check_strenghten a.fun_typ constr
895     with Not_found ->
896 abate 421 should_have loc constr
897     "but the interface of the abstraction is not compatible"
898 abate 19 in
899     let env = match a.fun_name with
900     | None -> env
901 abate 686 | Some f -> enter_value f a.fun_typ env in
902 abate 19 List.iter
903     (fun (t1,t2) ->
904 abate 374 let acc = a.fun_body.br_accept in
905     if not (Types.subtype t1 acc) then
906     raise_loc loc (NonExhaustive (Types.diff t1 acc));
907 abate 65 ignore (type_check_branches loc env t1 a.fun_body t2 false)
908 abate 19 ) a.fun_iface;
909     t
910 abate 64
911 abate 19 | Match (e,b) ->
912     let t = type_check env e b.br_accept true in
913 abate 65 type_check_branches loc env t b constr precise
914 abate 30
915 abate 64 | Try (e,b) ->
916     let te = type_check env e constr precise in
917 abate 65 let tb = type_check_branches loc env Types.any b constr precise in
918 abate 64 Types.cup te tb
919    
920 abate 110 | Pair (e1,e2) ->
921     type_check_pair loc env e1 e2 constr precise
922 abate 421
923 abate 110 | Xml (e1,e2) ->
924     type_check_pair ~kind:`XML loc env e1 e2 constr precise
925 abate 159
926 abate 29 | RecordLitt r ->
927 abate 421 type_record loc env r constr precise
928 abate 31
929 abate 421 | Map (e,b) ->
930     type_map loc env false e b constr precise
931    
932     | Transform (e,b) ->
933     flatten loc (type_map loc env true e b) constr precise
934    
935 abate 86 | Apply (e1,e2) ->
936     let t1 = type_check env e1 Types.Arrow.any true in
937     let t1 = Types.Arrow.get t1 in
938     let dom = Types.Arrow.domain t1 in
939 abate 110 let res =
940     if Types.Arrow.need_arg t1 then
941     let t2 = type_check env e2 dom true in
942     Types.Arrow.apply t1 t2
943     else
944     (ignore (type_check env e2 dom false); Types.Arrow.apply_noarg t1)
945     in
946 abate 421 check loc res constr
947 abate 19
948 abate 421 | UnaryOp (o,e) ->
949 abate 426 let t = o.un_op_typer loc
950     (type_check env e) constr precise in
951 abate 421 check loc t constr
952    
953     | BinaryOp (o,e1,e2) ->
954 abate 426 let t = o.bin_op_typer loc
955     (type_check env e1)
956     (type_check env e2) constr precise in
957 abate 421 check loc t constr
958    
959     | Var s ->
960     let t =
961 abate 686 try find_value s env
962 abate 656 with Not_found ->
963 abate 686 raise_loc loc (UnboundId (s, Env.mem s env.ids) ) in
964 abate 421 check loc t constr
965    
966     | Cst c ->
967     check loc (Types.constant c) constr
968    
969 abate 522 | String (i,j,s,e) ->
970     type_check_string loc env 0 s i j e constr precise
971    
972 abate 421 | Dot (e,l) ->
973     let t = type_check env e Types.Record.any true in
974     let t =
975     try (Types.Record.project t l)
976     with Not_found -> raise_loc loc (WrongLabel(t,l))
977     in
978     check loc t constr
979    
980     | RemoveField (e,l) ->
981     let t = type_check env e Types.Record.any true in
982     let t = Types.Record.remove_field t l in
983     check loc t constr
984    
985     | Xtrans (e,b) ->
986     let t = type_check env e Sequence.any true in
987     let t =
988     Sequence.map_tree
989     (fun t ->
990     let resid = Types.diff t b.br_accept in
991     let res = type_check_branches loc env t b Sequence.any true in
992     (res,resid)
993     ) t in
994     check loc t constr
995    
996 abate 501 | Validate (e, schema_name, elt_name) ->
997     ignore (type_check env e Types.any false);
998     let t = fst (Hashtbl.find !schema_elements (schema_name, elt_name)) in
999     check loc t constr
1000 abate 421
1001 abate 623 | Ref (e,t) ->
1002     ignore (type_check env e (Types.descr t) false);
1003     check loc (Builtin_defs.ref_type t) constr
1004    
1005 abate 110 and type_check_pair ?(kind=`Normal) loc env e1 e2 constr precise =
1006 abate 361 let rects = Types.Product.normal ~kind constr in
1007 abate 110 if Types.Product.is_empty rects then
1008     (match kind with
1009 abate 421 | `Normal -> should_have loc constr "but it is a pair"
1010     | `XML -> should_have loc constr "but it is an XML element");
1011 abate 334 let need_s = Types.Product.need_second rects in
1012 abate 355 let t1 = type_check env e1 (Types.Product.pi1 rects) (precise || need_s) in
1013     let c2 = Types.Product.constraint_on_2 rects t1 in
1014     if Types.is_empty c2 then
1015     raise_loc loc (ShouldHave2 (constr,"but the first component has type",t1));
1016     let t2 = type_check env e2 c2 precise in
1017 abate 334
1018 abate 110 if precise then
1019 abate 355 match kind with
1020     | `Normal -> Types.times (Types.cons t1) (Types.cons t2)
1021     | `XML -> Types.xml (Types.cons t1) (Types.cons t2)
1022 abate 110 else
1023     constr
1024    
1025 abate 522 and type_check_string loc env ofs s i j e constr precise =
1026     if U.equal_index i j then type_check env e constr precise
1027     else
1028     let rects = Types.Product.normal constr in
1029     if Types.Product.is_empty rects
1030     then should_have_str loc ofs constr "but it is a string"
1031     else
1032     let need_s = Types.Product.need_second rects in
1033     let (ch,i') = U.next s i in
1034 abate 656 let ch = Chars.V.mk_int ch in
1035 abate 522 let tch = Types.constant (Types.Char ch) in
1036     let t1 = check_str loc ofs tch (Types.Product.pi1 rects) in
1037     let c2 = Types.Product.constraint_on_2 rects t1 in
1038     let t2 = type_check_string loc env (ofs + 1) s i' j e c2 precise in
1039     if precise then Types.times (Types.cons t1) (Types.cons t2)
1040     else constr
1041    
1042 abate 421 and type_record loc env r constr precise =
1043     (* try to get rid of precise = true for values of fields *)
1044     (* also: the use equivalent of need_second to optimize... *)
1045     if not (Types.Record.has_record constr) then
1046     should_have loc constr "but it is a record";
1047     let (rconstr,res) =
1048     List.fold_left
1049     (fun (rconstr,res) (l,e) ->
1050     (* could compute (split l e) once... *)
1051     let pi = Types.Record.project_opt rconstr l in
1052     if Types.is_empty pi then
1053 abate 542 (let l = Label.to_string (LabelPool.value l) in
1054 abate 421 should_have loc constr
1055     (Printf.sprintf "Field %s is not allowed here." l));
1056     let t = type_check env e pi true in
1057     let rconstr = Types.Record.condition rconstr l t in
1058     let res = (l,Types.cons t) :: res in
1059     (rconstr,res)
1060     ) (constr, []) (LabelMap.get r)
1061     in
1062     if not (Types.Record.has_empty_record rconstr) then
1063     should_have loc constr "More fields should be present";
1064     let t =
1065     Types.record' (false, LabelMap.from_list (fun _ _ -> assert false) res)
1066     in
1067     check loc t constr
1068 abate 110
1069 abate 19
1070 abate 65 and type_check_branches loc env targ brs constr precise =
1071 abate 374 if Types.is_empty targ then Types.empty
1072 abate 9 else (
1073     brs.br_typ <- Types.cup brs.br_typ targ;
1074 abate 65 branches_aux loc env targ
1075 abate 19 (if precise then Types.empty else constr)
1076     constr precise brs.br_branches
1077 abate 9 )
1078 abate 6
1079 abate 65 and branches_aux loc env targ tres constr precise = function
1080 abate 374 | [] -> tres
1081 abate 6 | b :: rem ->
1082     let p = b.br_pat in
1083     let acc = Types.descr (Patterns.accept p) in
1084    
1085     let targ' = Types.cap targ acc in
1086     if Types.is_empty targ'
1087 abate 65 then branches_aux loc env targ tres constr precise rem
1088 abate 6 else
1089     ( b.br_used <- true;
1090     let res = Patterns.filter targ' p in
1091 abate 686 let res = List.map (fun (x,t) -> (x,Types.descr t)) res in
1092     let env' = enter_values res env in
1093 abate 19 let t = type_check env' b.br_body constr precise in
1094     let tres = if precise then Types.cup t tres else tres in
1095 abate 9 let targ'' = Types.diff targ acc in
1096     if (Types.non_empty targ'') then
1097 abate 65 branches_aux loc env targ'' tres constr precise rem
1098 abate 9 else
1099     tres
1100 abate 6 )
1101 abate 16
1102 abate 421 and type_map loc env def e b constr precise =
1103     let acc = if def then Sequence.any else Sequence.star b.br_accept in
1104     let t = type_check env e acc true in
1105    
1106     let constr' = Sequence.approx (Types.cap Sequence.any constr) in
1107     let exact = Types.subtype (Sequence.star constr') constr in
1108     (* Note:
1109     - could be more precise by integrating the decomposition
1110     of constr inside Sequence.map.
1111     *)
1112     let res =
1113     Sequence.map
1114     (fun t ->
1115     let res =
1116     type_check_branches loc env t b constr' (precise || (not exact)) in
1117     if def && not (Types.subtype t b.br_accept)
1118     then Types.cup res Sequence.nil_type
1119     else res)
1120     t in
1121     if exact then res else check loc res constr
1122    
1123 abate 66 and type_let_decl env l =
1124     let acc = Types.descr (Patterns.accept l.let_pat) in
1125     let t = type_check env l.let_body acc true in
1126     let res = Patterns.filter t l.let_pat in
1127     List.map (fun (x,t) -> (x, Types.descr t)) res
1128    
1129     and type_rec_funs env l =
1130     let types =
1131     List.fold_left
1132 abate 431 (fun accu -> function
1133 abate 656 | { exp_descr=Abstraction { fun_typ = t; fun_name = Some f };
1134     exp_loc=loc } ->
1135 abate 686 if Env.mem f env.ids then
1136 abate 656 error loc "This function name clashes with a type name";
1137 abate 431 (f,t) :: accu
1138     | _ -> assert false
1139     ) [] l
1140 abate 66 in
1141 abate 686 let env' = enter_values types env in
1142 abate 431 List.iter (fun e -> ignore (type_check env' e Types.any false)) l;
1143 abate 66 types
1144    
1145 abate 427
1146     let rec unused_branches b =
1147 abate 314 List.iter
1148 abate 427 (fun (Branch (br,s)) ->
1149     if not br.br_used
1150     then warning br.br_loc "This branch is not used"
1151     else unused_branches s
1152     )
1153     b
1154 abate 314
1155 abate 427 let report_unused_branches () =
1156     unused_branches !cur_branch;
1157     cur_branch := []
1158 abate 637
1159     let clear_unused_branches () =
1160     cur_branch := []
1161 abate 427
1162 abate 501 (* Schema stuff from now on ... *)
1163    
1164 abate 508 let debug = true
1165 abate 501
1166     (** convertion from XML Schema types (including global elements and
1167     attributes) to CDuce Types.descr *)
1168     module Schema_converter =
1169     struct
1170    
1171 abate 508 open Printf
1172     open Schema_types
1173 abate 501
1174     (* auxiliary functions *)
1175    
1176     (* build a regexp Elem from a Types.descr *)
1177 abate 505 let mk_re_elt descr = PElem descr
1178 abate 501
1179     (* conversion functions *)
1180    
1181     let cd_type_of_simple_type = function
1182 abate 505 | SBuilt_in name -> PType (Schema_builtin.cd_type_of_builtin name)
1183 abate 501 | SUser_defined (_, _, _, _) -> assert false (* TODO *)
1184    
1185 abate 505 let complex_memo = Hashtbl.create 213
1186    
1187 abate 501 let rec regexp_of_term = function
1188 abate 516 | All [] | Choice [] | Sequence [] -> PEpsilon
1189 abate 501 | Choice (hd :: tl) ->
1190     List.fold_left
1191 abate 505 (fun acc particle -> PAlt (acc, regexp_of_particle particle))
1192 abate 501 (regexp_of_particle hd) tl
1193 abate 516 | All (hd :: tl) | Sequence (hd :: tl) ->
1194 abate 501 List.fold_left
1195 abate 505 (fun acc particle -> PSeq (acc, regexp_of_particle particle))
1196 abate 501 (regexp_of_particle hd) tl
1197     | Elt decl -> mk_re_elt (cd_type_of_elt_decl !decl)
1198    
1199     and regexp_of_content_type = function
1200 abate 505 | CT_empty -> PEpsilon
1201 abate 501 | CT_simple st -> mk_re_elt (cd_type_of_simple_type st)
1202     | CT_model (particle, mixed) ->
1203     assert (not mixed); (* TODO mixed support *)
1204     regexp_of_particle particle
1205    
1206     and regexp_of_particle =
1207     (* given a regexp re and a (non negative) integer n create a regexp
1208     matching exactly n times re *)
1209     let rec repeat_regexp re = function
1210 abate 505 | 0 -> PEpsilon
1211     | n when n > 0 -> PSeq (re, repeat_regexp re (n - 1))
1212 abate 501 | _ -> assert false
1213     in
1214     fun (min, max, term) ->
1215     let term_regexp = regexp_of_term term in
1216     let min_regexp = repeat_regexp term_regexp min in
1217     match max with
1218     | Some max ->
1219     assert (max >= min);
1220     let rec aux acc = function
1221     | 0 -> acc
1222     | n ->
1223     aux
1224 abate 505 (PAlt (PEpsilon, (PSeq (term_regexp, acc))))
1225 abate 501 (n - 1)
1226     in
1227 abate 505 PSeq (min_regexp, aux PEpsilon (max - min))
1228     | None -> PSeq (min_regexp, PStar term_regexp)
1229 abate 501
1230     (** @return a pair composed by a type for the attributes (a record) and a
1231     type for the content model (a sequence) *)
1232     and cd_type_of_complex_type' = function
1233     | CBuilt_in name -> assert false
1234 abate 505 | CUser_defined (id, name, _, _, attr_uses, content) ->
1235     try PAlias (Hashtbl.find complex_memo id)
1236     with Not_found ->
1237 abate 677 let slot = mk_derecurs_slot noloc in
1238 abate 505 Hashtbl.add complex_memo id slot;
1239     let content_re = regexp_of_content_type content in
1240     let content_ast_node = PRegexp (content_re, PType Sequence.nil_type) in
1241 abate 677 slot.pdescr <-
1242     PTimes (cd_type_of_attr_uses attr_uses, content_ast_node);
1243 abate 505 PAlias slot
1244    
1245 abate 501
1246 abate 508 (* TODO if constraint is Fixed we can give a more precise CDuce type *)
1247    
1248 abate 501 (** @return a closed record *)
1249     and cd_type_of_attr_uses attr_uses =
1250 abate 505 let fields =
1251     List.map
1252     (fun (required, (name, st, _), _) ->
1253 abate 508 let r = cd_type_of_simple_type st in
1254 abate 505 let r = if required then r else POptional r in
1255 abate 542 (LabelPool.mk (Ns.empty, U.mk name), r) (* TODO: NS *)
1256 abate 505 ) attr_uses in
1257     PRecord (false, LabelMap.from_list_disj fields)
1258 abate 501
1259 abate 508 and cd_type_of_att_decl (name, st, _) =
1260     let r = cd_type_of_simple_type st in
1261 abate 542 PRecord (false, LabelMap.from_list_disj [(LabelPool.mk (Ns.empty, U.mk name), r)])
1262     (* TODO: NS *)
1263 abate 508
1264 abate 501 and cd_type_of_elt_decl (name, typ, _) =
1265 abate 656 let atom_type = PType (Types.atom (Atoms.atom (Atoms.V.mk Ns.empty (U.mk name)))) in
1266 abate 505 let content = match !typ with
1267 abate 508 | S st ->
1268     PTimes (PType Types.empty_closed_record, cd_type_of_simple_type st)
1269 abate 505 | C ct -> cd_type_of_complex_type' ct
1270     in
1271     PXml (atom_type, content)
1272 abate 501
1273 abate 505 let typ r = Types.descr (do_typ noloc r)
1274    
1275 abate 501 let cd_type_of_complex_type = function
1276     | CBuilt_in name -> Schema_builtin.cd_type_of_builtin name
1277 abate 505 | ct -> typ (PXml (PType Types.any, cd_type_of_complex_type' ct))
1278 abate 501
1279     let cd_type_of_type_def = function
1280 abate 505 | S st -> typ (cd_type_of_simple_type st)
1281 abate 501 | C ct -> cd_type_of_complex_type ct
1282    
1283 abate 508 let cd_type_of_elt_decl x = typ (cd_type_of_elt_decl x)
1284     let cd_type_of_att_decl x = typ (cd_type_of_att_decl x)
1285 abate 505
1286 abate 501 end
1287    
1288     let get_schema_validator (schema_name, elt_name) =
1289     snd (Hashtbl.find !schema_elements (schema_name, elt_name))
1290    
1291     let register_schema schema_name schema =
1292     if StringSet.mem schema_name !schemas then
1293     failwith ("Redefinition of schema " ^ schema_name)
1294     else begin
1295     schemas := StringSet.add schema_name !schemas;
1296     List.iter (* Schema types -> CDuce types *)
1297     (fun type_def ->
1298     let cd_type = Schema_converter.cd_type_of_type_def type_def in
1299     Hashtbl.add !schema_types
1300     (schema_name, Schema_types.name_of_type_def type_def)
1301     cd_type)
1302     schema.Schema_types.type_defs;
1303 abate 508 List.iter (* Schema attributes -> CDuce types *)
1304     (fun (att_name, _, _) as att_decl ->
1305     let cd_type = Schema_converter.cd_type_of_att_decl att_decl in
1306     Hashtbl.add !schema_attributes (schema_name, att_name) cd_type)
1307     schema.Schema_types.att_decls;
1308 abate 501 List.iter (* Schema elements -> CDuce types * validators *)
1309     (fun elt_decl ->
1310     let cd_type = Schema_converter.cd_type_of_elt_decl elt_decl in
1311     if debug then
1312     (Types.Print.print Format.std_formatter cd_type;
1313     Format.fprintf Format.std_formatter "\n";
1314     Format.pp_print_flush Format.std_formatter ());
1315     let validator = Schema_validator.validator_of_elt_decl elt_decl in
1316     Hashtbl.add !schema_elements
1317     (schema_name, Schema_types.name_of_elt_decl elt_decl)
1318     (cd_type, validator))
1319     schema.Schema_types.elt_decls
1320     end
1321    
1322     (* DEBUGGING ONLY *)
1323    
1324 abate 508 let get_schema_type x = fst (Hashtbl.find !schema_elements x)

CVS Admin">CVS Admin
ViewVC Help
Powered by ViewVC 1.1.5