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

Contents of /typing/typer.ml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 667 - (hide annotations)
Tue Jul 10 17:52:34 2007 UTC (5 years, 11 months ago) by abate
File size: 41452 byte(s)
[r2003-09-22 16:18:19 by cvscast] Empty log message

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