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

Contents of /typing/typer.ml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 229 - (hide annotations)
Tue Jul 10 17:17:01 2007 UTC (5 years, 10 months ago) by abate
File size: 27791 byte(s)
[r2003-03-09 23:48:48 by cvscast] Groose simplification records + ralentissement

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

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