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

Contents of /typing/typer.ml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 549 - (hide annotations)
Tue Jul 10 17:43:35 2007 UTC (5 years, 11 months ago) by abate
File size: 40277 byte(s)
[r2003-06-30 14:11:14 by cvscast] Namespaces in record fields

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