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

Contents of /typing/typer.ml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 695 - (hide annotations)
Tue Jul 10 17:56:03 2007 UTC (5 years, 10 months ago) by abate
File size: 43589 byte(s)
[r2003-10-02 20:04:31 by cvscast] Cleaning + new semantics for default values in regexps

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