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

Contents of /typing/typer.ml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 427 - (hide annotations)
Tue Jul 10 17:33:51 2007 UTC (5 years, 11 months ago) by abate
File size: 29140 byte(s)
[r2003-05-25 12:20:16 by cvscast] No warning for embedded unused branches

Original author: cvscast
Date: 2003-05-25 12:20:16+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     Location.print_loc loc
11     Location.html_hilight loc
12     msg
13    
14 abate 5 (* I. Transform the abstract syntax of types and patterns into
15     the internal form *)
16    
17     open Location
18     open Ast
19 abate 225 open Ident
20 abate 5
21 abate 140 module S = struct type t = string let compare = compare end
22 abate 225 module TypeEnv = Map.Make(S)
23 abate 140
24 abate 9 exception NonExhaustive of Types.descr
25 abate 421 exception Constraint of Types.descr * Types.descr
26 abate 19 exception ShouldHave of Types.descr * string
27 abate 355 exception ShouldHave2 of Types.descr * string * Types.descr
28 abate 233 exception WrongLabel of Types.descr * label
29 abate 374 exception UnboundId of id
30 abate 421 exception Error of string
31 abate 5
32 abate 9 let raise_loc loc exn = raise (Location (loc,exn))
33 abate 421 let error loc msg = raise_loc loc (Error msg)
34 abate 9
35 abate 5
36 abate 278 (* Eliminate Recursion, propagate Sequence Capture Variables *)
37 abate 5
38 abate 278 let rec seq_vars accu = function
39     | Epsilon | Elem _ -> accu
40     | Seq (r1,r2) | Alt (r1,r2) -> seq_vars (seq_vars accu r1) r2
41     | Star r | WeakStar r -> seq_vars accu r
42     | SeqCapture (v,r) -> seq_vars (IdSet.add v accu) r
43 abate 71
44 abate 278 type derecurs_slot = {
45     ploc : Location.loc;
46     pid : int;
47     mutable ploop : bool;
48     mutable pdescr : derecurs option
49     } and derecurs =
50     | PAlias of derecurs_slot
51     | PType of Types.descr
52     | POr of derecurs * derecurs
53     | PAnd of derecurs * derecurs
54     | PDiff of derecurs * derecurs
55     | PTimes of derecurs * derecurs
56     | PXml of derecurs * derecurs
57     | PArrow of derecurs * derecurs
58     | POptional of derecurs
59     | PRecord of bool * derecurs label_map
60     | PCapture of id
61     | PConstant of id * Types.const
62     | PRegexp of derecurs_regexp * derecurs
63     and derecurs_regexp =
64     | PEpsilon
65     | PElem of derecurs
66     | PSeq of derecurs_regexp * derecurs_regexp
67     | PAlt of derecurs_regexp * derecurs_regexp
68     | PStar of derecurs_regexp
69     | PWeakStar of derecurs_regexp
70 abate 71
71 abate 278 let rec hash_derecurs = function
72 abate 426 | PAlias s ->
73     s.pid
74     | PType t ->
75     1 + 17 * (Types.hash_descr t)
76     | POr (p1,p2) ->
77     2 + 17 * (hash_derecurs p1) + 257 * (hash_derecurs p2)
78     | PAnd (p1,p2) ->
79     3 + 17 * (hash_derecurs p1) + 257 * (hash_derecurs p2)
80     | PDiff (p1,p2) ->
81     4 + 17 * (hash_derecurs p1) + 257 * (hash_derecurs p2)
82     | PTimes (p1,p2) ->
83     5 + 17 * (hash_derecurs p1) + 257 * (hash_derecurs p2)
84     | PXml (p1,p2) ->
85     6 + 17 * (hash_derecurs p1) + 257 * (hash_derecurs p2)
86     | PArrow (p1,p2) ->
87     7 + 17 * (hash_derecurs p1) + 257 * (hash_derecurs p2)
88     | POptional p ->
89     8 + 17 * (hash_derecurs p)
90     | PRecord (o,r) ->
91     (if o then 9 else 10) + 17 * (LabelMap.hash hash_derecurs r)
92     | PCapture x ->
93     11 + 17 * (Id.hash x)
94     | PConstant (x,c) ->
95     12 + 17 * (Id.hash x) + 257 * (Types.hash_const c)
96     | PRegexp (p,q) ->
97     13 + 17 * (hash_derecurs_regexp p) + 257 * (hash_derecurs q)
98 abate 278 and hash_derecurs_regexp = function
99 abate 426 | PEpsilon ->
100     1
101     | PElem p ->
102     2 + 17 * (hash_derecurs p)
103     | PSeq (p1,p2) ->
104     3 + 17 * (hash_derecurs_regexp p1) + 257 * (hash_derecurs_regexp p2)
105     | PAlt (p1,p2) ->
106     4 + 17 * (hash_derecurs_regexp p1) + 257 * (hash_derecurs_regexp p2)
107     | PStar p ->
108     5 + 17 * (hash_derecurs_regexp p)
109     | PWeakStar p ->
110     6 + 17 * (hash_derecurs_regexp p)
111 abate 107
112 abate 278 let rec equal_derecurs p1 p2 = (p1 == p2) || match p1,p2 with
113 abate 426 | PAlias s1, PAlias s2 ->
114     s1 == s2
115     | PType t1, PType t2 ->
116     Types.equal_descr t1 t2
117 abate 278 | POr (p1,q1), POr (p2,q2)
118     | PAnd (p1,q1), PAnd (p2,q2)
119     | PDiff (p1,q1), PDiff (p2,q2)
120     | PTimes (p1,q1), PTimes (p2,q2)
121     | PXml (p1,q1), PXml (p2,q2)
122 abate 426 | PArrow (p1,q1), PArrow (p2,q2) ->
123     (equal_derecurs p1 p2) && (equal_derecurs q1 q2)
124     | POptional p1, POptional p2 ->
125     equal_derecurs p1 p2
126     | PRecord (o1,r1), PRecord (o2,r2) ->
127     (o1 == o2) && (LabelMap.equal equal_derecurs r1 r2)
128     | PCapture x1, PCapture x2 ->
129     Id.equal x1 x2
130     | PConstant (x1,c1), PConstant (x2,c2) ->
131     (Id.equal x1 x2) && (Types.equal_const c1 c2)
132     | PRegexp (p1,q1), PRegexp (p2,q2) ->
133     (equal_derecurs_regexp p1 p2) && (equal_derecurs q1 q2)
134 abate 278 | _ -> false
135     and equal_derecurs_regexp r1 r2 = match r1,r2 with
136 abate 426 | PEpsilon, PEpsilon ->
137     true
138     | PElem p1, PElem p2 ->
139     equal_derecurs p1 p2
140 abate 278 | PSeq (p1,q1), PSeq (p2,q2)
141 abate 426 | PAlt (p1,q1), PAlt (p2,q2) ->
142     (equal_derecurs_regexp p1 p2) && (equal_derecurs_regexp q1 q2)
143 abate 278 | PStar p1, PStar p2
144 abate 426 | PWeakStar p1, PWeakStar p2 ->
145     equal_derecurs_regexp p1 p2
146 abate 278 | _ -> false
147 abate 5
148 abate 278 module DerecursTable = Hashtbl.Make(
149     struct
150     type t = derecurs
151     let hash = hash_derecurs
152     let equal = equal_derecurs
153     end
154     )
155 abate 5
156 abate 278 module RE = Hashtbl.Make(
157     struct
158     type t = derecurs_regexp * derecurs
159 abate 426 let hash (p,q) =
160     (hash_derecurs_regexp p) + 17 * (hash_derecurs q)
161     let equal (p1,q1) (p2,q2) =
162     (equal_derecurs_regexp p1 p2) && (equal_derecurs q1 q2)
163 abate 278 end
164     )
165 abate 71
166 abate 278
167     let counter = State.ref "Typer.counter - derecurs" 0
168     let mk_slot loc =
169     incr counter;
170     { ploop = false; ploc = loc; pid = !counter; pdescr = None }
171    
172     let rec derecurs env p = match p.descr with
173     | PatVar v ->
174     (try PAlias (TypeEnv.find v env)
175 abate 426 with Not_found ->
176     raise_loc_generic p.loc ("Undefined type/pattern " ^ v))
177 abate 278 | Recurs (p,b) -> derecurs (derecurs_def env b) p
178     | Internal t -> PType t
179     | Or (p1,p2) -> POr (derecurs env p1, derecurs env p2)
180     | And (p1,p2) -> PAnd (derecurs env p1, derecurs env p2)
181     | Diff (p1,p2) -> PDiff (derecurs env p1, derecurs env p2)
182     | Prod (p1,p2) -> PTimes (derecurs env p1, derecurs env p2)
183     | XmlT (p1,p2) -> PXml (derecurs env p1, derecurs env p2)
184     | Arrow (p1,p2) -> PArrow (derecurs env p1, derecurs env p2)
185     | Optional p -> POptional (derecurs env p)
186     | Record (o,r) -> PRecord (o, LabelMap.map (derecurs env) r)
187     | Capture x -> PCapture x
188     | Constant (x,c) -> PConstant (x,c)
189     | Regexp (r,q) ->
190 abate 426 let constant_nil t v =
191     PAnd (t, PConstant (v, Types.Atom Sequence.nil_atom)) in
192 abate 278 let vars = seq_vars IdSet.empty r in
193     let q = IdSet.fold constant_nil (derecurs env q) vars in
194     let r = derecurs_regexp (fun p -> p) env r in
195     PRegexp (r, q)
196     and derecurs_regexp vars env = function
197 abate 426 | Epsilon ->
198     PEpsilon
199     | Elem p ->
200     PElem (vars (derecurs env p))
201     | Seq (p1,p2) ->
202     PSeq (derecurs_regexp vars env p1, derecurs_regexp vars env p2)
203     | Alt (p1,p2) ->
204     PAlt (derecurs_regexp vars env p1, derecurs_regexp vars env p2)
205     | Star p ->
206     PStar (derecurs_regexp vars env p)
207     | WeakStar p ->
208     PWeakStar (derecurs_regexp vars env p)
209     | SeqCapture (x,p) ->
210     derecurs_regexp (fun p -> PAnd (vars p, PCapture x)) env p
211 abate 71
212 abate 140
213 abate 278 and derecurs_def env b =
214     let b = List.map (fun (v,p) -> (v,p,mk_slot p.loc)) b in
215     let env = List.fold_left (fun env (v,p,s) -> TypeEnv.add v s env) env b in
216     List.iter (fun (v,p,s) -> s.pdescr <- Some (derecurs env p)) b;
217     env
218 abate 5
219 abate 278 (* Stratification and recursive hash-consing *)
220 abate 5
221 abate 277 type descr =
222     | IType of Types.descr
223     | IOr of descr * descr
224     | IAnd of descr * descr
225     | IDiff of descr * descr
226     | ITimes of slot * slot
227     | IXml of slot * slot
228     | IArrow of slot * slot
229 abate 278 | IOptional of descr
230 abate 277 | IRecord of bool * slot label_map
231     | ICapture of id
232     | IConstant of id * Types.const
233     and slot = {
234     mutable fv : fv option;
235     mutable hash : int option;
236     mutable rank1: int; mutable rank2: int;
237     mutable gen1 : int; mutable gen2: int;
238 abate 278 mutable d : descr option
239 abate 277 }
240    
241     let descr s =
242     match s.d with
243     | Some d -> d
244     | None -> assert false
245    
246     let gen = ref 0
247     let rank = ref 0
248    
249     let rec hash_descr = function
250     | IType x -> Types.hash_descr x
251     | IOr (d1,d2) -> 1 + 17 * (hash_descr d1) + 257 * (hash_descr d2)
252     | IAnd (d1,d2) -> 2 + 17 * (hash_descr d1) + 257 * (hash_descr d2)
253     | IDiff (d1,d2) -> 3 + 17 * (hash_descr d1) + 257 * (hash_descr d2)
254     | IOptional d -> 4 + 17 * (hash_descr d)
255     | ITimes (s1,s2) -> 5 + 17 * (hash_slot s1) + 257 * (hash_slot s2)
256     | IXml (s1,s2) -> 6 + 17 * (hash_slot s1) + 257 * (hash_slot s2)
257     | IArrow (s1,s2) -> 7 + 17 * (hash_slot s1) + 257 * (hash_slot s2)
258     | IRecord (o,r) -> (if o then 8 else 9) + 17 * (LabelMap.hash hash_slot r)
259     | ICapture x -> 10 + 17 * (Id.hash x)
260     | IConstant (x,y) -> 11 + 17 * (Id.hash x) + 257 * (Types.hash_const y)
261     and hash_slot s =
262     if s.gen1 = !gen then 13 * s.rank1
263     else (
264     incr rank;
265     s.rank1 <- !rank; s.gen1 <- !gen;
266     hash_descr (descr s)
267     )
268    
269     let rec equal_descr d1 d2 =
270     match (d1,d2) with
271     | IType x1, IType x2 -> Types.equal_descr x1 x2
272     | IOr (x1,y1), IOr (x2,y2)
273     | IAnd (x1,y1), IAnd (x2,y2)
274     | IDiff (x1,y1), IDiff (x2,y2) -> (equal_descr x1 x2) && (equal_descr y1 y2)
275     | IOptional x1, IOptional x2 -> equal_descr x1 x2
276     | ITimes (x1,y1), ITimes (x2,y2)
277     | IXml (x1,y1), IXml (x2,y2)
278     | IArrow (x1,y1), IArrow (x2,y2) -> (equal_slot x1 x2) && (equal_slot y1 y2)
279 abate 426 | IRecord (o1,r1), IRecord (o2,r2) ->
280     (o1 = o2) && (LabelMap.equal equal_slot r1 r2)
281 abate 277 | ICapture x1, ICapture x2 -> Id.equal x1 x2
282 abate 426 | IConstant (x1,y1), IConstant (x2,y2) ->
283     (Id.equal x1 x2) && (Types.equal_const y1 y2)
284 abate 277 | _ -> false
285     and equal_slot s1 s2 =
286     ((s1.gen1 = !gen) && (s2.gen2 = !gen) && (s1.rank1 = s2.rank2))
287     ||
288     ((s1.gen1 <> !gen) && (s2.gen2 <> !gen) && (
289     incr rank;
290     s1.rank1 <- !rank; s1.gen1 <- !gen;
291     s2.rank2 <- !rank; s2.gen2 <- !gen;
292     equal_descr (descr s1) (descr s2)
293     ))
294    
295     module Arg = struct
296     type t = slot
297    
298     let hash s =
299     match s.hash with
300     | Some h -> h
301     | None ->
302     incr gen; rank := 0;
303     let h = hash_slot s in
304     s.hash <- Some h;
305     h
306    
307 abate 278 let equal s1 s2 =
308     (s1 == s2) ||
309     (incr gen; rank := 0;
310     let e = equal_slot s1 s2 in
311 abate 355 (* if e then Printf.eprintf "Recursive hash-consig: Equal\n"; *)
312 abate 278 e)
313 abate 277 end
314     module SlotTable = Hashtbl.Make(Arg)
315    
316     let rec fv_slot s =
317     match s.fv with
318     | Some x -> x
319     | None ->
320     if s.gen1 = !gen then IdSet.empty
321     else (s.gen1 <- !gen; fv_descr (descr s))
322     and fv_descr = function
323 abate 278 | IType _ -> IdSet.empty
324 abate 277 | IOr (d1,d2)
325     | IAnd (d1,d2)
326     | IDiff (d1,d2) -> IdSet.cup (fv_descr d1) (fv_descr d2)
327     | IOptional d -> fv_descr d
328     | ITimes (s1,s2)
329     | IXml (s1,s2)
330     | IArrow (s1,s2) -> IdSet.cup (fv_slot s1) (fv_slot s2)
331 abate 426 | IRecord (o,r) ->
332     List.fold_left IdSet.cup IdSet.empty (LabelMap.map_to_list fv_slot r)
333 abate 277 | ICapture x | IConstant (x,_) -> IdSet.singleton x
334 abate 278
335 abate 277
336     let compute_fv s =
337     match s.fv with
338     | Some x -> ()
339     | None ->
340     incr gen;
341     let x = fv_slot s in
342     s.fv <- Some x
343    
344 abate 278
345     let todo_fv = ref []
346 abate 277
347     let mk () =
348     let s =
349     { d = None;
350     fv = None;
351     hash = None;
352     rank1 = 0; rank2 = 0;
353     gen1 = 0; gen2 = 0 } in
354 abate 278 todo_fv := s :: !todo_fv;
355 abate 277 s
356 abate 278
357     let flush_fv () =
358     List.iter compute_fv !todo_fv;
359     todo_fv := []
360 abate 277
361 abate 278 let compile_slot_hash = DerecursTable.create 67
362     let compile_hash = DerecursTable.create 67
363    
364 abate 277 let defs = ref []
365 abate 278
366     let rec compile p =
367     try DerecursTable.find compile_hash p
368 abate 277 with Not_found ->
369 abate 278 let c = real_compile p in
370     DerecursTable.replace compile_hash p c;
371     c
372     and real_compile = function
373     | PAlias v ->
374     if v.ploop then
375     raise_loc_generic v.ploc ("Unguarded recursion on type/pattern");
376     v.ploop <- true;
377     let r = match v.pdescr with Some x -> compile x | _ -> assert false in
378     v.ploop <- false;
379     r
380     | PType t -> IType t
381     | POr (t1,t2) -> IOr (compile t1, compile t2)
382     | PAnd (t1,t2) -> IAnd (compile t1, compile t2)
383     | PDiff (t1,t2) -> IDiff (compile t1, compile t2)
384     | PTimes (t1,t2) -> ITimes (compile_slot t1, compile_slot t2)
385     | PXml (t1,t2) -> IXml (compile_slot t1, compile_slot t2)
386     | PArrow (t1,t2) -> IArrow (compile_slot t1, compile_slot t2)
387     | POptional t -> IOptional (compile t)
388     | PRecord (o,r) -> IRecord (o, LabelMap.map compile_slot r)
389     | PConstant (x,v) -> IConstant (x,v)
390     | PCapture x -> ICapture x
391     | PRegexp (r,q) -> compile_regexp r q
392     and compile_regexp r q =
393     let memo = RE.create 17 in
394     let rec aux accu r q =
395     if RE.mem memo (r,q) then accu
396     else (
397     RE.add memo (r,q) ();
398     match r with
399 abate 426 | PEpsilon ->
400     (match q with
401     | PRegexp (r,q) -> aux accu r q
402     | _ -> (compile q) :: accu)
403 abate 278 | PElem p -> ITimes (compile_slot p, compile_slot q) :: accu
404     | PSeq (r1,r2) -> aux accu r1 (PRegexp (r2,q))
405     | PAlt (r1,r2) -> aux (aux accu r1 q) r2 q
406     | PStar r1 -> aux (aux accu r1 (PRegexp (r,q))) PEpsilon q
407     | PWeakStar r1 -> aux (aux accu PEpsilon q) r1 (PRegexp (r,q))
408     )
409     in
410     let accu = aux [] r q in
411     match accu with
412     | [] -> assert false
413     | p::l -> List.fold_left (fun acc p -> IOr (p,acc)) p l
414     and compile_slot p =
415     try DerecursTable.find compile_slot_hash p
416     with Not_found ->
417 abate 277 let s = mk () in
418 abate 278 defs := (s,p) :: !defs;
419     DerecursTable.add compile_slot_hash p s;
420 abate 277 s
421 abate 278
422 abate 277
423     let rec flush_defs () =
424     match !defs with
425     | [] -> ()
426 abate 278 | (s,p)::t -> defs := t; s.d <- Some (compile p); flush_defs ()
427 abate 277
428     let typ_nodes = SlotTable.create 67
429     let pat_nodes = SlotTable.create 67
430    
431     let rec typ = function
432     | IType t -> t
433     | IOr (s1,s2) -> Types.cup (typ s1) (typ s2)
434     | IAnd (s1,s2) -> Types.cap (typ s1) (typ s2)
435     | IDiff (s1,s2) -> Types.diff (typ s1) (typ s2)
436     | ITimes (s1,s2) -> Types.times (typ_node s1) (typ_node s2)
437     | IXml (s1,s2) -> Types.xml (typ_node s1) (typ_node s2)
438     | IArrow (s1,s2) -> Types.arrow (typ_node s1) (typ_node s2)
439     | IOptional s -> Types.Record.or_absent (typ s)
440     | IRecord (o,r) -> Types.record' (o, LabelMap.map typ_node r)
441     | ICapture x | IConstant (x,_) -> assert false
442    
443     and typ_node s : Types.node =
444     try SlotTable.find typ_nodes s
445     with Not_found ->
446     let x = Types.make () in
447     SlotTable.add typ_nodes s x;
448     Types.define x (typ (descr s));
449     x
450    
451     let rec pat d : Patterns.descr =
452     if IdSet.is_empty (fv_descr d)
453     then Patterns.constr (typ d)
454     else pat_aux d
455    
456    
457     and pat_aux = function
458     | IOr (s1,s2) -> Patterns.cup (pat s1) (pat s2)
459     | IAnd (s1,s2) -> Patterns.cap (pat s1) (pat s2)
460     | IDiff (s1,s2) when IdSet.is_empty (fv_descr s2) ->
461     let s2 = Types.neg (typ s2) in
462     Patterns.cap (pat s1) (Patterns.constr s2)
463     | IDiff _ ->
464     raise (Patterns.Error "Difference not allowed in patterns")
465     | ITimes (s1,s2) -> Patterns.times (pat_node s1) (pat_node s2)
466     | IXml (s1,s2) -> Patterns.xml (pat_node s1) (pat_node s2)
467     | IOptional _ ->
468     raise (Patterns.Error "Optional field not allowed in record patterns")
469     | IRecord (o,r) ->
470     let pats = ref [] in
471     let aux l s =
472     if IdSet.is_empty (fv_slot s) then typ_node s
473     else
474     ( pats := Patterns.record l (pat_node s) :: !pats;
475     Types.any_node )
476     in
477     let constr = Types.record' (o,LabelMap.mapi aux r) in
478     List.fold_left Patterns.cap (Patterns.constr constr) !pats
479     (* TODO: can avoid constr when o=true, and all fields have fv *)
480     | ICapture x -> Patterns.capture x
481     | IConstant (x,c) -> Patterns.constant x c
482     | IArrow _ ->
483     raise (Patterns.Error "Arrow not allowed in patterns")
484     | IType _ -> assert false
485    
486     and pat_node s : Patterns.node =
487     try SlotTable.find pat_nodes s
488     with Not_found ->
489     let x = Patterns.make (fv_slot s) in
490     SlotTable.add pat_nodes s x;
491     Patterns.define x (pat (descr s));
492     x
493    
494     let glb = State.ref "Typer.glb_env" TypeEnv.empty
495    
496    
497     let register_global_types b =
498 abate 278 List.iter
499     (fun (v,p) ->
500     if TypeEnv.mem v !glb
501     then raise_loc_generic p.loc ("Multiple definition for type " ^ v)
502     ) b;
503     glb := derecurs_def !glb b;
504     let b = List.map (fun (v,p) -> (v,p,compile (derecurs !glb p))) b in
505 abate 277 flush_defs ();
506     flush_fv ();
507 abate 320 List.iter
508     (fun (v,p,s) ->
509     if not (IdSet.is_empty (fv_descr s)) then
510     raise_loc_generic p.loc "Capture variables are not allowed in types";
511     let t = typ s in
512     if (p.loc <> noloc) && (Types.is_empty t) then
513 abate 330 warning p.loc ("This definition yields an empty type for " ^ v);
514 abate 320 Types.Print.register_global v t) b
515 abate 278
516     let dump_global_types ppf =
517     TypeEnv.iter (fun v _ -> Format.fprintf ppf " %s" v) !glb
518 abate 277
519    
520     let typ p =
521 abate 278 let s = compile_slot (derecurs !glb p) in
522 abate 277 flush_defs ();
523     flush_fv ();
524     if IdSet.is_empty (fv_slot s) then typ_node s
525     else raise_loc_generic p.loc "Capture variables are not allowed in types"
526    
527     let pat p =
528 abate 278 let s = compile_slot (derecurs !glb p) in
529 abate 277 flush_defs ();
530     flush_fv ();
531     try pat_node s
532     with Patterns.Error e -> raise_loc_generic p.loc e
533     | Location (loc,exn) when loc = noloc -> raise (Location (p.loc, exn))
534 abate 5
535    
536     (* II. Build skeleton *)
537    
538 abate 225 module Fv = IdSet
539 abate 6
540 abate 427 type branch = Branch of Typed.branch * branch list
541 abate 314
542 abate 427 let cur_branch : branch list ref = ref []
543    
544 abate 316 let exp loc fv e =
545 abate 6 fv,
546     { Typed.exp_loc = loc;
547 abate 5 Typed.exp_typ = Types.empty;
548 abate 316 Typed.exp_descr = e;
549 abate 5 }
550 abate 316
551    
552     let rec expr loc = function
553     | LocatedExpr (loc,e) -> expr loc e
554     | Forget (e,t) ->
555     let (fv,e) = expr loc e and t = typ t in
556     exp loc fv (Typed.Forget (e,t))
557     | Var s ->
558     exp loc (Fv.singleton s) (Typed.Var s)
559     | Apply (e1,e2) ->
560     let (fv1,e1) = expr loc e1 and (fv2,e2) = expr loc e2 in
561     exp loc (Fv.cup fv1 fv2) (Typed.Apply (e1,e2))
562     | Abstraction a ->
563     let iface = List.map (fun (t1,t2) -> (typ t1, typ t2))
564     a.fun_iface in
565     let t = List.fold_left
566     (fun accu (t1,t2) -> Types.cap accu (Types.arrow t1 t2))
567     Types.any iface in
568     let iface = List.map
569     (fun (t1,t2) -> (Types.descr t1, Types.descr t2))
570     iface in
571     let (fv0,body) = branches a.fun_body in
572     let fv = match a.fun_name with
573     | None -> fv0
574     | Some f -> Fv.remove f fv0 in
575     let e = Typed.Abstraction
576     { Typed.fun_name = a.fun_name;
577     Typed.fun_iface = iface;
578     Typed.fun_body = body;
579     Typed.fun_typ = t;
580     Typed.fun_fv = fv
581     } in
582     exp loc fv e
583     | Cst c ->
584     exp loc Fv.empty (Typed.Cst c)
585     | Pair (e1,e2) ->
586     let (fv1,e1) = expr loc e1 and (fv2,e2) = expr loc e2 in
587     exp loc (Fv.cup fv1 fv2) (Typed.Pair (e1,e2))
588     | Xml (e1,e2) ->
589     let (fv1,e1) = expr loc e1 and (fv2,e2) = expr loc e2 in
590     exp loc (Fv.cup fv1 fv2) (Typed.Xml (e1,e2))
591     | Dot (e,l) ->
592     let (fv,e) = expr loc e in
593     exp loc fv (Typed.Dot (e,l))
594     | RemoveField (e,l) ->
595     let (fv,e) = expr loc e in
596     exp loc fv (Typed.RemoveField (e,l))
597     | RecordLitt r ->
598     let fv = ref Fv.empty in
599     let r = LabelMap.map
600     (fun e ->
601     let (fv2,e) = expr loc e
602     in fv := Fv.cup !fv fv2; e)
603     r in
604     exp loc !fv (Typed.RecordLitt r)
605     | Op (op,le) ->
606     let (fvs,ltes) = List.split (List.map (expr loc) le) in
607     let fv = List.fold_left Fv.cup Fv.empty fvs in
608 abate 421 (try
609     (match (ltes,Typed.find_op op) with
610     | [e], `Unary op -> exp loc fv (Typed.UnaryOp (op, e))
611     | [e1;e2], `Binary op -> exp loc fv (Typed.BinaryOp (op, e1,e2))
612     | _ -> assert false)
613     with Not_found -> assert false)
614    
615 abate 316 | Match (e,b) ->
616     let (fv1,e) = expr loc e
617     and (fv2,b) = branches b in
618     exp loc (Fv.cup fv1 fv2) (Typed.Match (e, b))
619 abate 421 | Map (e,b) ->
620 abate 316 let (fv1,e) = expr loc e
621     and (fv2,b) = branches b in
622 abate 421 exp loc (Fv.cup fv1 fv2) (Typed.Map (e, b))
623     | Transform (e,b) ->
624     let (fv1,e) = expr loc e
625     and (fv2,b) = branches b in
626     exp loc (Fv.cup fv1 fv2) (Typed.Transform (e, b))
627 abate 331 | Xtrans (e,b) ->
628 abate 316 let (fv1,e) = expr loc e
629     and (fv2,b) = branches b in
630 abate 331 exp loc (Fv.cup fv1 fv2) (Typed.Xtrans (e, b))
631 abate 316 | Try (e,b) ->
632     let (fv1,e) = expr loc e
633     and (fv2,b) = branches b in
634     exp loc (Fv.cup fv1 fv2) (Typed.Try (e, b))
635    
636 abate 5
637 abate 316 and branches b =
638 abate 6 let fv = ref Fv.empty in
639 abate 19 let accept = ref Types.empty in
640 abate 314 let branch (p,e) =
641 abate 427 let cur_br = !cur_branch in
642     cur_branch := [];
643 abate 316 let (fv2,e) = expr noloc e in
644     let br_loc = merge_loc p.loc e.Typed.exp_loc in
645 abate 314 let p = pat p in
646     let fv2 = Fv.diff fv2 (Patterns.fv p) in
647     fv := Fv.cup !fv fv2;
648     accept := Types.cup !accept (Types.descr (Patterns.accept p));
649     let br =
650     {
651     Typed.br_loc = br_loc;
652     Typed.br_used = br_loc = noloc;
653     Typed.br_pat = p;
654     Typed.br_body = e } in
655 abate 427 cur_branch := Branch (br, !cur_branch) :: cur_br;
656 abate 314 br in
657     let b = List.map branch b in
658 abate 19 (!fv,
659     {
660     Typed.br_typ = Types.empty;
661     Typed.br_branches = b;
662 abate 45 Typed.br_accept = !accept;
663     Typed.br_compiled = None;
664 abate 19 }
665     )
666 abate 5
667 abate 122 let expr = expr noloc
668    
669 abate 277 let let_decl p e =
670     let (_,e) = expr e in
671     { Typed.let_pat = pat p;
672 abate 66 Typed.let_body = e;
673     Typed.let_compiled = None }
674    
675     (* III. Type-checks *)
676    
677     type env = Types.descr Env.t
678 abate 6
679     open Typed
680    
681 abate 421 let require loc t s =
682     if not (Types.subtype t s) then raise_loc loc (Constraint (t, s))
683 abate 17
684 abate 421 let check loc t s =
685     require loc t s; t
686 abate 17
687 abate 421 let should_have loc constr s =
688     raise_loc loc (ShouldHave (constr,s))
689    
690     let flatten loc arg constr precise =
691     let constr' = Sequence.star
692     (Sequence.approx (Types.cap Sequence.any constr)) in
693     let sconstr' = Sequence.star constr' in
694     let exact = Types.subtype constr' constr in
695     if exact then
696     let t = arg sconstr' precise in
697     if precise then Sequence.flatten t else constr
698     else
699     let t = arg sconstr' true in
700     Sequence.flatten t
701    
702 abate 19 let rec type_check env e constr precise =
703     let d = type_check' e.exp_loc env e.exp_descr constr precise in
704 abate 421 let d = if precise then d else constr in
705 abate 6 e.exp_typ <- Types.cup e.exp_typ d;
706     d
707    
708 abate 19 and type_check' loc env e constr precise = match e with
709 abate 54 | Forget (e,t) ->
710     let t = Types.descr t in
711     ignore (type_check env e t false);
712 abate 421 check loc t constr
713    
714 abate 19 | Abstraction a ->
715     let t =
716     try Types.Arrow.check_strenghten a.fun_typ constr
717     with Not_found ->
718 abate 421 should_have loc constr
719     "but the interface of the abstraction is not compatible"
720 abate 19 in
721     let env = match a.fun_name with
722     | None -> env
723     | Some f -> Env.add f a.fun_typ env in
724     List.iter
725     (fun (t1,t2) ->
726 abate 374 let acc = a.fun_body.br_accept in
727     if not (Types.subtype t1 acc) then
728     raise_loc loc (NonExhaustive (Types.diff t1 acc));
729 abate 65 ignore (type_check_branches loc env t1 a.fun_body t2 false)
730 abate 19 ) a.fun_iface;
731     t
732 abate 64
733 abate 19 | Match (e,b) ->
734     let t = type_check env e b.br_accept true in
735 abate 65 type_check_branches loc env t b constr precise
736 abate 30
737 abate 64 | Try (e,b) ->
738     let te = type_check env e constr precise in
739 abate 65 let tb = type_check_branches loc env Types.any b constr precise in
740 abate 64 Types.cup te tb
741    
742 abate 110 | Pair (e1,e2) ->
743     type_check_pair loc env e1 e2 constr precise
744 abate 421
745 abate 110 | Xml (e1,e2) ->
746     type_check_pair ~kind:`XML loc env e1 e2 constr precise
747 abate 159
748 abate 29 | RecordLitt r ->
749 abate 421 type_record loc env r constr precise
750 abate 31
751 abate 421 | Map (e,b) ->
752     type_map loc env false e b constr precise
753    
754     | Transform (e,b) ->
755     flatten loc (type_map loc env true e b) constr precise
756    
757 abate 86 | Apply (e1,e2) ->
758     let t1 = type_check env e1 Types.Arrow.any true in
759     let t1 = Types.Arrow.get t1 in
760     let dom = Types.Arrow.domain t1 in
761 abate 110 let res =
762     if Types.Arrow.need_arg t1 then
763     let t2 = type_check env e2 dom true in
764     Types.Arrow.apply t1 t2
765     else
766     (ignore (type_check env e2 dom false); Types.Arrow.apply_noarg t1)
767     in
768 abate 421 check loc res constr
769 abate 19
770 abate 421 | UnaryOp (o,e) ->
771 abate 426 let t = o.un_op_typer loc
772     (type_check env e) constr precise in
773 abate 421 check loc t constr
774    
775     | BinaryOp (o,e1,e2) ->
776 abate 426 let t = o.bin_op_typer loc
777     (type_check env e1)
778     (type_check env e2) constr precise in
779 abate 421 check loc t constr
780    
781     | Var s ->
782     let t =
783     try Env.find s env
784     with Not_found -> raise_loc loc (UnboundId s) in
785     check loc t constr
786    
787     | Cst c ->
788     check loc (Types.constant c) constr
789    
790     | Dot (e,l) ->
791     let t = type_check env e Types.Record.any true in
792     let t =
793     try (Types.Record.project t l)
794     with Not_found -> raise_loc loc (WrongLabel(t,l))
795     in
796     check loc t constr
797    
798     | RemoveField (e,l) ->
799     let t = type_check env e Types.Record.any true in
800     let t = Types.Record.remove_field t l in
801     check loc t constr
802    
803     | Xtrans (e,b) ->
804     let t = type_check env e Sequence.any true in
805     let t =
806     Sequence.map_tree
807     (fun t ->
808     let resid = Types.diff t b.br_accept in
809     let res = type_check_branches loc env t b Sequence.any true in
810     (res,resid)
811     ) t in
812     check loc t constr
813    
814    
815 abate 110 and type_check_pair ?(kind=`Normal) loc env e1 e2 constr precise =
816 abate 361 let rects = Types.Product.normal ~kind constr in
817 abate 110 if Types.Product.is_empty rects then
818     (match kind with
819 abate 421 | `Normal -> should_have loc constr "but it is a pair"
820     | `XML -> should_have loc constr "but it is an XML element");
821 abate 334 let need_s = Types.Product.need_second rects in
822 abate 355 let t1 = type_check env e1 (Types.Product.pi1 rects) (precise || need_s) in
823     let c2 = Types.Product.constraint_on_2 rects t1 in
824     if Types.is_empty c2 then
825     raise_loc loc (ShouldHave2 (constr,"but the first component has type",t1));
826     let t2 = type_check env e2 c2 precise in
827 abate 334
828 abate 110 if precise then
829 abate 355 match kind with
830     | `Normal -> Types.times (Types.cons t1) (Types.cons t2)
831     | `XML -> Types.xml (Types.cons t1) (Types.cons t2)
832 abate 110 else
833     constr
834    
835 abate 421 and type_record loc env r constr precise =
836     (* try to get rid of precise = true for values of fields *)
837     (* also: the use equivalent of need_second to optimize... *)
838     if not (Types.Record.has_record constr) then
839     should_have loc constr "but it is a record";
840     let (rconstr,res) =
841     List.fold_left
842     (fun (rconstr,res) (l,e) ->
843     (* could compute (split l e) once... *)
844     let pi = Types.Record.project_opt rconstr l in
845     if Types.is_empty pi then
846     (let l = U.to_string (LabelPool.value l) in
847     should_have loc constr
848     (Printf.sprintf "Field %s is not allowed here." l));
849     let t = type_check env e pi true in
850     let rconstr = Types.Record.condition rconstr l t in
851     let res = (l,Types.cons t) :: res in
852     (rconstr,res)
853     ) (constr, []) (LabelMap.get r)
854     in
855     if not (Types.Record.has_empty_record rconstr) then
856     should_have loc constr "More fields should be present";
857     let t =
858     Types.record' (false, LabelMap.from_list (fun _ _ -> assert false) res)
859     in
860     check loc t constr
861 abate 110
862 abate 19
863 abate 65 and type_check_branches loc env targ brs constr precise =
864 abate 374 if Types.is_empty targ then Types.empty
865 abate 9 else (
866     brs.br_typ <- Types.cup brs.br_typ targ;
867 abate 65 branches_aux loc env targ
868 abate 19 (if precise then Types.empty else constr)
869     constr precise brs.br_branches
870 abate 9 )
871 abate 6
872 abate 65 and branches_aux loc env targ tres constr precise = function
873 abate 374 | [] -> tres
874 abate 6 | b :: rem ->
875     let p = b.br_pat in
876     let acc = Types.descr (Patterns.accept p) in
877    
878     let targ' = Types.cap targ acc in
879     if Types.is_empty targ'
880 abate 65 then branches_aux loc env targ tres constr precise rem
881 abate 6 else
882     ( b.br_used <- true;
883     let res = Patterns.filter targ' p in
884     let env' = List.fold_left
885     (fun env (x,t) -> Env.add x (Types.descr t) env)
886     env res in
887 abate 19 let t = type_check env' b.br_body constr precise in
888     let tres = if precise then Types.cup t tres else tres in
889 abate 9 let targ'' = Types.diff targ acc in
890     if (Types.non_empty targ'') then
891 abate 65 branches_aux loc env targ'' tres constr precise rem
892 abate 9 else
893     tres
894 abate 6 )
895 abate 16
896 abate 421 and type_map loc env def e b constr precise =
897     let acc = if def then Sequence.any else Sequence.star b.br_accept in
898     let t = type_check env e acc true in
899    
900     let constr' = Sequence.approx (Types.cap Sequence.any constr) in
901     let exact = Types.subtype (Sequence.star constr') constr in
902     (* Note:
903     - could be more precise by integrating the decomposition
904     of constr inside Sequence.map.
905     *)
906     let res =
907     Sequence.map
908     (fun t ->
909     let res =
910     type_check_branches loc env t b constr' (precise || (not exact)) in
911     if def && not (Types.subtype t b.br_accept)
912     then Types.cup res Sequence.nil_type
913     else res)
914     t in
915     if exact then res else check loc res constr
916    
917 abate 66 and type_let_decl env l =
918     let acc = Types.descr (Patterns.accept l.let_pat) in
919     let t = type_check env l.let_body acc true in
920     let res = Patterns.filter t l.let_pat in
921     List.map (fun (x,t) -> (x, Types.descr t)) res
922    
923     and type_rec_funs env l =
924     let types =
925     List.fold_left
926     (fun accu -> function {let_body={exp_descr=Abstraction a}} as l ->
927     let t = a.fun_typ in
928     let acc = Types.descr (Patterns.accept l.let_pat) in
929     if not (Types.subtype t acc) then
930     raise_loc l.let_body.exp_loc (NonExhaustive (Types.diff t acc));
931     let res = Patterns.filter t l.let_pat in
932     List.fold_left (fun accu (x,t) -> (x, Types.descr t)::accu) accu res
933     | _ -> assert false) [] l
934     in
935     let env' = List.fold_left (fun env (x,t) -> Env.add x t env) env types in
936     List.iter
937     (function { let_body = { exp_descr = Abstraction a } } as l ->
938     ignore (type_check env' l.let_body Types.any false)
939     | _ -> assert false) l;
940     types
941    
942 abate 427
943     let rec unused_branches b =
944 abate 314 List.iter
945 abate 427 (fun (Branch (br,s)) ->
946     if not br.br_used
947     then warning br.br_loc "This branch is not used"
948     else unused_branches s
949     )
950     b
951 abate 314
952 abate 427 let report_unused_branches () =
953     unused_branches !cur_branch;
954     cur_branch := []
955    

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