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

Diff of /typing/typer.ml

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 47 by abate, Tue Jul 10 17:00:52 2007 UTC revision 139 by abate, Tue Jul 10 17:09:49 2007 UTC
# Line 4  Line 4 
4  open Location  open Location
5  open Ast  open Ast
6    
 exception Pattern of string  
7  exception NonExhaustive of Types.descr  exception NonExhaustive of Types.descr
8  exception MultipleLabel of Types.label  exception MultipleLabel of Types.label
9  exception Constraint of Types.descr * Types.descr * string  exception Constraint of Types.descr * Types.descr * string
# Line 32  Line 31 
31     | `And of ti * ti     | `And of ti * ti
32     | `Diff of ti * ti     | `Diff of ti * ti
33     | `Times of ti * ti     | `Times of ti * ti
34       | `Xml of ti * ti
35     | `Arrow of ti * ti     | `Arrow of ti * ti
36     | `Record of Types.label * bool * ti     | `Record of Types.label * bool * ti
37     | `Capture of Patterns.capture     | `Capture of Patterns.capture
# Line 44  Line 44 
44  module StringMap = Map.Make(S)  module StringMap = Map.Make(S)
45  module StringSet = Set.Make(S)  module StringSet = Set.Make(S)
46    
47    type glb = ti StringMap.t
48    
49  let mk' =  let mk' =
50    let counter = ref 0 in    let counter = ref 0 in
51    fun loc ->    fun loc ->
# Line 73  Line 75 
75  *)  *)
76    
77  module Regexp = struct  module Regexp = struct
   let memo = Hashtbl.create 51  
78    let defs = ref []    let defs = ref []
79    let name =    let name =
80      let c = ref 0 in      let c = ref 0 in
# Line 87  Line 88 
88      | Star r | WeakStar r -> seq_vars accu r      | Star r | WeakStar r -> seq_vars accu r
89      | SeqCapture (v,r) -> seq_vars (StringSet.add v accu) r      | SeqCapture (v,r) -> seq_vars (StringSet.add v accu) r
90    
91    let rec propagate vars = function    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      let re_loc = ref noloc
102    
103      let rec propagate vars : regexp -> flat = function
104      | Epsilon -> `Epsilon      | Epsilon -> `Epsilon
105      | Elem x -> `Elem (vars,x)      | Elem x -> let p = vars x in `Elem (uniq_id (),p)
106      | Seq (r1,r2) -> `Seq (propagate vars r1,propagate vars r2)      | Seq (r1,r2) -> `Seq (propagate vars r1,propagate vars r2)
107      | Alt (r1,r2) -> `Alt (propagate vars r1, propagate vars r2)      | Alt (r1,r2) -> `Alt (propagate vars r1, propagate vars r2)
108      | Star r -> `Star (propagate vars r)      | Star r -> `Star (propagate vars r)
109      | WeakStar r -> `WeakStar (propagate vars r)      | WeakStar r -> `WeakStar (propagate vars r)
110      | SeqCapture (v,x) -> propagate (StringSet.add v vars) x      | SeqCapture (v,x) ->
111            let v= mk !re_loc (Capture v) in
112            propagate (fun p -> mk !re_loc (And (vars p,v))) x
113    
114    let cup r1 r2 =    let cup r1 r2 =
115      match (r1,r2) with      match (r1,r2) with
116        | (_, `Empty) -> r1        | (_, `Empty) -> r1
117        | (`Empty, _) -> r2        | (`Empty, _) -> r2
118        | (`Res t1, `Res t2) -> `Res (mk noloc (Or (t1,t2)))        | (`Res t1, `Res t2) -> `Res (mk !re_loc (Or (t1,t2)))
119    
120    (*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    let rec compile fin e seq : [`Res of Ast.ppat | `Empty] =    let rec compile fin e seq : [`Res of Ast.ppat | `Empty] =
128      if List.mem seq e then `Empty      if Coind.mem seq !e then `Empty
129      else      else (
130        let e = seq :: e in        e := Coind.add seq !e;
131        match seq with        match seq with
132          | [] ->          | [] ->
133              `Res fin              `Res fin
134          | `Epsilon :: rest ->          | `Epsilon :: rest ->
135              compile fin e rest              compile fin e rest
136          | `Elem (vars,x) :: rest ->          | `Elem (_,p) :: rest ->
137              let capt = StringSet.fold              `Res (mk !re_loc (Prod (p, guard_compile fin rest)))
                          (fun v t -> mk noloc (And (t, (mk noloc (Capture v)))))  
                          vars x in  
             `Res (mk noloc (Prod (capt, guard_compile fin rest)))  
138          | `Seq (r1,r2) :: rest ->          | `Seq (r1,r2) :: rest ->
139              compile fin e (r1 :: r2 :: rest)              compile fin e (r1 :: r2 :: rest)
140          | `Alt (r1,r2) :: rest ->          | `Alt (r1,r2) :: rest ->
141              cup (compile fin e (r1::rest)) (compile fin e (r2::rest))              cup (compile fin e (r1::rest)) (compile fin e (r2::rest))
142          | `Star r :: rest -> cup (compile fin e (r::seq)) (compile fin e rest)          | `Star r :: rest ->
143          | `WeakStar r :: rest -> cup (compile fin e rest) (compile fin e (r::seq))              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    and guard_compile fin seq =    and guard_compile fin seq =
148      try Hashtbl.find memo seq      try Memo.find seq !memo
149      with      with
150          Not_found ->          Not_found ->
151            let n = name () in            let n = name () in
152            let v = mk noloc (PatVar n) in            let v = mk !re_loc (PatVar n) in
153            Hashtbl.add memo seq v;            memo := Memo.add seq v !memo;
154            let d = compile fin [] seq in            let d = compile fin (ref Coind.empty) seq in
155            (match d with            (match d with
156               | `Empty -> assert false               | `Empty -> assert false
157               | `Res d -> defs := (n,d) :: !defs);               | `Res d -> defs := (n,d) :: !defs);
158            v            v
159    
160    
   let atom_nil = Types.mk_atom "nil"  
161    let constant_nil v t =    let constant_nil v t =
162      mk noloc (And (t, (mk noloc (Constant (v, Types.Atom atom_nil)))))      mk !re_loc
163          (And (t, (mk !re_loc (Constant (v, Types.Atom Sequence.nil_atom)))))
164    
165    let compile regexp queue : ppat =    let compile loc regexp queue : ppat =
166        re_loc := loc;
167      let vars = seq_vars StringSet.empty regexp in      let vars = seq_vars StringSet.empty regexp in
168      let fin = StringSet.fold constant_nil vars queue in      let fin = StringSet.fold constant_nil vars queue in
169      let n = guard_compile fin [propagate StringSet.empty regexp] in      let n = guard_compile fin [propagate (fun p -> p) regexp] in
170      Hashtbl.clear memo;      memo := Memo.empty;
171      let d = !defs in      let d = !defs in
172      defs := [];      defs := [];
173      mk noloc (Recurs (n,d))      mk !re_loc (Recurs (n,d))
174  end  end
175    
176  let compile_regexp = Regexp.compile  let compile_regexp = Regexp.compile noloc
177    
178    
179  let rec compile env { loc = loc; descr = d } : ti =  let rec compile env { loc = loc; descr = d } : ti =
# Line 159  Line 181 
181    | PatVar s ->    | PatVar s ->
182        (try StringMap.find s env        (try StringMap.find s env
183         with Not_found ->         with Not_found ->
184           raise_loc loc (Pattern ("Undefined type variable " ^ s))           raise_loc_generic loc ("Undefined type variable " ^ s)
185        )        )
186    | Recurs (t, b) -> compile (compile_many env b) t    | Recurs (t, b) -> compile (compile_many env b) t
187    | Regexp (r,q) -> compile env (Regexp.compile r q)    | Regexp (r,q) -> compile env (Regexp.compile loc r q)
188    | Internal t -> cons loc (`Type t)    | Internal t -> cons loc (`Type t)
189    | Or (t1,t2) -> cons loc (`Or (compile env t1, compile env t2))    | Or (t1,t2) -> cons loc (`Or (compile env t1, compile env t2))
190    | And (t1,t2) -> cons loc (`And (compile env t1, compile env t2))    | And (t1,t2) -> cons loc (`And (compile env t1, compile env t2))
191    | Diff (t1,t2) -> cons loc (`Diff (compile env t1, compile env t2))    | Diff (t1,t2) -> cons loc (`Diff (compile env t1, compile env t2))
192    | Prod (t1,t2) -> cons loc (`Times (compile env t1, compile env t2))    | Prod (t1,t2) -> cons loc (`Times (compile env t1, compile env t2))
193      | XmlT (t1,t2) -> cons loc (`Xml (compile env t1, compile env t2))
194    | Arrow (t1,t2) -> cons loc (`Arrow (compile env t1, compile env t2))    | Arrow (t1,t2) -> cons loc (`Arrow (compile env t1, compile env t2))
195    | Record (l,o,t) -> cons loc (`Record (l,o,compile env t))    | Record (l,o,t) -> cons loc (`Record (l,o,compile env t))
196    | Constant (x,v) -> cons loc (`Constant (x,v))    | Constant (x,v) -> cons loc (`Constant (x,v))
# Line 180  Line 203 
203    List.iter (fun (v,t,x) -> x.descr' <- `Alias (v, compile env t)) b;    List.iter (fun (v,t,x) -> x.descr' <- `Alias (v, compile env t)) b;
204    env    env
205    
206    let comp_fv_seen = ref []
207  let rec comp_fv seen s =  let comp_fv_res = ref []
208    let rec comp_fv s =
209      if List.memq s !comp_fv_seen then ()
210      else (
211        comp_fv_seen := s :: !comp_fv_seen;
212    match s.fv with    match s.fv with
213      | Some l -> l        | Some fv -> comp_fv_res := List.rev_append fv !comp_fv_res
214      | None ->      | None ->
215          let l =            (match s.descr' with
216            match s.descr' with               | `Alias (_,x) -> comp_fv x
             | `Alias (_,x) -> if List.memq s seen then [] else comp_fv (s :: seen) x  
217              | `Or (s1,s2)              | `Or (s1,s2)
218              | `And (s1,s2)              | `And (s1,s2)
219              | `Diff (s1,s2)              | `Diff (s1,s2)
220              | `Times (s1,s2)               | `Times (s1,s2) | `Xml (s1,s2)
221              | `Arrow (s1,s2) -> SortedList.cup (comp_fv seen s1) (comp_fv seen s2)               | `Arrow (s1,s2) -> comp_fv s1; comp_fv s2
222              | `Record (l,opt,s) -> comp_fv seen s               | `Record (l,opt,s) -> comp_fv s
223              | `Type _ -> []               | `Type _ -> ()
224              | `Capture x              | `Capture x
225              | `Constant (x,_) -> [x]               | `Constant (x,_) -> comp_fv_res := x :: !comp_fv_res
226          in            )
227          if seen = [] then s.fv <- Some l;    )
         l  
228    
229    
230  let fv = comp_fv []  
231    let fv s =
232      match s.fv with
233        | Some l -> l
234        | None ->
235            comp_fv s;
236            let l = SortedList.from_list !comp_fv_res in
237            comp_fv_res := [];
238            comp_fv_seen := [];
239            s.fv <- Some l;
240            l
241    
242  let rec typ seen s : Types.descr =  let rec typ seen s : Types.descr =
243    match s.descr' with    match s.descr' with
244      | `Alias (v,x) ->      | `Alias (v,x) ->
245          if List.memq s seen then          if List.memq s seen then
246            raise_loc s.loc'            raise_loc_generic s.loc'
247              (Pattern              ("Unguarded recursion on variable " ^ v ^ " in this type")
                ("Unguarded recursion on variable " ^ v ^ " in this type"))  
248          else typ (s :: seen) x          else typ (s :: seen) x
249      | `Type t -> t      | `Type t -> t
250      | `Or (s1,s2) -> Types.cup (typ seen s1) (typ seen s2)      | `Or (s1,s2) -> Types.cup (typ seen s1) (typ seen s2)
251      | `And (s1,s2) ->  Types.cap (typ seen s1) (typ seen s2)      | `And (s1,s2) ->  Types.cap (typ seen s1) (typ seen s2)
252      | `Diff (s1,s2) -> Types.diff (typ seen s1) (typ seen s2)      | `Diff (s1,s2) -> Types.diff (typ seen s1) (typ seen s2)
253      | `Times (s1,s2) -> Types.times (typ_node s1) (typ_node s2)      | `Times (s1,s2) -> Types.times (typ_node s1) (typ_node s2)
254        | `Xml (s1,s2) ->   Types.xml (typ_node s1) (typ_node s2)
255      | `Arrow (s1,s2) -> Types.arrow (typ_node s1) (typ_node s2)      | `Arrow (s1,s2) -> Types.arrow (typ_node s1) (typ_node s2)
256      | `Record (l,o,s) -> Types.record l o (typ_node s)      | `Record (l,o,s) -> Types.record l o (typ_node s)
257      | `Capture _ | `Constant _ -> assert false      | `Capture x | `Constant (x,_) -> assert false
258    
259  and typ_node s : Types.node =  and typ_node s : Types.node =
260    match s.type_node with    match s.type_node with
# Line 231  Line 266 
266          Types.define x t;          Types.define x t;
267          x          x
268    
269  let type_node s = Types.internalize (typ_node s)  let type_node s =
270      let s = typ_node s in
271      let s = Types.internalize s in
272    (*  Types.define s (Types.normalize (Types.descr s)); *)
273      s
274    
275  let rec pat seen s : Patterns.descr =  let rec pat seen s : Patterns.descr =
276    if fv s = [] then Patterns.constr (type_node s) else    if fv s = [] then Patterns.constr (Types.descr (type_node s)) else
277    match s.descr' with      try pat_aux seen s
278        with Patterns.Error e -> raise_loc_generic s.loc' e
279          | Location (loc,exn) when loc = noloc -> raise (Location (s.loc', exn))
280    
281    
282    and pat_aux seen s = match s.descr' with
283      | `Alias (v,x) ->      | `Alias (v,x) ->
284          if List.memq s seen then        if List.memq s seen
285            raise_loc s.loc'        then raise
286              (Pattern          (Patterns.Error
287                 ("Unguarded recursion on variable " ^ v ^ " in this pattern"))             ("Unguarded recursion on variable " ^ v ^ " in this pattern"));
288          else pat (s :: seen) x        pat (s :: seen) x
289      | `Or (s1,s2) -> Patterns.cup (pat seen s1) (pat seen s2)      | `Or (s1,s2) -> Patterns.cup (pat seen s1) (pat seen s2)
290      | `And (s1,s2) -> Patterns.cap (pat seen s1) (pat seen s2)      | `And (s1,s2) -> Patterns.cap (pat seen s1) (pat seen s2)
291      | `Diff (s1,s2) when fv s2 = [] ->      | `Diff (s1,s2) when fv s2 = [] ->
292          let s2 = Types.cons (Types.neg (Types.descr (type_node s2)))in        let s2 = Types.neg (Types.descr (type_node s2)) in
293          Patterns.cap (pat seen s1) (Patterns.constr s2)          Patterns.cap (pat seen s1) (Patterns.constr s2)
294      | `Diff _ ->      | `Diff _ ->
295          raise_loc s.loc' (Pattern "Difference not allowed in patterns")        raise (Patterns.Error "Difference not allowed in patterns")
296      | `Times (s1,s2) -> Patterns.times (pat_node s1) (pat_node s2)      | `Times (s1,s2) -> Patterns.times (pat_node s1) (pat_node s2)
297      | `Xml (s1,s2) -> Patterns.xml (pat_node s1) (pat_node s2)
298      | `Record (l,false,s) -> Patterns.record l (pat_node s)      | `Record (l,false,s) -> Patterns.record l (pat_node s)
299      | `Record _ ->      | `Record _ ->
300          raise_loc s.loc'        raise (Patterns.Error "Optional field not allowed in record patterns")
           (Pattern "Optional field not allowed in record patterns")  
301      | `Capture x ->  Patterns.capture x      | `Capture x ->  Patterns.capture x
302      | `Constant (x,c) -> Patterns.constant x c      | `Constant (x,c) -> Patterns.constant x c
303      | `Arrow _ ->      | `Arrow _ ->
304          raise_loc s.loc' (Pattern "Arrow not allowed in patterns")        raise (Patterns.Error "Arrow not allowed in patterns")
305      | `Type _ -> assert false      | `Type _ -> assert false
306    
307  and pat_node s : Patterns.node =  and pat_node s : Patterns.node =
# Line 270  Line 314 
314          Patterns.define x t;          Patterns.define x t;
315          x          x
316    
 let global_types = ref StringMap.empty  
   
317  let mk_typ e =  let mk_typ e =
318    if fv e = [] then type_node e    if fv e = [] then type_node e
319    else raise_loc e.loc' (Pattern "Capture variables are not allowed in types")    else raise_loc_generic e.loc' "Capture variables are not allowed in types"
320    
321    
322  let typ e =  let typ glb e =
323    mk_typ (compile !global_types e)    mk_typ (compile glb e)
324    
325    let pat glb e =
326      pat_node (compile glb e)
327    
328    let register_global_types glb b =
329      let env' = compile_many glb b in
330      List.fold_left
331        (fun glb (v,{ loc = loc }) ->
332           let t = StringMap.find v env' in
333           let d = Types.descr (mk_typ t) in
334           (*              let d = Types.normalize d in*)
335           Types.Print.register_global v d;
336           if StringMap.mem v glb
337           then raise_loc_generic loc ("Multiple definition for type " ^ v);
338           StringMap.add v t glb
339        ) glb b
340    
 let pat e =  
   let e = compile !global_types e in  
   pat_node e  
   
 let register_global_types b =  
   let env = compile_many !global_types b in  
   List.iter (fun (v,_) ->  
                let d = Types.descr (mk_typ (StringMap.find v env)) in  
                let d = Types.normalize d in  
                Types.Print.register_global v d  
             ) b;  
   global_types := env  
341    
342    
343  (* II. Build skeleton *)  (* II. Build skeleton *)
344    
345  module Fv = StringSet  module Fv = StringSet
346    
347  let rec expr { loc = loc; descr = d } =  (* IDEA: introduce a node Loc in the AST to override nolocs
348       in sub-expressions *)
349    
350    let rec expr loc' glb { loc = loc; descr = d } =
351      let loc =  if loc = noloc then loc' else loc in
352    let (fv,td) =    let (fv,td) =
353      match d with      match d with
354        | DebugTyper t -> (Fv.empty, Typed.DebugTyper (typ t))        | Forget (e,t) ->
355              let (fv,e) = expr loc glb e and t = typ glb t in
356              (fv, Typed.Forget (e,t))
357        | Var s -> (Fv.singleton s, Typed.Var s)        | Var s -> (Fv.singleton s, Typed.Var s)
358        | Apply (e1,e2) ->        | Apply (e1,e2) ->
359            let (fv1,e1) = expr e1 and (fv2,e2) = expr e2 in            let (fv1,e1) = expr loc glb e1 and (fv2,e2) = expr loc glb e2 in
360            (Fv.union fv1 fv2, Typed.Apply (e1,e2))            (Fv.union fv1 fv2, Typed.Apply (e1,e2))
361        | Abstraction a ->        | Abstraction a ->
362            let iface = List.map (fun (t1,t2) -> (typ t1, typ t2)) a.fun_iface in            let iface = List.map (fun (t1,t2) -> (typ glb t1, typ glb t2))
363                            a.fun_iface in
364            let t = List.fold_left            let t = List.fold_left
365                      (fun accu (t1,t2) -> Types.cap accu (Types.arrow t1 t2))                      (fun accu (t1,t2) -> Types.cap accu (Types.arrow t1 t2))
366                      Types.any iface in                      Types.any iface in
367            let iface = List.map            let iface = List.map
368                          (fun (t1,t2) -> (Types.descr t1, Types.descr t2))                          (fun (t1,t2) -> (Types.descr t1, Types.descr t2))
369                          iface in                          iface in
370            let (fv0,body) = branches a.fun_body in            let (fv0,body) = branches loc glb a.fun_body in
371            let fv = match a.fun_name with            let fv = match a.fun_name with
372              | None -> fv0              | None -> fv0
373              | Some f -> Fv.remove f fv0 in              | Some f -> Fv.remove f fv0 in
# Line 324  Line 377 
377                 Typed.fun_iface = iface;                 Typed.fun_iface = iface;
378                 Typed.fun_body = body;                 Typed.fun_body = body;
379                 Typed.fun_typ = t;                 Typed.fun_typ = t;
380                 Typed.fun_fv = Fv.elements fv0                 Typed.fun_fv = Fv.elements fv
381               }               }
382            )            )
383        | Cst c -> (Fv.empty, Typed.Cst c)        | Cst c -> (Fv.empty, Typed.Cst c)
384        | Pair (e1,e2) ->        | Pair (e1,e2) ->
385            let (fv1,e1) = expr e1 and (fv2,e2) = expr e2 in            let (fv1,e1) = expr loc glb e1 and (fv2,e2) = expr loc glb e2 in
386            (Fv.union fv1 fv2, Typed.Pair (e1,e2))            (Fv.union fv1 fv2, Typed.Pair (e1,e2))
387          | Xml (e1,e2) ->
388              let (fv1,e1) = expr loc glb e1 and (fv2,e2) = expr loc glb e2 in
389              (Fv.union fv1 fv2, Typed.Xml (e1,e2))
390        | Dot (e,l) ->        | Dot (e,l) ->
391            let (fv,e) = expr e in            let (fv,e) = expr loc glb e in
392            (fv,  Typed.Dot (e,l))            (fv,  Typed.Dot (e,l))
393        | RecordLitt r ->        | RecordLitt r ->
394            let fv = ref Fv.empty in            let fv = ref Fv.empty in
395            let r  = List.sort (fun (l1,_) (l2,_) -> compare l1 l2) r in            let r  = List.sort (fun (l1,_) (l2,_) -> compare l1 l2) r in
396            let r = List.map            let r = List.map
397                      (fun (l,e) ->                      (fun (l,e) ->
398                         let (fv2,e) = expr e in fv := Fv.union !fv fv2; (l,e))                         let (fv2,e) = expr loc glb e
399                           in fv := Fv.union !fv fv2; (l,e))
400                      r in                      r in
401            let rec check = function            let rec check = function
402              | (l1,_) :: (l2,_) :: _ when l1 = l2 ->              | (l1,_) :: (l2,_) :: _ when l1 = l2 ->
# Line 349  Line 406 
406            check r;            check r;
407            (!fv, Typed.RecordLitt r)            (!fv, Typed.RecordLitt r)
408        | Op (op,le) ->        | Op (op,le) ->
409            let (fvs,ltes) = List.split (List.map expr le) in            let (fvs,ltes) = List.split (List.map (expr loc glb) le) in
410            let fv = List.fold_left Fv.union Fv.empty fvs in            let fv = List.fold_left Fv.union Fv.empty fvs in
411            (fv, Typed.Op (op,ltes))            (fv, Typed.Op (op,ltes))
412        | Match (e,b) ->        | Match (e,b) ->
413            let (fv1,e) = expr e            let (fv1,e) = expr loc glb e
414            and (fv2,b) = branches b in            and (fv2,b) = branches loc glb b in
415            (Fv.union fv1 fv2, Typed.Match (e, b))            (Fv.union fv1 fv2, Typed.Match (e, b))
416        | Map (e,b) ->        | Map (e,b) ->
417            let (fv1,e) = expr e            let (fv1,e) = expr loc glb e
418            and (fv2,b) = branches b in            and (fv2,b) = branches loc glb b in
419            (Fv.union fv1 fv2, Typed.Map (e, b))            (Fv.union fv1 fv2, Typed.Map (e, b))
420          | Try (e,b) ->
421              let (fv1,e) = expr loc glb e
422              and (fv2,b) = branches loc glb b in
423              (Fv.union fv1 fv2, Typed.Try (e, b))
424    in    in
425    fv,    fv,
426    { Typed.exp_loc = loc;    { Typed.exp_loc = loc;
# Line 367  Line 428 
428      Typed.exp_descr = td;      Typed.exp_descr = td;
429    }    }
430    
431    and branches b =    and branches loc glb b =
432      let fv = ref Fv.empty in      let fv = ref Fv.empty in
433      let accept = ref Types.empty in      let accept = ref Types.empty in
434      let b = List.map      let b = List.map
435                (fun (p,e) ->                (fun (p,e) ->
436                   let (fv2,e) = expr e in                   let (fv2,e) = expr loc glb e in
437                     let p = pat glb p in
438                     let fv2 = List.fold_right Fv.remove (Patterns.fv p) fv2 in
439                   fv := Fv.union !fv fv2;                   fv := Fv.union !fv fv2;
                  let p = pat p in  
440                   accept := Types.cup !accept (Types.descr (Patterns.accept p));                   accept := Types.cup !accept (Types.descr (Patterns.accept p));
441                   { Typed.br_used = false;                   { Typed.br_used = false;
442                     Typed.br_pat = p;                     Typed.br_pat = p;
# Line 389  Line 451 
451       }       }
452      )      )
453    
454    let expr = expr noloc
455    
456    let let_decl glb p e =
457      let (_,e) = expr glb e in
458      { Typed.let_pat = pat glb p;
459        Typed.let_body = e;
460        Typed.let_compiled = None }
461    
462    (* III. Type-checks *)
463    
464  module Env = StringMap  module Env = StringMap
465    type env = Types.descr Env.t
466    
467  open Typed  open Typed
468    
469    let warning loc msg =
470      Format.fprintf !Location.warning_ppf "Warning %a:@\n%a%s@\n"
471        Location.print_loc loc
472        Location.html_hilight loc
473        msg
474    
475  let check loc t s msg =  let check loc t s msg =
476    if not (Types.subtype t s) then raise_loc loc (Constraint (t, s, msg))    if not (Types.subtype t s) then raise_loc loc (Constraint (t, s, msg))
# Line 406  Line 484 
484    d    d
485    
486  and type_check' loc env e constr precise = match e with  and type_check' loc env e constr precise = match e with
487      | Forget (e,t) ->
488          let t = Types.descr t in
489          ignore (type_check env e t false);
490          t
491    | Abstraction a ->    | Abstraction a ->
492        let t =        let t =
493          try Types.Arrow.check_strenghten a.fun_typ constr          try Types.Arrow.check_strenghten a.fun_typ constr
# Line 422  Line 504 
504             ignore (type_check_branches loc env t1 a.fun_body t2 false)             ignore (type_check_branches loc env t1 a.fun_body t2 false)
505          ) a.fun_iface;          ) a.fun_iface;
506        t        t
507    
508    | Match (e,b) ->    | Match (e,b) ->
509        let t = type_check env e b.br_accept true in        let t = type_check env e b.br_accept true in
510        type_check_branches loc env t b constr precise        type_check_branches loc env t b constr precise
511    
512    | Pair (e1,e2) ->    | Try (e,b) ->
513        let rects = Types.Product.get constr in        let te = type_check env e constr precise in
514        if Types.Product.is_empty rects then        let tb = type_check_branches loc env Types.any b constr precise in
515          raise_loc loc (ShouldHave (constr,"but it is a pair."));        Types.cup te tb
       let pi1 = Types.Product.pi1 rects in  
   
       let t1 = type_check env e1 (Types.Product.pi1 rects)  
                  (precise || (Types.Product.need_second rects))in  
       let rects = Types.Product.restrict_1 rects t1 in  
       let t2 = type_check env e2 (Types.Product.pi2 rects) precise in  
       if precise then  
         Types.times (Types.cons t1) (Types.cons t2)  
       else  
         constr  
516    
517      | Pair (e1,e2) ->
518          type_check_pair loc env e1 e2 constr precise
519      | Xml (e1,e2) ->
520          type_check_pair ~kind:`XML loc env e1 e2 constr precise
521    | RecordLitt r ->    | RecordLitt r ->
522        let rconstr = Types.Record.get constr in        let rconstr = Types.Record.get constr in
523        if Types.Record.is_empty rconstr then        if Types.Record.is_empty rconstr then
524          raise_loc loc (ShouldHave (constr,"but it is a record."));          raise_loc loc (ShouldHave (constr,"but it is a record."));
525    
526    (* Completely buggy !  Need to check at the end that all required labels
527       are present ...A better to do it without precise = true ? *)
528          let precise = true in
529    
530        let (rconstr,res) =        let (rconstr,res) =
531          List.fold_left          List.fold_left
532            (fun (rconstr,res) (l,e) ->            (fun (rconstr,res) (l,e) ->
# Line 455  Line 536 
536                 raise_loc loc                 raise_loc loc
537                   (ShouldHave (constr,(Printf.sprintf                   (ShouldHave (constr,(Printf.sprintf
538                                          "Field %s is not allowed here."                                          "Field %s is not allowed here."
539                                          (Types.label_name l)                                          (Types.LabelPool.value l)
540                                       )                                       )
541                               ));                               ));
542               let t = type_check env e pi true in               let t = type_check env e pi true in
# Line 468  Line 549 
549               (rconstr,res)               (rconstr,res)
550            ) (rconstr, if precise then Types.Record.any else constr) r            ) (rconstr, if precise then Types.Record.any else constr) r
551        in        in
552    (*      check loc res constr ""; *)
553        res        res
554    
555    | Map (e,b) ->    | Map (e,b) ->
# Line 475  Line 557 
557    
558        let constr' = Sequence.approx (Types.cap Sequence.any constr) in        let constr' = Sequence.approx (Types.cap Sequence.any constr) in
559        let exact = Types.subtype (Sequence.star constr') constr in        let exact = Types.subtype (Sequence.star constr') constr in
   
       if exact then (  
         (* Note: typing mail fail because of the approx on t *)  
         let res = type_check_branches loc env (Sequence.approx t)  
                     b constr' precise in  
         if precise then Sequence.star res else constr  
       )  
       else  
560          (* Note:          (* Note:
561             - could be more precise by integrating the decomposition             - could be more precise by integrating the decomposition
562             of constr inside Sequence.map.             of constr inside Sequence.map.
563          *)          *)
564          let res =          let res =
565            Sequence.map            Sequence.map
566              (fun t -> type_check_branches loc env t b constr' true)            (fun t ->
567                 type_check_branches loc env t b constr' (precise || (not exact)))
568              t in              t in
569          if not exact then check loc res constr "";          if not exact then check loc res constr "";
570          if precise then res else constr          if precise then res else constr
# Line 510  Line 585 
585          let res = Sequence.concat t1 t2 in          let res = Sequence.concat t1 t2 in
586          check loc res constr "";          check loc res constr "";
587          if precise then res else constr          if precise then res else constr
588      | Apply (e1,e2) ->
589    (*
590          let constr' = Sequence.star
591                          (Sequence.approx (Types.cap Sequence.any constr)) in
592          let t1 = type_check env e1 (Types.cup Types.Arrow.any constr') true in
593          let t1_fun = Types.Arrow.get t1 in
594    
595          let has_fun = not (Types.Arrow.is_empty t1_fun)
596          and has_seq = not (Types.subtype t1 Types.Arrow.any) in
597    
598          let constr' =
599            Types.cap
600              (if has_fun then Types.Arrow.domain t1_fun else Types.any)
601              (if has_seq then constr' else Types.any)
602          in
603          let need_arg = has_fun && Types.Arrow.need_arg t1_fun in
604          let precise  = need_arg || has_seq in
605          let t2 = type_check env e2 constr' precise in
606          let res = Types.cup
607                      (if has_fun then
608                         if need_arg then Types.Arrow.apply t1_fun t2
609                         else Types.Arrow.apply_noarg t1_fun
610                       else Types.empty)
611                      (if has_seq then Sequence.concat t1 t2
612                       else Types.empty)
613          in
614          check loc res constr "";
615          res
616    *)
617          let t1 = type_check env e1 Types.Arrow.any true in
618          let t1 = Types.Arrow.get t1 in
619          let dom = Types.Arrow.domain t1 in
620          let res =
621            if Types.Arrow.need_arg t1 then
622              let t2 = type_check env e2 dom true in
623              Types.Arrow.apply t1 t2
624            else
625              (ignore (type_check env e2 dom false); Types.Arrow.apply_noarg t1)
626          in
627          check loc res constr "";
628          res
629    | Op ("flatten", [e]) ->    | Op ("flatten", [e]) ->
630        let constr' = Sequence.star        let constr' = Sequence.star
631                        (Sequence.approx (Types.cap Sequence.any constr)) in                        (Sequence.approx (Types.cap Sequence.any constr)) in
# Line 528  Line 644 
644        check loc t constr "";        check loc t constr "";
645        t        t
646    
647    and type_check_pair ?(kind=`Normal) loc env e1 e2 constr precise =
648      let rects = Types.Product.get ~kind constr in
649      if Types.Product.is_empty rects then
650        (match kind with
651          | `Normal -> raise_loc loc (ShouldHave (constr,"but it is a pair."))
652          | `XML -> raise_loc loc (ShouldHave (constr,"but it is an XML element.")));
653      let pi1 = Types.Product.pi1 rects in
654    
655      let t1 = type_check env e1 (Types.Product.pi1 rects)
656                 (precise || (Types.Product.need_second rects))in
657      let rects = Types.Product.restrict_1 rects t1 in
658      let t2 = type_check env e2 (Types.Product.pi2 rects) precise in
659      if precise then
660        match kind with
661          | `Normal -> Types.times (Types.cons t1) (Types.cons t2)
662          | `XML -> Types.xml (Types.cons t1) (Types.cons t2)
663      else
664        constr
665    
666    
667  and compute_type env e =  and compute_type env e =
668    type_check env e Types.any true    type_check env e Types.any true
669    
670  and compute_type' loc env = function  and compute_type' loc env = function
   | DebugTyper t -> Types.descr t  
671    | Var s ->    | Var s ->
672        (try Env.find s env        (try Env.find s env
673         with Not_found -> raise_loc loc (UnboundId s)         with Not_found -> raise_loc loc (UnboundId s)
674        )        )
   | Apply (e1,e2) ->  
       let t1 = type_check env e1 Types.Arrow.any true in  
       let t1 = Types.Arrow.get t1 in  
       let dom = Types.Arrow.domain t1 in  
       if Types.Arrow.need_arg t1 then  
         let t2 = type_check env e2 dom true in  
         Types.Arrow.apply t1 t2  
       else  
         (ignore (type_check env e2 dom false); Types.Arrow.apply_noarg t1)  
675    | Cst c -> Types.constant c    | Cst c -> Types.constant c
676    | Dot (e,l) ->    | Dot (e,l) ->
677        let t = type_check env e Types.Record.any true in        let t = type_check env e Types.Record.any true in
# Line 610  Line 736 
736              tres              tres
737          )          )
738    
739    and type_let_decl env l =
740      let acc = Types.descr (Patterns.accept l.let_pat) in
741      let t = type_check env l.let_body acc true in
742      let res = Patterns.filter t l.let_pat in
743      List.map (fun (x,t) -> (x, Types.descr t)) res
744    
745    and type_rec_funs env l =
746      let types =
747        List.fold_left
748          (fun accu -> function  {let_body={exp_descr=Abstraction a}} as l ->
749             let t = a.fun_typ in
750             let acc = Types.descr (Patterns.accept l.let_pat) in
751             if not (Types.subtype t acc) then
752               raise_loc l.let_body.exp_loc (NonExhaustive (Types.diff t acc));
753             let res = Patterns.filter t l.let_pat in
754             List.fold_left (fun accu (x,t) -> (x, Types.descr t)::accu) accu res
755             | _ -> assert false) [] l
756      in
757      let env' = List.fold_left (fun env (x,t) -> Env.add x t env) env types in
758      List.iter
759        (function  { let_body = { exp_descr = Abstraction a } } as l ->
760           ignore (type_check env' l.let_body Types.any false)
761           | _ -> assert false) l;
762      types
763    
764    
765  and type_op loc op args =  and type_op loc op args =
766    match (op,args) with    match (op,args) with
767      | ("+", [loc1,t1; loc2,t2]) ->      | "+", [loc1,t1; loc2,t2] ->
768          type_int_binop Intervals.add loc1 t1 loc2 t2          type_int_binop Intervals.add loc1 t1 loc2 t2
769      | ("*", [loc1,t1; loc2,t2]) ->      | "-", [loc1,t1; loc2,t2] ->
770            type_int_binop Intervals.sub loc1 t1 loc2 t2
771        | ("*" | "/"), [loc1,t1; loc2,t2] ->
772          type_int_binop (fun i1 i2 -> Intervals.any) loc1 t1 loc2 t2          type_int_binop (fun i1 i2 -> Intervals.any) loc1 t1 loc2 t2
773      | ("@", [loc1,t1; loc2,t2]) ->      | "@", [loc1,t1; loc2,t2] ->
774          check loc1 t1 Sequence.any          check loc1 t1 Sequence.any
775            "The first argument of @ must be a sequence";            "The first argument of @ must be a sequence";
776          Sequence.concat t1 t2          Sequence.concat t1 t2
777      | ("flatten", [loc1,t1]) ->      | "flatten", [loc1,t1] ->
778          check loc1 t1 Sequence.seqseq          check loc1 t1 Sequence.seqseq
779            "The argument of flatten must be a sequence of sequences";            "The argument of flatten must be a sequence of sequences";
780          Sequence.flatten t1          Sequence.flatten t1
781        | "load_xml", [loc1,t1] ->
782            check loc1 t1 Sequence.string
783              "The argument of load_xml must be a string (filename)";
784            Types.any
785        | "raise", [loc1,t1] ->
786            Types.empty
787        | "print_xml", [loc1,t1] ->
788            Sequence.string
789        | "print", [loc1,t1] ->
790            check loc1 t1 Sequence.string
791              "The argument of print must be a string";
792            Sequence.nil_type
793        | "dump_to_file", [loc1,t1; loc2,t2] ->
794            check loc1 t1 Sequence.string
795              "The argument of dump_to_file must be a string (filename)";
796            check loc2 t2 Sequence.string
797              "The argument of dump_to_file must be a string (value to dump)";
798            Sequence.nil_type
799        | "int_of", [loc1,t1] ->
800            check loc1 t1 Sequence.string
801              "The argument of int_of must be a string";
802            if not (Types.subtype t1 Builtin.intstr) then
803              warning loc "This application of int_of may fail";
804            Types.interval Intervals.any
805        | "string_of", [loc1,t1] ->
806            Sequence.string
807      | _ -> assert false      | _ -> assert false
808    
809  and type_int_binop f loc1 t1 loc2 t2 =  and type_int_binop f loc1 t1 loc2 t2 =

Legend:
Removed from v.47  
changed lines
  Added in v.139

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