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

Contents of /typing/typer.ml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 66 - (hide annotations)
Tue Jul 10 17:02:51 2007 UTC (5 years, 11 months ago) by abate
File size: 21282 byte(s)
[r2002-10-31 16:59:46 by cvscast] Empty log message

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

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