]> matita.cs.unibo.it Git - helm.git/blob - helm/software/components/ng_kernel/nCicEnvironment.ml
1) The NG kernel now accepts only usage of declared universes
[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 is_declared u =
81  match u with
82     [false,x] -> List.exists (fun y -> NUri.eq x y) !universes
83   | _ -> assert false
84 ;;
85
86 let add_constraint strict a b = 
87   match a,b with
88   | [false,a2],[false,b2] -> 
89       if not (le_path_uri [] strict a2 b2) then (
90         if le_path_uri [] (not strict) b2 a2 then
91          (raise(BadConstraint(lazy("universe inconsistency adding "^pp_constraint strict a2 b2
92            ^ " to:\n" ^ pp_constraints ()))));
93         universes := a2 :: b2 :: 
94           List.filter (fun x -> not (NUri.eq x a2 || NUri.eq x b2)) !universes;
95         le_constraints := (strict,a2,b2) :: !le_constraints);
96         history := (`Constr (strict,a,b))::!history;
97   | _ -> raise (BadConstraint
98           (lazy "trying to add a constraint on an inferred universe"))
99 ;;
100
101 let sup l =
102   match l with
103   | [false,_] -> Some l
104   | l ->
105    let bigger_than acc (s1,n1) = List.filter (le_path_uri [] s1 n1) acc in
106    let solutions = List.fold_left bigger_than !universes l in
107    let rec aux = function
108      | [] -> None
109      | u :: tl ->
110          if List.exists (fun x -> le_path_uri [] true x u) solutions then aux tl
111          else Some [false,u]
112    in
113     aux solutions
114 ;;
115
116
117
118 let typecheck_obj,already_set = ref (fun _ -> assert false), ref false;;
119 let set_typecheck_obj f =
120  if !already_set then
121   assert false
122  else
123   begin
124    typecheck_obj := f;
125    already_set := true
126   end
127 ;;
128
129 let invalidate_item item =
130  let item_eq a b = 
131    match a, b with
132    | `Obj (u1,_), `Obj (u2,_) -> NUri.eq u1 u2
133    | `Constr _, `Constr _ -> a=b (* MAKE EFFICIENT *)
134    | _ -> false
135  in
136  let rec aux to_be_deleted =
137   function
138      [] -> assert false
139    | item'::tl when item_eq item item' -> item'::to_be_deleted,tl
140    | item'::tl -> aux (item'::to_be_deleted) tl
141  in
142   let to_be_deleted,h = aux [] !history in
143    history := h;
144    List.iter 
145      (function 
146      | `Obj (uri,_) -> NUri.UriHash.remove cache uri
147      | `Constr (strict,[_,u1],[_,u2]) as c -> 
148           let w = strict,u1,u2 in
149           if not(List.mem c !history) then 
150            le_constraints := List.filter ((<>) w) !le_constraints;
151      | `Constr _ -> assert false
152      ) to_be_deleted
153 ;;
154
155 exception Propagate of NUri.uri * exn;;
156
157 let to_exn f x =
158  match f x with
159     `WellTyped o -> o
160   | `Exn e -> raise e
161 ;;
162
163 let check_and_add_obj ((u,_,_,_,_) as obj) =
164  let saved_frozen_list = !frozen_list in
165  try
166    frozen_list := (u,obj)::saved_frozen_list;
167    !typecheck_obj obj;
168    frozen_list := saved_frozen_list;
169    let obj' = `WellTyped obj in
170    NUri.UriHash.add cache u obj';
171    history := (`Obj (u,obj))::!history;
172    obj'
173  with
174     Sys.Break as e ->
175      frozen_list := saved_frozen_list;
176      raise e
177   | Propagate (u',old_exn) as e' ->
178      frozen_list := saved_frozen_list;
179      let exn = `Exn (BadDependency (lazy (NUri.string_of_uri u ^
180        " depends (recursively) on " ^ NUri.string_of_uri u' ^
181        " which is not well-typed"), 
182        match old_exn with BadDependency (_,e) -> e | _ -> old_exn)) in
183      NUri.UriHash.add cache u exn;
184      history := (`Obj (u,obj))::!history;
185      if saved_frozen_list = [] then
186       exn
187      else
188       raise e'
189   | e ->
190      frozen_list := saved_frozen_list;
191      let exn = `Exn e in
192      NUri.UriHash.add cache u exn;
193      history := (`Obj (u,obj))::!history;
194      if saved_frozen_list = [] then
195       exn
196      else
197       raise (Propagate (u,e))
198 ;;
199
200 let get_checked_obj u =
201  if List.exists (fun (k,_) -> NUri.eq u k) !frozen_list
202  then
203   raise (CircularDependency (lazy (NUri.string_of_uri u)))
204  else
205   try NUri.UriHash.find cache u
206   with Not_found -> check_and_add_obj (!get_obj u)
207 ;;
208
209 let get_checked_obj u = to_exn get_checked_obj u;;
210
211 let check_and_add_obj ((u,_,_,_,_) as obj) =
212  if NUri.UriHash.mem cache u then
213   raise (AlreadyDefined (lazy (NUri.string_of_uri u)))
214  else
215   ignore (to_exn check_and_add_obj obj)
216 ;;
217
218 let get_checked_decl = function
219   | Ref.Ref (uri, Ref.Decl) ->
220       (match get_checked_obj uri with
221       | _,height,_,_, C.Constant (rlv,name,None,ty,att) ->
222           rlv,name,ty,att,height
223       | _,_,_,_, C.Constant (_,_,Some _,_,_) ->
224           prerr_endline "get_checked_decl on a definition"; assert false
225       | _ -> prerr_endline "get_checked_decl on a non decl 2"; assert false)
226   | _ -> prerr_endline "get_checked_decl on a non decl"; assert false
227 ;;
228
229 let get_checked_def = function
230   | Ref.Ref (uri, Ref.Def _) ->
231       (match get_checked_obj uri with
232       | _,height,_,_, C.Constant (rlv,name,Some bo,ty,att) ->
233           rlv,name,bo,ty,att,height
234       | _,_,_,_, C.Constant (_,_,None,_,_) ->
235           prerr_endline "get_checked_def on an axiom"; assert false
236       | _ -> prerr_endline "get_checked_def on a non def 2"; assert false)
237   | _ -> prerr_endline "get_checked_def on a non def"; assert false
238 ;;
239
240 let get_checked_indtys = function
241   | Ref.Ref (uri, (Ref.Ind (_,n,_)|Ref.Con (n,_,_))) ->
242       (match get_checked_obj uri with
243       | _,_,_,_, C.Inductive (inductive,leftno,tys,att) ->
244         inductive,leftno,tys,att,n
245       | _ -> prerr_endline "get_checked_indtys on a non ind 2"; assert false)
246   | _ -> prerr_endline "get_checked_indtys on a non ind"; assert false
247 ;;
248
249 let get_checked_fixes_or_cofixes = function
250   | Ref.Ref (uri, (Ref.Fix _|Ref.CoFix _))->
251       (match get_checked_obj uri with
252       | _,height,_,_, C.Fixpoint (_,funcs,att) ->
253          funcs, att, height
254       | _ ->prerr_endline "get_checked_(co)fix on a non (co)fix 2";assert false)
255   | _ -> prerr_endline "get_checked_(co)fix on a non (co)fix"; assert false
256 ;;
257
258 let get_relevance (Ref.Ref (_, infos) as r) =
259   match infos with
260      Ref.Def _ -> let res,_,_,_,_,_ = get_checked_def r in res
261    | Ref.Decl -> let res,_,_,_,_ = get_checked_decl r in res
262    | Ref.Ind _ ->
263        let _,_,tl,_,n = get_checked_indtys r in
264        let res,_,_,_ = List.nth tl n in
265          res
266     | Ref.Con (_,i,_) ->
267        let _,_,tl,_,n = get_checked_indtys r in
268        let _,_,_,cl = List.nth tl n in
269        let res,_,_ = List.nth cl (i - 1) in
270          res
271     | Ref.Fix (fixno,_,_)
272     | Ref.CoFix fixno ->
273         let fl,_,_ = get_checked_fixes_or_cofixes r in
274         let res,_,_,_,_ = List.nth fl fixno in
275           res
276 ;;
277
278
279 let invalidate _ = 
280   assert (!frozen_list = []);
281   NUri.UriHash.clear cache
282 ;;