]> matita.cs.unibo.it Git - helm.git/blob - helm/software/components/ng_kernel/nCicEnvironment.ml
07185a9476eb61b7b508f397b34a518ee45d5cc8
[helm.git] / helm / software / components / ng_kernel / nCicEnvironment.ml
1 (*
2     ||M||  This file is part of HELM, an Hypertextual, Electronic        
3     ||A||  Library of Mathematics, developed at the Computer Science     
4     ||T||  Department, University of Bologna, Italy.                     
5     ||I||                                                                
6     ||T||  HELM is free software; you can redistribute it and/or         
7     ||A||  modify it under the terms of the GNU General Public License   
8     \   /  version 2 or (at your option) any later version.      
9      \ /   This software is distributed as is, NO WARRANTY.     
10       V_______________________________________________________________ *)
11
12 (* $Id$ *)
13
14 module C = NCic
15 module Ref = NReference
16
17 exception CircularDependency of string Lazy.t;;
18 exception ObjectNotFound of string Lazy.t;;
19 exception BadDependency of string Lazy.t * exn;;
20 exception BadConstraint of string Lazy.t;;
21 exception AlreadyDefined of string Lazy.t;;
22
23 let cache = NUri.UriHash.create 313;;
24 let history = ref [];;
25 let frozen_list = ref [];;
26
27 let get_obj = ref (fun _ -> assert false);;
28 let set_get_obj f = get_obj := f;;
29
30 let type0 = []
31
32 let max l1 l2 =
33  HExtlib.list_uniq ~eq:(fun (b1,u1) (b2,u2) -> b1=b2 && NUri.eq u1 u2)
34   (List.sort (fun (b1,u1) (b2,u2) ->
35     let res = compare b1 b2 in if res = 0 then NUri.compare u1 u2 else res)
36       (l1 @ l2))
37
38 let le_constraints = ref [] (* strict,a,b *)
39
40 let rec le_path_uri avoid strict a b =
41  (not strict && NUri.eq a b) ||
42  List.exists
43   (fun (strict',x,y) ->
44      NUri.eq y b && not (List.exists (NUri.eq x) avoid) &&
45        le_path_uri (x::avoid) (strict && not strict') a x
46   ) !le_constraints
47 ;;
48
49 let leq_path a b = le_path_uri [b] (fst a) (snd a) b;;
50
51 let universe_leq a b = 
52   match a, b with
53   | a,[(false,b)] -> List.for_all (fun a -> leq_path a b) a
54   | _,_ ->
55      raise (BadConstraint
56       (lazy "trying to check if a universe is less or equal than an inferred universe"))
57
58 let universe_eq a b = 
59   match a,b with 
60   | [(false,_)], [(false,_)] -> universe_leq b a && universe_leq a b
61   | _, [(false,_)]
62   | [(false,_)],_ -> false
63   | _ ->
64      raise (BadConstraint
65       (lazy "trying to check if two inferred universes are equal"))
66 ;;
67
68 let pp_constraint b x y =  
69   NUri.name_of_uri x ^ (if b then " < " else " <= ") ^ NUri.name_of_uri y
70 ;;
71
72 let pp_constraints () =
73   String.concat "\n" (List.map (fun (b,x,y) -> pp_constraint b x y) !le_constraints)
74 ;;
75
76 let universes = ref [];;
77
78 let get_universes () = List.map (fun x -> [false,x]) !universes;;
79
80 let add_constraint strict a b = 
81   match a,b with
82   | [false,a2],[false,b2] -> 
83       if not (le_path_uri [] strict a2 b2) then (
84         if le_path_uri [] (not strict) b2 a2 then
85          (raise(BadConstraint(lazy("universe inconsistency adding "^pp_constraint strict a2 b2
86            ^ " to:\n" ^ pp_constraints ()))));
87         universes := a2 :: b2 :: 
88           List.filter (fun x -> not (NUri.eq x a2 || NUri.eq x b2)) !universes;
89         le_constraints := (strict,a2,b2) :: !le_constraints);
90         history := (`Constr (strict,a,b))::!history;
91   | _ -> raise (BadConstraint
92           (lazy "trying to add a constraint on an inferred universe"))
93 ;;
94
95 let sup l =
96   match l with
97   | [false,_] -> Some l
98   | l ->
99    let bigger_than acc (s1,n1) = List.filter (le_path_uri [] s1 n1) acc in
100    let solutions = List.fold_left bigger_than !universes l in
101    let rec aux = function
102      | [] -> None
103      | u :: tl ->
104          if List.exists (fun x -> le_path_uri [] true x u) solutions then aux tl
105          else Some [false,u]
106    in
107     aux solutions
108 ;;
109
110
111
112 let typecheck_obj,already_set = ref (fun _ -> assert false), ref false;;
113 let set_typecheck_obj f =
114  if !already_set then
115   assert false
116  else
117   begin
118    typecheck_obj := f;
119    already_set := true
120   end
121 ;;
122
123 let invalidate_item item =
124  let item_eq a b = 
125    match a, b with
126    | `Obj (u1,_), `Obj (u2,_) -> NUri.eq u1 u2
127    | `Constr _, `Constr _ -> a=b (* MAKE EFFICIENT *)
128    | _ -> false
129  in
130  let rec aux to_be_deleted =
131   function
132      [] -> assert false
133    | item'::tl when item_eq item item' -> item'::to_be_deleted,tl
134    | item'::tl -> aux (item'::to_be_deleted) tl
135  in
136   let to_be_deleted,h = aux [] !history in
137    history := h;
138    List.iter 
139      (function 
140      | `Obj (uri,_) -> NUri.UriHash.remove cache uri
141      | `Constr (strict,[_,u1],[_,u2]) as c -> 
142           let w = strict,u1,u2 in
143           if not(List.mem c !history) then 
144            le_constraints := List.filter ((<>) w) !le_constraints;
145      | `Constr _ -> assert false
146      ) to_be_deleted
147 ;;
148
149 exception Propagate of NUri.uri * exn;;
150
151 let to_exn f x =
152  match f x with
153     `WellTyped o -> o
154   | `Exn e -> raise e
155 ;;
156
157 let check_and_add_obj ((u,_,_,_,_) as obj) =
158  let saved_frozen_list = !frozen_list in
159  try
160    frozen_list := (u,obj)::saved_frozen_list;
161    !typecheck_obj obj;
162    frozen_list := saved_frozen_list;
163    let obj' = `WellTyped obj in
164    NUri.UriHash.add cache u obj';
165    history := (`Obj (u,obj))::!history;
166    obj'
167  with
168     Sys.Break as e ->
169      frozen_list := saved_frozen_list;
170      raise e
171   | Propagate (u',old_exn) as e' ->
172      frozen_list := saved_frozen_list;
173      let exn = `Exn (BadDependency (lazy (NUri.string_of_uri u ^
174        " depends (recursively) on " ^ NUri.string_of_uri u' ^
175        " which is not well-typed"), 
176        match old_exn with BadDependency (_,e) -> e | _ -> old_exn)) in
177      NUri.UriHash.add cache u exn;
178      history := (`Obj (u,obj))::!history;
179      if saved_frozen_list = [] then
180       exn
181      else
182       raise e'
183   | e ->
184      frozen_list := saved_frozen_list;
185      let exn = `Exn e in
186      NUri.UriHash.add cache u exn;
187      history := (`Obj (u,obj))::!history;
188      if saved_frozen_list = [] then
189       exn
190      else
191       raise (Propagate (u,e))
192 ;;
193
194 let get_checked_obj u =
195  if List.exists (fun (k,_) -> NUri.eq u k) !frozen_list
196  then
197   raise (CircularDependency (lazy (NUri.string_of_uri u)))
198  else
199   try NUri.UriHash.find cache u
200   with Not_found -> check_and_add_obj (!get_obj u)
201 ;;
202
203 let get_checked_obj u = to_exn get_checked_obj u;;
204
205 let check_and_add_obj ((u,_,_,_,_) as obj) =
206  if NUri.UriHash.mem cache u then
207   raise (AlreadyDefined (lazy (NUri.string_of_uri u)))
208  else
209   ignore (to_exn check_and_add_obj obj)
210 ;;
211
212 let get_checked_decl = function
213   | Ref.Ref (uri, Ref.Decl) ->
214       (match get_checked_obj uri with
215       | _,height,_,_, C.Constant (rlv,name,None,ty,att) ->
216           rlv,name,ty,att,height
217       | _,_,_,_, C.Constant (_,_,Some _,_,_) ->
218           prerr_endline "get_checked_decl on a definition"; assert false
219       | _ -> prerr_endline "get_checked_decl on a non decl 2"; assert false)
220   | _ -> prerr_endline "get_checked_decl on a non decl"; assert false
221 ;;
222
223 let get_checked_def = function
224   | Ref.Ref (uri, Ref.Def _) ->
225       (match get_checked_obj uri with
226       | _,height,_,_, C.Constant (rlv,name,Some bo,ty,att) ->
227           rlv,name,bo,ty,att,height
228       | _,_,_,_, C.Constant (_,_,None,_,_) ->
229           prerr_endline "get_checked_def on an axiom"; assert false
230       | _ -> prerr_endline "get_checked_def on a non def 2"; assert false)
231   | _ -> prerr_endline "get_checked_def on a non def"; assert false
232 ;;
233
234 let get_checked_indtys = function
235   | Ref.Ref (uri, (Ref.Ind (_,n,_)|Ref.Con (n,_,_))) ->
236       (match get_checked_obj uri with
237       | _,_,_,_, C.Inductive (inductive,leftno,tys,att) ->
238         inductive,leftno,tys,att,n
239       | _ -> prerr_endline "get_checked_indtys on a non ind 2"; assert false)
240   | _ -> prerr_endline "get_checked_indtys on a non ind"; assert false
241 ;;
242
243 let get_checked_fixes_or_cofixes = function
244   | Ref.Ref (uri, (Ref.Fix _|Ref.CoFix _))->
245       (match get_checked_obj uri with
246       | _,height,_,_, C.Fixpoint (_,funcs,att) ->
247          funcs, att, height
248       | _ ->prerr_endline "get_checked_(co)fix on a non (co)fix 2";assert false)
249   | _ -> prerr_endline "get_checked_(co)fix on a non (co)fix"; assert false
250 ;;
251
252 let get_relevance (Ref.Ref (_, infos) as r) =
253   match infos with
254      Ref.Def _ -> let res,_,_,_,_,_ = get_checked_def r in res
255    | Ref.Decl -> let res,_,_,_,_ = get_checked_decl r in res
256    | Ref.Ind _ ->
257        let _,_,tl,_,n = get_checked_indtys r in
258        let res,_,_,_ = List.nth tl n in
259          res
260     | Ref.Con (_,i,_) ->
261        let _,_,tl,_,n = get_checked_indtys r in
262        let _,_,_,cl = List.nth tl n in
263        let res,_,_ = List.nth cl (i - 1) in
264          res
265     | Ref.Fix (fixno,_,_)
266     | Ref.CoFix fixno ->
267         let fl,_,_ = get_checked_fixes_or_cofixes r in
268         let res,_,_,_,_ = List.nth fl fixno in
269           res
270 ;;
271
272
273 let invalidate _ = 
274   assert (!frozen_list = []);
275   NUri.UriHash.clear cache
276 ;;