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

Contents of /typing/typer.ml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 421 - (hide annotations)
Tue Jul 10 17:33:25 2007 UTC (5 years, 10 months ago) by abate
File size: 28547 byte(s)
[r2003-05-25 10:34:50 by cvscast] review Builtin

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

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