package universo
A tool for Dedukti to play with universes
Install
Dune Dependency
Authors
Maintainers
Sources
v2.7.tar.gz
sha512=97171b48dd96043d84587581d72edb442f63e7b5ac1695771aa1c3c9074739e15bc7d17678fedb7062acbf403a0bf323d97485c31b92376b80c63b5c2300ee3c
sha256=5e1b6a859dfa1eb2098947a99c7d11ee450f750d96da1720f4834e1505d1096c
doc/src/universo.checking/checker.ml.html
Source file checker.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250
module B = Kernel.Basic module C = Common.Constraints module F = Common.Files module L = Common.Log module M = Api.Meta module P = Api.Pp.Default module S = Kernel.Signature module T = Kernel.Term module U = Common.Universes module V = Elaboration.Var type t = { env : Api.Env.t; (** The current environement used for type checking *) in_path : F.path; (** path of the original file that should be typed checked *) meta_out : M.cfg; (** Meta configuration to translate back universes of Universo to the original theory universes *) constraints : (B.name, U.pred) Hashtbl.t; (** additional user constraints *) out_file : F.cout F.t; (** File were constraints are written *) } (* This is a reference because we have to use it in the Reduction Engine *) (** [globel_env] is a reference to the current type checking environment. *) let global_env : t option ref = ref None let get = function | None -> failwith "Environment not initialized" | Some env -> env let of_global_env env = {C.file = env.out_file; C.meta = env.meta_out} module MakeRE (Conv : Kernel.Reduction.ConvChecker) : Kernel.Reduction.S = struct module rec R : Kernel.Reduction.S = Kernel.Reduction.Make (Conv) (Kernel.Matching.Make (R)) module Rule = Kernel.Rule include R (** Name for rules that reduce variables. Names are irrelevant for Universo. *) let dummy_name = Rule.Gamma (false, B.mk_name (B.mk_mident "dummy") (B.mk_ident "dummy")) (* FIXME: this rules are not exported hence redundant rules might be added when the current module is impoted somewhere else *) (** [add_rule vl vr] add to the current signature the rule that maps [vl] to [vr]. *) let rec add_rule vl vr = let pat = Rule.Pattern (B.dloc, vl, []) in let rhs = T.mk_Const B.dloc vr in let rule = Rule.{ctx = []; pat; rhs; name = dummy_name} in let sg = Api.Env.get_signature (get !global_env).env in S.add_rules sg [Rule.to_rule_infos rule] and univ_conversion l r = let sg = Api.Env.get_signature (get !global_env).env in if T.term_eq l r then true else if (* If two universes should be equal, then we add the constraint [l =?= r] AND a rule that makes [l] convertible to [r]. Order matters and is handled by the module U. *) V.is_uvar l && V.is_uvar r then C.mk_cstr (of_global_env (get !global_env)) add_rule (U.EqVar (V.name_of_uvar l, V.name_of_uvar r)) else if V.is_uvar l && U.is_enum r then ( let r = U.extract_univ r in ignore (C.mk_cstr (of_global_env (get !global_env)) add_rule (U.Pred (U.Cumul (Var (V.name_of_uvar l), r)))); C.mk_cstr (of_global_env (get !global_env)) add_rule (U.Pred (U.Cumul (r, Var (V.name_of_uvar l))))) else if V.is_uvar r && U.is_enum l then ( let l = U.extract_univ l in ignore (C.mk_cstr (of_global_env (get !global_env)) add_rule (U.Pred (U.Cumul (Var (V.name_of_uvar r), l)))); C.mk_cstr (of_global_env (get !global_env)) add_rule (U.Pred (U.Cumul (l, Var (V.name_of_uvar r)))) (* The witness of a universe constraint is always I. It's type should should be convertible to true. Knowing Dedukti behavior, the expected type is the left one (true) and the right one is the predicate to satisfy *)) else if T.term_eq (U.true_ ()) l then if U.is_subtype r then let s = U.extract_subtype r in are_convertible sg (U.true_ ()) s else if U.is_forall r then let s = U.extract_forall r in are_convertible sg (U.true_ ()) s else C.mk_cstr (of_global_env (get !global_env)) add_rule (U.Pred (U.extract_pred r)) (* Encoding of cumulativity uses the rule cast _ _ A A t --> t. Hence, sometimes [lift ss a =?= a]. This case is not capture by the cases above. This quite ugly to be so dependent of that rule, but I have found no nice solution to resolve that one. *) else if U.is_cast' l && not (U.is_cast' r) then let _, _, a, b, t = U.extract_cast' l in are_convertible sg a b && are_convertible sg t r else if (not (U.is_cast' l)) && U.is_cast' r then let _, _, a, b, t = U.extract_cast' r in are_convertible sg a b && are_convertible sg l t else (* TODO: One should handle one more case with Cumul. Currentl Cumul is assumed being linear but it is hackish because it assumes a theory file where the order of rules matter. In particular, having Cumul linear forces to have the non linear rule for Subtype first. Otherwise, the system is not confluent. However, having Cumul non linear requires to add more cases here. Non linearity should be also handled in matching_test function. *) false and are_convertible_lst sg : (T.term * T.term) list -> bool = function | [] -> true | (l, r) :: lst -> if T.term_eq l r then are_convertible_lst sg lst else (*Format.printf "l:%a@." Pp.print_term l; Format.printf "r:%a@." Pp.print_term r; *) let l', r' = (whnf sg l, whnf sg r) in (* Format.printf "l':%a@." Pp.print_term l'; Format.printf "r':%a@." Pp.print_term r'; *) if univ_conversion l' r' then are_convertible_lst sg lst else are_convertible_lst sg (R.conversion_step sg (l', r') lst) and are_convertible sg t1 t2 = try are_convertible_lst sg [(t1, t2)] with Kernel.Reduction.Not_convertible -> false and constraint_convertibility _cstr r sg t1 t2 = if T.term_eq t1 t2 then true else match r with | Rule.Gamma (_, rn) -> (* We need to avoid non linear rule of the theory otherwise we may produce inconsistent constraints: lift s s' a should not always reduce to a.*) if B.string_of_ident (B.id rn) = "id_cast" then false else are_convertible sg t1 t2 | _ -> are_convertible sg t1 t2 end module rec RE : Kernel.Reduction.S = MakeRE (RE) module Typing = Kernel.Typing.Make (RE) (** [check_user_constraints table name t] checks whether the user has added constraints on the onstant [name] and if so, add this constraint. In [t], every universo variable (md.var) are replaced by the sort associated to the constant [name]. *) let check_user_constraints : (B.name, U.pred) Hashtbl.t -> B.name -> T.term -> unit = fun constraints name ty -> let get_uvar ty = match ty with | T.App (_, (T.Const (_, name) as t), _) when V.is_uvar t -> name | _ -> assert false in if Hashtbl.mem constraints name then let pred = Hashtbl.find constraints name in let uvar = get_uvar ty in let replace_univ : U.univ -> U.univ = function | Var _ -> Var uvar | _ as t -> t in let replace : U.pred -> U.pred = function | Axiom (s, s') -> Axiom (replace_univ s, replace_univ s') | Cumul (s, s') -> Cumul (replace_univ s, replace_univ s') | Rule (s, s', s'') -> Rule (replace_univ s, replace_univ s', replace_univ s'') in ignore (C.mk_cstr (of_global_env (get !global_env)) (fun _ -> assert false) (U.Pred (replace pred))) (* TODO: universo_env and env should be only one *) (** [mk_entry env e] type checks the entry e in the same way then dkcheck does. However, the convertibility tests is hacked so that we can add constraints dynamically while type checking the term. This is really close to what is done with typical ambiguity in Coq. *) let mk_entry : t -> Api.Env.t -> Parsers.Entry.entry -> unit = fun universo_env env e -> let module E = Parsers.Entry in let module Rule = Kernel.Rule in global_env := Some universo_env; let sg = Api.Env.get_signature universo_env.env in let _add_rules rs = let ris = List.map Rule.to_rule_infos rs in S.add_rules sg ris in match e with | Decl (lc, id, sc, st, ty) -> ( L.log_check "[CHECKING] %a" P.print_ident id; check_user_constraints universo_env.constraints (B.mk_name (F.md_of universo_env.in_path `Output) id) ty; Format.fprintf (F.fmt_of_file universo_env.out_file) "@.(; %a ;)@." P.print_ident id; match Typing.inference sg ty with | Kind | Type _ -> S.add_declaration sg lc id sc st ty | s -> raise (Kernel.Typing.Typing_error (Kernel.Typing.SortExpected (ty, [], s))) ) | Def (lc, id, sc, opaque, mty, te) -> ( L.log_check "[CHECKING] %a" P.print_ident id; Format.fprintf (F.fmt_of_file universo_env.out_file) "@.(; %a ;)@." P.print_ident id; let open Rule in let ty = match mty with | None -> Typing.inference sg te | Some ty -> Typing.checking sg te ty; ty in match ty with | Kind -> raise (Api.Env.Env_error ( env, lc, Kernel.Typing.Typing_error Kernel.Typing.KindIsNotTypable )) | _ -> if opaque then S.add_declaration sg lc id sc S.Static ty else let _ = S.add_declaration sg lc id sc (S.Definable T.Free) ty in let cst = B.mk_name (F.md_of (get !global_env).in_path `Output) id in let rule = { name = Delta cst; ctx = []; pat = Pattern (lc, cst, []); rhs = te; } in _add_rules [rule]) | Rules (_, rs) -> let open Rule in let _ = List.map (fun (r : partially_typed_rule) -> Format.fprintf (F.fmt_of_file universo_env.out_file) "@.(; %a ;)@." Rule.pp_rule_name r.name; Typing.check_rule sg r) rs in _add_rules rs | Require _ -> () (* FIXME: How should we handle a Require command? *) | _ -> assert false (* other commands are not supported by this is only by lazyness. *)
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>