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

Contents of /typing/typer.ml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 694 - (hide annotations)
Tue Jul 10 17:55:47 2007 UTC (5 years, 10 months ago) by abate
File size: 42956 byte(s)
[r2003-10-01 22:59:28 by cvscast] Empty log message

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