X-Git-Url: http://matita.cs.unibo.it/gitweb/?a=blobdiff_plain;f=helm%2Fsoftware%2Fcomponents%2Fng_kernel%2FnCicEnvironment.ml;h=b3b1eda16eab228c19944d7f7f176e2ffd6433e9;hb=20427121e8114fa60b64bd1669a0fc734bf39205;hp=1e2cd913e8074a70226b3b067f20840ba6a7ba35;hpb=7d6f47c980081e06fee46c08d5b5bd7faf1e6aa9;p=helm.git diff --git a/helm/software/components/ng_kernel/nCicEnvironment.ml b/helm/software/components/ng_kernel/nCicEnvironment.ml index 1e2cd913e..b3b1eda16 100644 --- a/helm/software/components/ng_kernel/nCicEnvironment.ml +++ b/helm/software/components/ng_kernel/nCicEnvironment.ml @@ -1,93 +1,282 @@ +(* + ||M|| This file is part of HELM, an Hypertextual, Electronic + ||A|| Library of Mathematics, developed at the Computer Science + ||T|| Department, University of Bologna, Italy. + ||I|| + ||T|| HELM is free software; you can redistribute it and/or + ||A|| modify it under the terms of the GNU General Public License + \ / version 2 or (at your option) any later version. + \ / This software is distributed as is, NO WARRANTY. + V_______________________________________________________________ *) + +(* $Id$ *) + +module C = NCic +module Ref = NReference + +exception CircularDependency of string Lazy.t;; +exception ObjectNotFound of string Lazy.t;; +exception BadDependency of string Lazy.t * exn;; +exception BadConstraint of string Lazy.t;; +exception AlreadyDefined of string Lazy.t;; + let cache = NUri.UriHash.create 313;; +let history = ref [];; +let frozen_list = ref [];; + +let get_obj = ref (fun _ -> assert false);; +let set_get_obj f = get_obj := f;; + +let type0 = [] + +let max l1 l2 = + HExtlib.list_uniq ~eq:(fun (b1,u1) (b2,u2) -> b1=b2 && NUri.eq u1 u2) + (List.sort (fun (b1,u1) (b2,u2) -> + let res = compare b1 b2 in if res = 0 then NUri.compare u1 u2 else res) + (l1 @ l2)) + +let le_constraints = ref [] (* strict,a,b *) + +let rec le_path_uri avoid strict a b = + (not strict && NUri.eq a b) || + List.exists + (fun (strict',x,y) -> + NUri.eq y b && not (List.exists (NUri.eq x) avoid) && + le_path_uri (x::avoid) (strict && not strict') a x + ) !le_constraints +;; + +let leq_path a b = le_path_uri [b] (fst a) (snd a) b;; + +let universe_leq a b = + match a, b with + | a,[(false,b)] -> List.for_all (fun a -> leq_path a b) a + | _,_ -> + raise (BadConstraint + (lazy "trying to check if a universe is less or equal than an inferred universe")) + +let universe_eq a b = + match a,b with + | [(false,_)], [(false,_)] -> universe_leq b a && universe_leq a b + | _, [(false,_)] + | [(false,_)],_ -> false + | _ -> + raise (BadConstraint + (lazy "trying to check if two inferred universes are equal")) +;; + +let pp_constraint b x y = + NUri.name_of_uri x ^ (if b then " < " else " <= ") ^ NUri.name_of_uri y +;; + +let pp_constraints () = + String.concat "\n" (List.map (fun (b,x,y) -> pp_constraint b x y) !le_constraints) +;; + +let universes = ref [];; + +let get_universes () = List.map (fun x -> [false,x]) !universes;; -let oldg = ref CicUniv.empty_ugraph;; +let is_declared u = + match u with + [false,x] -> List.exists (fun y -> NUri.eq x y) !universes + | _ -> assert false +;; + +let add_constraint strict a b = + match a,b with + | [false,a2],[false,b2] -> + if not (le_path_uri [] strict a2 b2) then ( + if le_path_uri [] (not strict) b2 a2 then + (raise(BadConstraint(lazy("universe inconsistency adding "^pp_constraint strict a2 b2 + ^ " to:\n" ^ pp_constraints ())))); + universes := a2 :: b2 :: + List.filter (fun x -> not (NUri.eq x a2 || NUri.eq x b2)) !universes; + le_constraints := (strict,a2,b2) :: !le_constraints); + history := (`Constr (strict,a,b))::!history; + | _ -> raise (BadConstraint + (lazy "trying to add a constraint on an inferred universe")) +;; + +let sup l = + match l with + | [false,_] -> Some l + | l -> + let bigger_than acc (s1,n1) = List.filter (le_path_uri [] s1 n1) acc in + let solutions = List.fold_left bigger_than !universes l in + let rec aux = function + | [] -> None + | u :: tl -> + if List.exists (fun x -> le_path_uri [] true x u) solutions then aux tl + else Some [false,u] + in + aux solutions +;; + + + +let typecheck_obj,already_set = ref (fun _ -> assert false), ref false;; +let set_typecheck_obj f = + if !already_set then + assert false + else + begin + typecheck_obj := f; + already_set := true + end +;; + +let invalidate_item item = + let item_eq a b = + match a, b with + | `Obj (u1,_), `Obj (u2,_) -> NUri.eq u1 u2 + | `Constr _, `Constr _ -> a=b (* MAKE EFFICIENT *) + | _ -> false + in + let rec aux to_be_deleted = + function + [] -> assert false + | item'::tl when item_eq item item' -> item'::to_be_deleted,tl + | item'::tl -> aux (item'::to_be_deleted) tl + in + let to_be_deleted,h = aux [] !history in + history := h; + List.iter + (function + | `Obj (uri,_) -> NUri.UriHash.remove cache uri + | `Constr (strict,[_,u1],[_,u2]) as c -> + let w = strict,u1,u2 in + if not(List.mem c !history) then + le_constraints := List.filter ((<>) w) !le_constraints; + | `Constr _ -> assert false + ) to_be_deleted +;; + +exception Propagate of NUri.uri * exn;; -let load_graph uri = - let _,g = CicEnvironment.get_obj !oldg uri in - oldg := g +let to_exn f x = + match f x with + `WellTyped o -> o + | `Exn e -> raise e ;; -let get_graph _ = !oldg;; +let check_and_add_obj ((u,_,_,_,_) as obj) = + let saved_frozen_list = !frozen_list in + try + frozen_list := (u,obj)::saved_frozen_list; + !typecheck_obj obj; + frozen_list := saved_frozen_list; + let obj' = `WellTyped obj in + NUri.UriHash.add cache u obj'; + history := (`Obj (u,obj))::!history; + obj' + with + Sys.Break as e -> + frozen_list := saved_frozen_list; + raise e + | Propagate (u',old_exn) as e' -> + frozen_list := saved_frozen_list; + let exn = `Exn (BadDependency (lazy (NUri.string_of_uri u ^ + " depends (recursively) on " ^ NUri.string_of_uri u' ^ + " which is not well-typed"), + match old_exn with BadDependency (_,e) -> e | _ -> old_exn)) in + NUri.UriHash.add cache u exn; + history := (`Obj (u,obj))::!history; + if saved_frozen_list = [] then + exn + else + raise e' + | e -> + frozen_list := saved_frozen_list; + let exn = `Exn e in + NUri.UriHash.add cache u exn; + history := (`Obj (u,obj))::!history; + if saved_frozen_list = [] then + exn + else + raise (Propagate (u,e)) +;; let get_checked_obj u = - try let b, o = NUri.UriHash.find cache u in - if not b then assert false else o - with Not_found -> - let ouri = NUri.ouri_of_nuri u in - let o,_ = - try - CicEnvironment.get_obj CicUniv.oblivion_ugraph ouri - with exn -> prerr_endline (UriManager.string_of_uri ouri); raise exn - in - (* FIX: add all objects to the environment and give back the last one *) - let l = OCic2NCic.convert_obj ouri o in - List.iter (fun (u,_,_,_,_ as o) -> -(* prerr_endline ("+"^NUri.string_of_uri u); *) - NUri.UriHash.add cache u (false,o)) l; - HExtlib.list_last l -;; - -let get_obj u = + if List.exists (fun (k,_) -> NUri.eq u k) !frozen_list + then + raise (CircularDependency (lazy (NUri.string_of_uri u))) + else try NUri.UriHash.find cache u - with Not_found -> - (* in th final implementation should get it from disk *) - let ouri = NUri.ouri_of_nuri u in - let o,_ = CicEnvironment.get_obj CicUniv.oblivion_ugraph ouri in - let l = OCic2NCic.convert_obj ouri o in - List.iter (fun (u,_,_,_,_ as o) -> -(* prerr_endline ("+"^NUri.string_of_uri u); *) - NUri.UriHash.add cache u (false,o)) l; - false, HExtlib.list_last l + with Not_found -> check_and_add_obj (!get_obj u) +;; + +let get_checked_obj u = to_exn get_checked_obj u;; + +let check_and_add_obj ((u,_,_,_,_) as obj) = + if NUri.UriHash.mem cache u then + raise (AlreadyDefined (lazy (NUri.string_of_uri u))) + else + ignore (to_exn check_and_add_obj obj) ;; -let add_obj (u,_,_,_,_ as o) = - NUri.UriHash.replace cache u (true, o) +let get_checked_decl = function + | Ref.Ref (uri, Ref.Decl) -> + (match get_checked_obj uri with + | _,height,_,_, C.Constant (rlv,name,None,ty,att) -> + rlv,name,ty,att,height + | _,_,_,_, C.Constant (_,_,Some _,_,_) -> + prerr_endline "get_checked_decl on a definition"; assert false + | _ -> prerr_endline "get_checked_decl on a non decl 2"; assert false) + | _ -> prerr_endline "get_checked_decl on a non decl"; assert false ;; let get_checked_def = function - | NReference.Ref (_, uri, NReference.Def) -> + | Ref.Ref (uri, Ref.Def _) -> (match get_checked_obj uri with - | _,height,_,_, NCic.Constant (rlv,name,Some bo,ty,att) -> + | _,height,_,_, C.Constant (rlv,name,Some bo,ty,att) -> rlv,name,bo,ty,att,height - | _,_,_,_, NCic.Constant (_,_,None,_,_) -> + | _,_,_,_, C.Constant (_,_,None,_,_) -> prerr_endline "get_checked_def on an axiom"; assert false | _ -> prerr_endline "get_checked_def on a non def 2"; assert false) | _ -> prerr_endline "get_checked_def on a non def"; assert false ;; let get_checked_indtys = function - | NReference.Ref (_, uri, (NReference.Ind n|NReference.Con (n,_))) -> + | Ref.Ref (uri, (Ref.Ind (_,n,_)|Ref.Con (n,_,_))) -> (match get_checked_obj uri with - | _,_,_,_, NCic.Inductive (inductive,leftno,tys,att) -> + | _,_,_,_, C.Inductive (inductive,leftno,tys,att) -> inductive,leftno,tys,att,n | _ -> prerr_endline "get_checked_indtys on a non ind 2"; assert false) | _ -> prerr_endline "get_checked_indtys on a non ind"; assert false ;; -let get_checked_fix_or_cofix b = function - | NReference.Ref (_, uri, (NReference.Fix (fixno,_)|NReference.CoFix fixno))-> +let get_checked_fixes_or_cofixes = function + | Ref.Ref (uri, (Ref.Fix _|Ref.CoFix _))-> (match get_checked_obj uri with - | _,height,_,_, NCic.Fixpoint (is_fix,funcs,att) when is_fix = b -> + | _,height,_,_, C.Fixpoint (_,funcs,att) -> funcs, att, height | _ ->prerr_endline "get_checked_(co)fix on a non (co)fix 2";assert false) - | r -> prerr_endline ("get_checked_(co)fix on " ^ NReference.string_of_reference r); assert false + | _ -> prerr_endline "get_checked_(co)fix on a non (co)fix"; assert false ;; -let get_checked_fixes r = get_checked_fix_or_cofix true r;; -let get_checked_cofixes r = get_checked_fix_or_cofix false r;; -let get_indty_leftno = function - | NReference.Ref (_, uri, NReference.Ind _) - | NReference.Ref (_, uri, NReference.Con _) -> - (match get_checked_obj uri with - | _,_,_,_, NCic.Inductive (_,left,_,_) -> left - | _ ->prerr_endline "get_indty_leftno called on a non ind 2";assert false) - | _ -> prerr_endline "get_indty_leftno called on a non indty";assert false +let get_relevance (Ref.Ref (_, infos) as r) = + match infos with + Ref.Def _ -> let res,_,_,_,_,_ = get_checked_def r in res + | Ref.Decl -> let res,_,_,_,_ = get_checked_decl r in res + | Ref.Ind _ -> + let _,_,tl,_,n = get_checked_indtys r in + let res,_,_,_ = List.nth tl n in + res + | Ref.Con (_,i,_) -> + let _,_,tl,_,n = get_checked_indtys r in + let _,_,_,cl = List.nth tl n in + let res,_,_ = List.nth cl (i - 1) in + res + | Ref.Fix (fixno,_,_) + | Ref.CoFix fixno -> + let fl,_,_ = get_checked_fixes_or_cofixes r in + let res,_,_,_,_ = List.nth fl fixno in + res ;; + let invalidate _ = - List.iter - (fun (k,v) -> - NUri.UriHash.replace cache k (false,v)) - (NUri.UriHash.fold (fun k v -> (@) [k,snd v]) cache []) + assert (!frozen_list = []); + NUri.UriHash.clear cache ;; -