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

Contents of /typing/typer.ml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 110 - (hide annotations)
Tue Jul 10 17:07:14 2007 UTC (5 years, 10 months ago) by abate
File size: 24388 byte(s)
[r2002-11-10 22:26:37 by cvscast] Passage au type XML

Original author: cvscast
Date: 2002-11-10 22:26:39+00:00
1 abate 5 (* I. Transform the abstract syntax of types and patterns into
2     the internal form *)
3    
4     open Location
5     open Ast
6    
7 abate 9 exception NonExhaustive of Types.descr
8 abate 28 exception MultipleLabel of Types.label
9 abate 9 exception Constraint of Types.descr * Types.descr * string
10 abate 19 exception ShouldHave of Types.descr * string
11 abate 26 exception WrongLabel of Types.descr * Types.label
12 abate 36 exception UnboundId of string
13 abate 5
14 abate 9 let raise_loc loc exn = raise (Location (loc,exn))
15    
16 abate 5 (* Internal representation as a graph (desugar recursive types and regexp),
17     to compute freevars, etc... *)
18    
19 abate 9 type ti = {
20 abate 5 id : int;
21     mutable loc' : loc;
22     mutable fv : string SortedList.t option;
23     mutable descr': descr;
24     mutable type_node: Types.node option;
25     mutable pat_node: Patterns.node option
26     }
27     and descr =
28 abate 9 [ `Alias of string * ti
29 abate 5 | `Type of Types.descr
30     | `Or of ti * ti
31 abate 54 | `And of ti * ti * bool
32 abate 5 | `Diff of ti * ti
33     | `Times of ti * ti
34 abate 110 | `Xml of ti * ti
35 abate 5 | `Arrow of ti * ti
36     | `Record of Types.label * bool * ti
37     | `Capture of Patterns.capture
38     | `Constant of Patterns.capture * Types.const
39     ]
40    
41    
42    
43     module S = struct type t = string let compare = compare end
44     module StringMap = Map.Make(S)
45     module StringSet = Set.Make(S)
46    
47 abate 107 type glb = ti StringMap.t
48    
49 abate 5 let mk' =
50     let counter = ref 0 in
51 abate 13 fun loc ->
52 abate 5 incr counter;
53 abate 9 let rec x = {
54     id = !counter;
55 abate 13 loc' = loc;
56 abate 9 fv = None;
57     descr' = `Alias ("__dummy__", x);
58     type_node = None;
59     pat_node = None
60     } in
61 abate 5 x
62    
63     let cons loc d =
64 abate 13 let x = mk' loc in
65 abate 5 x.descr' <- d;
66     x
67    
68     (* Note:
69     Compilation of Regexp is implemented as a ``rewriting'' of
70     the parsed syntax, in order to be able to print its result
71     (for debugging for instance)
72    
73     It would be possible (and a little more efficient) to produce
74     directly ti nodes.
75     *)
76    
77     module Regexp = struct
78     let defs = ref []
79     let name =
80     let c = ref 0 in
81     fun () ->
82     incr c;
83     "#" ^ (string_of_int !c)
84    
85     let rec seq_vars accu = function
86     | Epsilon | Elem _ -> accu
87     | Seq (r1,r2) | Alt (r1,r2) -> seq_vars (seq_vars accu r1) r2
88     | Star r | WeakStar r -> seq_vars accu r
89     | SeqCapture (v,r) -> seq_vars (StringSet.add v accu) r
90    
91 abate 71 let uniq_id = let r = ref 0 in fun () -> incr r; !r
92    
93     type flat = [ `Epsilon
94     | `Elem of int * Ast.ppat (* the int arg is used to
95     to stop generic comparison *)
96     | `Seq of flat * flat
97     | `Alt of flat * flat
98     | `Star of flat
99     | `WeakStar of flat ]
100    
101 abate 107 let re_loc = ref noloc
102    
103 abate 71 let rec propagate vars : regexp -> flat = function
104 abate 5 | Epsilon -> `Epsilon
105 abate 71 | Elem x -> let p = vars x in `Elem (uniq_id (),p)
106 abate 5 | Seq (r1,r2) -> `Seq (propagate vars r1,propagate vars r2)
107     | Alt (r1,r2) -> `Alt (propagate vars r1, propagate vars r2)
108     | Star r -> `Star (propagate vars r)
109     | WeakStar r -> `WeakStar (propagate vars r)
110 abate 71 | SeqCapture (v,x) ->
111 abate 107 let v= mk !re_loc (Capture v) in
112     propagate (fun p -> mk !re_loc (And (vars p,v,true))) x
113 abate 5
114     let cup r1 r2 =
115     match (r1,r2) with
116     | (_, `Empty) -> r1
117     | (`Empty, _) -> r2
118 abate 107 | (`Res t1, `Res t2) -> `Res (mk !re_loc (Or (t1,t2)))
119 abate 5
120 abate 71 (*TODO: review this compilation schema to avoid explosion when
121     coding (Optional x) by (Or(Epsilon,x)); memoization ... *)
122    
123     module Memo = Map.Make(struct type t = flat list let compare = compare end)
124     module Coind = Set.Make(struct type t = flat list let compare = compare end)
125     let memo = ref Memo.empty
126    
127 abate 5 let rec compile fin e seq : [`Res of Ast.ppat | `Empty] =
128 abate 71 if Coind.mem seq !e then `Empty
129     else (
130     e := Coind.add seq !e;
131 abate 5 match seq with
132     | [] ->
133     `Res fin
134     | `Epsilon :: rest ->
135     compile fin e rest
136 abate 71 | `Elem (_,p) :: rest ->
137 abate 107 `Res (mk !re_loc (Prod (p, guard_compile fin rest)))
138 abate 5 | `Seq (r1,r2) :: rest ->
139     compile fin e (r1 :: r2 :: rest)
140     | `Alt (r1,r2) :: rest ->
141     cup (compile fin e (r1::rest)) (compile fin e (r2::rest))
142 abate 71 | `Star r :: rest ->
143     cup (compile fin e (r::seq)) (compile fin e rest)
144     | `WeakStar r :: rest ->
145     cup (compile fin e rest) (compile fin e (r::seq))
146     )
147 abate 5 and guard_compile fin seq =
148 abate 71 try Memo.find seq !memo
149 abate 5 with
150     Not_found ->
151     let n = name () in
152 abate 107 let v = mk !re_loc (PatVar n) in
153 abate 71 memo := Memo.add seq v !memo;
154     let d = compile fin (ref Coind.empty) seq in
155 abate 5 (match d with
156     | `Empty -> assert false
157     | `Res d -> defs := (n,d) :: !defs);
158     v
159    
160    
161     let constant_nil v t =
162 abate 107 mk !re_loc
163     (And (t,
164     (mk !re_loc (Constant (v, Types.Atom Sequence.nil_atom))), true))
165 abate 5
166 abate 107 let compile loc regexp queue : ppat =
167     re_loc := loc;
168 abate 5 let vars = seq_vars StringSet.empty regexp in
169 abate 107 let fin = StringSet.fold constant_nil vars queue in
170 abate 71 let n = guard_compile fin [propagate (fun p -> p) regexp] in
171     memo := Memo.empty;
172 abate 5 let d = !defs in
173     defs := [];
174 abate 107 mk !re_loc (Recurs (n,d))
175 abate 5 end
176    
177 abate 107 let compile_regexp = Regexp.compile noloc
178 abate 5
179    
180     let rec compile env { loc = loc; descr = d } : ti =
181     match (d : Ast.ppat') with
182     | PatVar s ->
183     (try StringMap.find s env
184 abate 9 with Not_found ->
185 abate 107 raise_loc_generic loc ("Undefined type variable " ^ s)
186 abate 5 )
187 abate 13 | Recurs (t, b) -> compile (compile_many env b) t
188 abate 107 | Regexp (r,q) -> compile env (Regexp.compile loc r q)
189 abate 5 | Internal t -> cons loc (`Type t)
190     | Or (t1,t2) -> cons loc (`Or (compile env t1, compile env t2))
191 abate 54 | And (t1,t2,e) -> cons loc (`And (compile env t1, compile env t2,e))
192 abate 5 | Diff (t1,t2) -> cons loc (`Diff (compile env t1, compile env t2))
193     | Prod (t1,t2) -> cons loc (`Times (compile env t1, compile env t2))
194 abate 110 | XmlT (t1,t2) -> cons loc (`Xml (compile env t1, compile env t2))
195 abate 5 | Arrow (t1,t2) -> cons loc (`Arrow (compile env t1, compile env t2))
196     | Record (l,o,t) -> cons loc (`Record (l,o,compile env t))
197     | Constant (x,v) -> cons loc (`Constant (x,v))
198     | Capture x -> cons loc (`Capture x)
199    
200 abate 13 and compile_many env b =
201     let b = List.map (fun (v,t) -> (v,t,mk' t.loc)) b in
202     let env =
203     List.fold_left (fun env (v,t,x) -> StringMap.add v x env) env b in
204     List.iter (fun (v,t,x) -> x.descr' <- `Alias (v, compile env t)) b;
205     env
206    
207 abate 71 let comp_fv_seen = ref []
208     let comp_fv_res = ref []
209     let rec comp_fv s =
210     if List.memq s !comp_fv_seen then ()
211     else (
212     comp_fv_seen := s :: !comp_fv_seen;
213     (match s.descr' with
214     | `Alias (_,x) -> comp_fv x
215     | `Or (s1,s2)
216     | `And (s1,s2,_)
217     | `Diff (s1,s2)
218 abate 110 | `Times (s1,s2) | `Xml (s1,s2)
219 abate 71 | `Arrow (s1,s2) -> comp_fv s1; comp_fv s2
220     | `Record (l,opt,s) -> comp_fv s
221     | `Type _ -> ()
222     | `Capture x
223     | `Constant (x,_) -> comp_fv_res := x :: !comp_fv_res);
224     if (!comp_fv_res = []) then s.fv <- Some [];
225     (* TODO: check that the above line is correct *)
226     )
227    
228    
229    
230     let fv s =
231 abate 5 match s.fv with
232     | Some l -> l
233 abate 71 | None ->
234     comp_fv s;
235     let l = SortedList.from_list !comp_fv_res in
236     comp_fv_res := [];
237     comp_fv_seen := [];
238     s.fv <- Some l;
239 abate 5 l
240    
241     let rec typ seen s : Types.descr =
242     match s.descr' with
243 abate 9 | `Alias (v,x) ->
244     if List.memq s seen then
245 abate 107 raise_loc_generic s.loc'
246     ("Unguarded recursion on variable " ^ v ^ " in this type")
247 abate 5 else typ (s :: seen) x
248     | `Type t -> t
249     | `Or (s1,s2) -> Types.cup (typ seen s1) (typ seen s2)
250 abate 54 | `And (s1,s2,_) -> Types.cap (typ seen s1) (typ seen s2)
251 abate 5 | `Diff (s1,s2) -> Types.diff (typ seen s1) (typ seen s2)
252     | `Times (s1,s2) -> Types.times (typ_node s1) (typ_node s2)
253 abate 110 | `Xml (s1,s2) -> Types.xml (typ_node s1) (typ_node s2)
254 abate 5 | `Arrow (s1,s2) -> Types.arrow (typ_node s1) (typ_node s2)
255     | `Record (l,o,s) -> Types.record l o (typ_node s)
256 abate 9 | `Capture _ | `Constant _ -> assert false
257 abate 5
258     and typ_node s : Types.node =
259     match s.type_node with
260     | Some x -> x
261     | None ->
262     let x = Types.make () in
263     s.type_node <- Some x;
264     let t = typ [] s in
265     Types.define x t;
266     x
267    
268 abate 71 let type_node s =
269     let s = typ_node s in
270     let s = Types.internalize s in
271     (* Types.define s (Types.normalize (Types.descr s)); *)
272     s
273 abate 5
274     let rec pat seen s : Patterns.descr =
275     if fv s = [] then Patterns.constr (type_node s) else
276 abate 107 try pat_aux seen s
277     with Patterns.Error e -> raise_loc_generic s.loc' e
278     | Location (loc,exn) when loc = noloc -> raise (Location (s.loc', exn))
279 abate 5
280 abate 107
281     and pat_aux seen s = match s.descr' with
282     | `Alias (v,x) ->
283     if List.memq s seen
284     then raise
285     (Patterns.Error
286     ("Unguarded recursion on variable " ^ v ^ " in this pattern"));
287     pat (s :: seen) x
288     | `Or (s1,s2) -> Patterns.cup (pat seen s1) (pat seen s2)
289     | `And (s1,s2,e) -> Patterns.cap (pat seen s1) (pat seen s2) e
290     | `Diff (s1,s2) when fv s2 = [] ->
291     let s2 = Types.cons (Types.neg (Types.descr (type_node s2)))in
292     Patterns.cap (pat seen s1) (Patterns.constr s2) true
293     | `Diff _ ->
294     raise (Patterns.Error "Difference not allowed in patterns")
295     | `Times (s1,s2) -> Patterns.times (pat_node s1) (pat_node s2)
296 abate 110 | `Xml (s1,s2) -> Patterns.xml (pat_node s1) (pat_node s2)
297 abate 107 | `Record (l,false,s) -> Patterns.record l (pat_node s)
298     | `Record _ ->
299     raise (Patterns.Error "Optional field not allowed in record patterns")
300     | `Capture x -> Patterns.capture x
301     | `Constant (x,c) -> Patterns.constant x c
302     | `Arrow _ ->
303     raise (Patterns.Error "Arrow not allowed in patterns")
304     | `Type _ -> assert false
305    
306 abate 5 and pat_node s : Patterns.node =
307     match s.pat_node with
308     | Some x -> x
309     | None ->
310     let x = Patterns.make (fv s) in
311     s.pat_node <- Some x;
312     let t = pat [] s in
313     Patterns.define x t;
314     x
315    
316 abate 13 let mk_typ e =
317 abate 71 if fv e = [] then type_node e
318 abate 107 else raise_loc_generic e.loc' "Capture variables are not allowed in types"
319 abate 13
320 abate 5
321 abate 107 let typ glb e =
322     mk_typ (compile glb e)
323 abate 13
324 abate 107 let pat glb e =
325     pat_node (compile glb e)
326 abate 5
327 abate 107 let register_global_types glb b =
328     let env' = compile_many glb b in
329     List.fold_left
330     (fun glb (v,{ loc = loc }) ->
331     let t = StringMap.find v env' in
332     let d = Types.descr (mk_typ t) in
333     (* let d = Types.normalize d in*)
334     Types.Print.register_global v d;
335     if StringMap.mem v glb
336     then raise_loc_generic loc ("Multiple definition for type " ^ v);
337     StringMap.add v t glb
338     ) glb b
339 abate 5
340    
341 abate 107
342 abate 5 (* II. Build skeleton *)
343    
344 abate 6 module Fv = StringSet
345    
346 abate 107 let rec expr glb { loc = loc; descr = d } =
347 abate 6 let (fv,td) =
348 abate 5 match d with
349 abate 54 | Forget (e,t) ->
350 abate 107 let (fv,e) = expr glb e and t = typ glb t in
351 abate 54 (fv, Typed.Forget (e,t))
352 abate 6 | Var s -> (Fv.singleton s, Typed.Var s)
353     | Apply (e1,e2) ->
354 abate 107 let (fv1,e1) = expr glb e1 and (fv2,e2) = expr glb e2 in
355 abate 6 (Fv.union fv1 fv2, Typed.Apply (e1,e2))
356 abate 5 | Abstraction a ->
357 abate 107 let iface = List.map (fun (t1,t2) -> (typ glb t1, typ glb t2))
358     a.fun_iface in
359 abate 6 let t = List.fold_left
360     (fun accu (t1,t2) -> Types.cap accu (Types.arrow t1 t2))
361     Types.any iface in
362 abate 9 let iface = List.map
363     (fun (t1,t2) -> (Types.descr t1, Types.descr t2))
364     iface in
365 abate 107 let (fv0,body) = branches glb a.fun_body in
366 abate 6 let fv = match a.fun_name with
367     | None -> fv0
368     | Some f -> Fv.remove f fv0 in
369     (fv,
370     Typed.Abstraction
371     { Typed.fun_name = a.fun_name;
372     Typed.fun_iface = iface;
373     Typed.fun_body = body;
374     Typed.fun_typ = t;
375 abate 69 Typed.fun_fv = Fv.elements fv
376 abate 6 }
377     )
378     | Cst c -> (Fv.empty, Typed.Cst c)
379     | Pair (e1,e2) ->
380 abate 107 let (fv1,e1) = expr glb e1 and (fv2,e2) = expr glb e2 in
381 abate 6 (Fv.union fv1 fv2, Typed.Pair (e1,e2))
382 abate 110 | Xml (e1,e2) ->
383     let (fv1,e1) = expr glb e1 and (fv2,e2) = expr glb e2 in
384     (Fv.union fv1 fv2, Typed.Xml (e1,e2))
385 abate 26 | Dot (e,l) ->
386 abate 107 let (fv,e) = expr glb e in
387 abate 27 (fv, Typed.Dot (e,l))
388 abate 6 | RecordLitt r ->
389     let fv = ref Fv.empty in
390 abate 47 let r = List.sort (fun (l1,_) (l2,_) -> compare l1 l2) r in
391 abate 6 let r = List.map
392     (fun (l,e) ->
393 abate 107 let (fv2,e) = expr glb e in fv := Fv.union !fv fv2; (l,e))
394 abate 47 r in
395     let rec check = function
396     | (l1,_) :: (l2,_) :: _ when l1 = l2 ->
397     raise_loc loc (MultipleLabel l1)
398     | _ :: rem -> check rem
399     | _ -> () in
400     check r;
401 abate 6 (!fv, Typed.RecordLitt r)
402 abate 16 | Op (op,le) ->
403 abate 107 let (fvs,ltes) = List.split (List.map (expr glb) le) in
404 abate 16 let fv = List.fold_left Fv.union Fv.empty fvs in
405     (fv, Typed.Op (op,ltes))
406 abate 6 | Match (e,b) ->
407 abate 107 let (fv1,e) = expr glb e
408     and (fv2,b) = branches glb b in
409 abate 6 (Fv.union fv1 fv2, Typed.Match (e, b))
410     | Map (e,b) ->
411 abate 107 let (fv1,e) = expr glb e
412     and (fv2,b) = branches glb b in
413 abate 6 (Fv.union fv1 fv2, Typed.Map (e, b))
414 abate 64 | Try (e,b) ->
415 abate 107 let (fv1,e) = expr glb e
416     and (fv2,b) = branches glb b in
417 abate 64 (Fv.union fv1 fv2, Typed.Try (e, b))
418 abate 5 in
419 abate 6 fv,
420     { Typed.exp_loc = loc;
421 abate 5 Typed.exp_typ = Types.empty;
422     Typed.exp_descr = td;
423     }
424    
425 abate 107 and branches glb b =
426 abate 6 let fv = ref Fv.empty in
427 abate 19 let accept = ref Types.empty in
428 abate 6 let b = List.map
429     (fun (p,e) ->
430 abate 107 let (fv2,e) = expr glb e in
431     let p = pat glb p in
432 abate 69 let fv2 = List.fold_right Fv.remove (Patterns.fv p) fv2 in
433 abate 6 fv := Fv.union !fv fv2;
434 abate 19 accept := Types.cup !accept (Types.descr (Patterns.accept p));
435 abate 6 { Typed.br_used = false;
436 abate 19 Typed.br_pat = p;
437 abate 6 Typed.br_body = e }
438     ) b in
439 abate 19 (!fv,
440     {
441     Typed.br_typ = Types.empty;
442     Typed.br_branches = b;
443 abate 45 Typed.br_accept = !accept;
444     Typed.br_compiled = None;
445 abate 19 }
446     )
447 abate 5
448 abate 107 let let_decl glb p e =
449     let (_,e) = expr glb e in
450     { Typed.let_pat = pat glb p;
451 abate 66 Typed.let_body = e;
452     Typed.let_compiled = None }
453    
454     (* III. Type-checks *)
455    
456 abate 6 module Env = StringMap
457 abate 66 type env = Types.descr Env.t
458 abate 6
459     open Typed
460    
461 abate 66 let warning loc msg =
462     Format.fprintf Format.std_formatter
463     "Warning %a:@\n%s@\n" Location.print_loc loc msg
464 abate 17
465     let check loc t s msg =
466     if not (Types.subtype t s) then raise_loc loc (Constraint (t, s, msg))
467    
468 abate 19 let rec type_check env e constr precise =
469 abate 31 (* Format.fprintf Format.std_formatter "constr=%a precise=%b@\n"
470 abate 37 Types.Print.print_descr constr precise;
471     *)
472 abate 19 let d = type_check' e.exp_loc env e.exp_descr constr precise in
473 abate 6 e.exp_typ <- Types.cup e.exp_typ d;
474     d
475    
476 abate 19 and type_check' loc env e constr precise = match e with
477 abate 54 | Forget (e,t) ->
478     let t = Types.descr t in
479     ignore (type_check env e t false);
480     t
481 abate 19 | Abstraction a ->
482     let t =
483     try Types.Arrow.check_strenghten a.fun_typ constr
484     with Not_found ->
485     raise_loc loc
486     (ShouldHave
487     (constr, "but the interface of the abstraction is not compatible"))
488     in
489     let env = match a.fun_name with
490     | None -> env
491     | Some f -> Env.add f a.fun_typ env in
492     List.iter
493     (fun (t1,t2) ->
494 abate 65 ignore (type_check_branches loc env t1 a.fun_body t2 false)
495 abate 19 ) a.fun_iface;
496     t
497 abate 64
498 abate 19 | Match (e,b) ->
499     let t = type_check env e b.br_accept true in
500 abate 65 type_check_branches loc env t b constr precise
501 abate 30
502 abate 64 | Try (e,b) ->
503     let te = type_check env e constr precise in
504 abate 65 let tb = type_check_branches loc env Types.any b constr precise in
505 abate 64 Types.cup te tb
506    
507 abate 110 | Pair (e1,e2) ->
508     type_check_pair loc env e1 e2 constr precise
509     | Xml (e1,e2) ->
510     type_check_pair ~kind:`XML loc env e1 e2 constr precise
511 abate 29 | RecordLitt r ->
512     let rconstr = Types.Record.get constr in
513     if Types.Record.is_empty rconstr then
514     raise_loc loc (ShouldHave (constr,"but it is a record."));
515    
516     let (rconstr,res) =
517     List.fold_left
518     (fun (rconstr,res) (l,e) ->
519     let rconstr = Types.Record.restrict_label_present rconstr l in
520     let pi = Types.Record.project_field rconstr l in
521     if Types.Record.is_empty rconstr then
522     raise_loc loc
523     (ShouldHave (constr,(Printf.sprintf
524     "Field %s is not allowed here."
525 abate 78 (Types.LabelPool.value l)
526 abate 29 )
527     ));
528     let t = type_check env e pi true in
529     let rconstr = Types.Record.restrict_field rconstr l t in
530    
531     let res =
532     if precise
533     then Types.cap res (Types.record l false (Types.cons t))
534     else res in
535     (rconstr,res)
536     ) (rconstr, if precise then Types.Record.any else constr) r
537     in
538     res
539    
540 abate 31 | Map (e,b) ->
541     let t = type_check env e (Sequence.star b.br_accept) true in
542    
543     let constr' = Sequence.approx (Types.cap Sequence.any constr) in
544     let exact = Types.subtype (Sequence.star constr') constr in
545 abate 54 (* Note:
546     - could be more precise by integrating the decomposition
547     of constr inside Sequence.map.
548     *)
549     let res =
550     Sequence.map
551     (fun t ->
552 abate 65 type_check_branches loc env t b constr' (precise || (not exact)))
553 abate 54 t in
554     if not exact then check loc res constr "";
555     if precise then res else constr
556 abate 31 | Op ("@", [e1;e2]) ->
557     let constr' = Sequence.star
558     (Sequence.approx (Types.cap Sequence.any constr)) in
559     let exact = Types.subtype constr' constr in
560     if exact then
561     let t1 = type_check env e1 constr' precise
562     and t2 = type_check env e2 constr' precise in
563     if precise then Sequence.concat t1 t2 else constr
564     else
565     (* Note:
566     the knownledge of t1 may makes it useless to
567     check t2 with 'precise' ... *)
568     let t1 = type_check env e1 constr' true
569     and t2 = type_check env e2 constr' true in
570     let res = Sequence.concat t1 t2 in
571     check loc res constr "";
572     if precise then res else constr
573 abate 86 | Apply (e1,e2) ->
574 abate 110 (*
575 abate 86 let constr' = Sequence.star
576     (Sequence.approx (Types.cap Sequence.any constr)) in
577     let t1 = type_check env e1 (Types.cup Types.Arrow.any constr') true in
578     let t1_fun = Types.Arrow.get t1 in
579    
580     let has_fun = not (Types.Arrow.is_empty t1_fun)
581     and has_seq = not (Types.subtype t1 Types.Arrow.any) in
582    
583     let constr' =
584     Types.cap
585     (if has_fun then Types.Arrow.domain t1_fun else Types.any)
586     (if has_seq then constr' else Types.any)
587     in
588     let need_arg = has_fun && Types.Arrow.need_arg t1_fun in
589     let precise = need_arg || has_seq in
590     let t2 = type_check env e2 constr' precise in
591     let res = Types.cup
592     (if has_fun then
593     if need_arg then Types.Arrow.apply t1_fun t2
594     else Types.Arrow.apply_noarg t1_fun
595     else Types.empty)
596     (if has_seq then Sequence.concat t1 t2
597     else Types.empty)
598     in
599     check loc res constr "";
600     res
601 abate 110 *)
602 abate 86 let t1 = type_check env e1 Types.Arrow.any true in
603     let t1 = Types.Arrow.get t1 in
604     let dom = Types.Arrow.domain t1 in
605 abate 110 let res =
606     if Types.Arrow.need_arg t1 then
607     let t2 = type_check env e2 dom true in
608     Types.Arrow.apply t1 t2
609     else
610     (ignore (type_check env e2 dom false); Types.Arrow.apply_noarg t1)
611     in
612     check loc res constr "";
613     res
614 abate 32 | Op ("flatten", [e]) ->
615     let constr' = Sequence.star
616     (Sequence.approx (Types.cap Sequence.any constr)) in
617     let sconstr' = Sequence.star constr' in
618     let exact = Types.subtype constr' constr in
619     if exact then
620     let t = type_check env e sconstr' precise in
621     if precise then Sequence.flatten t else constr
622     else
623     let t = type_check env e sconstr' true in
624     let res = Sequence.flatten t in
625     check loc res constr "";
626     if precise then res else constr
627 abate 19 | _ ->
628     let t : Types.descr = compute_type' loc env e in
629     check loc t constr "";
630     t
631    
632 abate 110 and type_check_pair ?(kind=`Normal) loc env e1 e2 constr precise =
633     let rects = Types.Product.get ~kind constr in
634     if Types.Product.is_empty rects then
635     (match kind with
636     | `Normal -> raise_loc loc (ShouldHave (constr,"but it is a pair."))
637     | `XML -> raise_loc loc (ShouldHave (constr,"but it is an XML element.")));
638     let pi1 = Types.Product.pi1 rects in
639    
640     let t1 = type_check env e1 (Types.Product.pi1 rects)
641     (precise || (Types.Product.need_second rects))in
642     let rects = Types.Product.restrict_1 rects t1 in
643     let t2 = type_check env e2 (Types.Product.pi2 rects) precise in
644     if precise then
645     match kind with
646     | `Normal -> Types.times (Types.cons t1) (Types.cons t2)
647     | `XML -> Types.xml (Types.cons t1) (Types.cons t2)
648     else
649     constr
650    
651    
652 abate 19 and compute_type env e =
653     type_check env e Types.any true
654    
655 abate 6 and compute_type' loc env = function
656 abate 36 | Var s ->
657     (try Env.find s env
658     with Not_found -> raise_loc loc (UnboundId s)
659     )
660 abate 6 | Cst c -> Types.constant c
661 abate 26 | Dot (e,l) ->
662     let t = type_check env e Types.Record.any true in
663     (try (Types.Record.project t l)
664     with Not_found -> raise_loc loc (WrongLabel(t,l)))
665 abate 16 | Op (op, el) ->
666     let args = List.map (fun e -> (e.exp_loc, compute_type env e)) el in
667     type_op loc op args
668 abate 17 | Map (e,b) ->
669     let t = compute_type env e in
670 abate 65 Sequence.map (fun t -> type_check_branches loc env t b Types.any true) t
671 abate 30
672     (* We keep these cases here to allow comparison and benchmarking ...
673     Just comment the corresponding cases in type_check' to
674     activate these ones.
675     *)
676     | Pair (e1,e2) ->
677     let t1 = compute_type env e1
678     and t2 = compute_type env e2 in
679     Types.times (Types.cons t1) (Types.cons t2)
680     | RecordLitt r ->
681     List.fold_left
682     (fun accu (l,e) ->
683     let t = compute_type env e in
684     let t = Types.record l false (Types.cons t) in
685     Types.cap accu t
686     ) Types.Record.any r
687    
688    
689 abate 19 | _ -> assert false
690 abate 6
691 abate 65 and type_check_branches loc env targ brs constr precise =
692 abate 6 if Types.is_empty targ then Types.empty
693 abate 9 else (
694     brs.br_typ <- Types.cup brs.br_typ targ;
695 abate 65 branches_aux loc env targ
696 abate 19 (if precise then Types.empty else constr)
697     constr precise brs.br_branches
698 abate 9 )
699 abate 6
700 abate 65 and branches_aux loc env targ tres constr precise = function
701     | [] -> raise_loc loc (NonExhaustive targ)
702 abate 6 | b :: rem ->
703     let p = b.br_pat in
704     let acc = Types.descr (Patterns.accept p) in
705    
706     let targ' = Types.cap targ acc in
707     if Types.is_empty targ'
708 abate 65 then branches_aux loc env targ tres constr precise rem
709 abate 6 else
710     ( b.br_used <- true;
711     let res = Patterns.filter targ' p in
712     let env' = List.fold_left
713     (fun env (x,t) -> Env.add x (Types.descr t) env)
714     env res in
715 abate 19 let t = type_check env' b.br_body constr precise in
716     let tres = if precise then Types.cup t tres else tres in
717 abate 9 let targ'' = Types.diff targ acc in
718     if (Types.non_empty targ'') then
719 abate 65 branches_aux loc env targ'' tres constr precise rem
720 abate 9 else
721     tres
722 abate 6 )
723 abate 16
724 abate 66 and type_let_decl env l =
725     let acc = Types.descr (Patterns.accept l.let_pat) in
726     let t = type_check env l.let_body acc true in
727     let res = Patterns.filter t l.let_pat in
728     List.map (fun (x,t) -> (x, Types.descr t)) res
729    
730     and type_rec_funs env l =
731     let types =
732     List.fold_left
733     (fun accu -> function {let_body={exp_descr=Abstraction a}} as l ->
734     let t = a.fun_typ in
735     let acc = Types.descr (Patterns.accept l.let_pat) in
736     if not (Types.subtype t acc) then
737     raise_loc l.let_body.exp_loc (NonExhaustive (Types.diff t acc));
738     let res = Patterns.filter t l.let_pat in
739     List.fold_left (fun accu (x,t) -> (x, Types.descr t)::accu) accu res
740     | _ -> assert false) [] l
741     in
742     let env' = List.fold_left (fun env (x,t) -> Env.add x t env) env types in
743     List.iter
744     (function { let_body = { exp_descr = Abstraction a } } as l ->
745     ignore (type_check env' l.let_body Types.any false)
746     | _ -> assert false) l;
747     types
748    
749    
750 abate 16 and type_op loc op args =
751     match (op,args) with
752 abate 51 | "+", [loc1,t1; loc2,t2] ->
753 abate 16 type_int_binop Intervals.add loc1 t1 loc2 t2
754 abate 51 | "-", [loc1,t1; loc2,t2] ->
755     type_int_binop Intervals.sub loc1 t1 loc2 t2
756     | ("*" | "/"), [loc1,t1; loc2,t2] ->
757 abate 16 type_int_binop (fun i1 i2 -> Intervals.any) loc1 t1 loc2 t2
758 abate 51 | "@", [loc1,t1; loc2,t2] ->
759 abate 17 check loc1 t1 Sequence.any
760     "The first argument of @ must be a sequence";
761     Sequence.concat t1 t2
762 abate 51 | "flatten", [loc1,t1] ->
763 abate 17 check loc1 t1 Sequence.seqseq
764     "The argument of flatten must be a sequence of sequences";
765     Sequence.flatten t1
766 abate 58 | "load_xml", [loc1,t1] ->
767     check loc1 t1 Sequence.string
768     "The argument of load_xml must be a string (filename)";
769     Types.any
770 abate 64 | "raise", [loc1,t1] ->
771     Types.empty
772 abate 76 | "print_xml", [loc1,t1] ->
773     Sequence.string
774 abate 66 | "int_of", [loc1,t1] ->
775     check loc1 t1 Sequence.string
776     "The argument of int_of must a string";
777     if not (Types.subtype t1 Builtin.intstr) then
778     warning loc "This application of int_of may fail";
779     Types.interval Intervals.any
780 abate 16 | _ -> assert false
781    
782     and type_int_binop f loc1 t1 loc2 t2 =
783     if not (Types.Int.is_int t1) then
784     raise_loc loc1
785     (Constraint
786     (t1,Types.Int.any,
787     "The first argument must be an integer"));
788     if not (Types.Int.is_int t2) then
789     raise_loc loc2
790     (Constraint
791 abate 37 (t2,Types.Int.any,
792 abate 16 "The second argument must be an integer"));
793     Types.Int.put
794     (f (Types.Int.get t1) (Types.Int.get t2));
795    
796    

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