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

Contents of /typing/typer.ml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 78 - (hide annotations)
Tue Jul 10 17:04:23 2007 UTC (5 years, 10 months ago) by abate
File size: 22328 byte(s)
[r2002-11-06 07:46:53 by cvscast] Empty log message

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

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