package coq-core
The Coq Proof Assistant -- Core Binaries and Tools
Install
Dune Dependency
Authors
Maintainers
Sources
coq-8.20.1.tar.gz
md5=0cfaa70f569be9494d24c829e6555d46
sha512=8ee967c636b67b22a4f34115871d8f9b9114df309afc9ddf5f61275251088c6e21f6cf745811df75554d30f4cebb6682f23eeb2e88b771330c4b60ce3f6bf5e2
doc/src/ltac2_plugin/tac2interp.ml.html
Source file tac2interp.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 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299
(************************************************************************) (* * The Coq Proof Assistant / The Coq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* <O___,, * (see version control and CREDITS file for authors & dates) *) (* \VV/ **************************************************************) (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (* * (see LICENSE file for the text of the license) *) (************************************************************************) open Util open Pp open CErrors open Names open Proofview.Notations open Tac2expr open Tac2val open Tac2bt exception LtacError = Tac2ffi.LtacError type environment = Tac2env.environment = { env_ist : valexpr Id.Map.t; } let empty_environment = { env_ist = Id.Map.empty; } type closure = { mutable clos_env : valexpr Id.Map.t; (** Mutable so that we can implement recursive functions imperatively *) clos_var : Name.t list; (** Bound variables *) clos_exp : glb_tacexpr; (** Body *) clos_ref : ltac_constant option; (** Global constant from which the closure originates *) } let push_id ist id v = { env_ist = Id.Map.add id v ist.env_ist } let push_name ist id v = match id with | Anonymous -> ist | Name id -> push_id ist id v let get_var ist id = try Id.Map.find id ist.env_ist with Not_found -> anomaly (str "Unbound variable " ++ Id.print id) let get_ref ist kn = try let data = Tac2env.interp_global kn in data.Tac2env.gdata_expr with Not_found -> anomaly (str "Unbound reference" ++ KerName.print kn) let return = Proofview.tclUNIT exception NoMatch let match_ctor_against ctor v = match ctor, v with | { cindx = Open ctor }, ValOpn (ctor', vs) -> if KerName.equal ctor ctor' then vs else raise NoMatch | { cindx = Open _ }, _ -> assert false | { cnargs = 0; cindx = Closed i }, ValInt i' -> if Int.equal i i' then [| |] else raise NoMatch | { cnargs = 0; cindx = Closed _ }, ValBlk _ -> raise NoMatch | _, ValInt _ -> raise NoMatch | { cindx = Closed i }, ValBlk (i', vs) -> if Int.equal i i' then vs else raise NoMatch | { cindx = Closed _ }, ValOpn _ -> assert false | _, (ValStr _ | ValCls _ | ValExt _) -> assert false let check_atom_against atm v = match atm, v with | AtmInt n, ValInt n' -> if not (Int.equal n n') then raise NoMatch | AtmStr s, ValStr s' -> if not (String.equal s (Bytes.unsafe_to_string s')) then raise NoMatch | (AtmInt _ | AtmStr _), _ -> assert false let rec match_pattern_against ist pat v = match pat with | GPatVar x -> push_name ist x v | GPatAtm atm -> check_atom_against atm v; ist | GPatAs (p,x) -> match_pattern_against (push_name ist (Name x) v) p v | GPatRef (ctor,pats) -> let vs = match_ctor_against ctor v in List.fold_left_i (fun i ist pat -> match_pattern_against ist pat vs.(i)) 0 ist pats | GPatOr pats -> match_pattern_against_or ist pats v and match_pattern_against_or ist pats v = match pats with | [] -> raise NoMatch | pat :: pats -> try match_pattern_against ist pat v with NoMatch -> match_pattern_against_or ist pats v let eval_glb_ext ist (Tac2dyn.Arg.Glb (tag,e)) = let tpe = Tac2env.interp_ml_object tag in with_frame (FrExtn (tag, e)) (tpe.Tac2env.ml_interp ist e) let rec interp (ist : environment) = function | GTacAtm (AtmInt n) -> return (Tac2ffi.of_int n) | GTacAtm (AtmStr s) -> return (Tac2ffi.of_string s) | GTacVar id -> return (get_var ist id) | GTacRef kn -> begin match Tac2env.get_compiled_global kn with | Some (_info,v) -> return v | None -> let data = get_ref ist kn in return (eval_pure Id.Map.empty (Some kn) data) end | GTacFun (ids, e) -> let cls = { clos_ref = None; clos_env = ist.env_ist; clos_var = ids; clos_exp = e } in let f = interp_closure cls in return f | GTacApp (f, args) -> interp ist f >>= fun f -> Proofview.Monad.List.map (fun e -> interp ist e) args >>= fun args -> Tac2val.apply_val f args | GTacLet (false, el, e) -> let fold accu (na, e) = interp ist e >>= fun e -> return (push_name accu na e) in Proofview.Monad.List.fold_left fold ist el >>= fun ist -> interp ist e | GTacLet (true, el, e) -> let ist = push_let_rec ist.env_ist el in interp { env_ist = ist } e | GTacCst (_, n, []) -> return (Valexpr.make_int n) | GTacCst (_, n, el) -> Proofview.Monad.List.map (fun e -> interp ist e) el >>= fun el -> return (Valexpr.make_block n (Array.of_list el)) | GTacCse (e, _, cse0, cse1) -> interp ist e >>= fun e -> interp_case ist e cse0 cse1 | GTacWth { opn_match = e; opn_branch = cse; opn_default = def } -> interp ist e >>= fun e -> interp_with ist e cse def | GTacFullMatch (e,brs) -> interp ist e >>= fun e -> interp_full_match ist e brs | GTacPrj (_, e, p) -> interp ist e >>= fun e -> interp_proj ist e p | GTacSet (_, e, p, r) -> interp ist e >>= fun e -> interp ist r >>= fun r -> interp_set ist e p r | GTacOpn (kn, el) -> Proofview.Monad.List.map (fun e -> interp ist e) el >>= fun el -> return (Tac2ffi.of_open (kn, Array.of_list el)) | GTacPrm ml -> return (Tac2env.interp_primitive ml) | GTacExt (tag, e) -> eval_glb_ext ist (Glb (tag,e)) and push_let_rec ist el = let map (na, e) = match e with | GTacFun (ids, e) -> let cls = { clos_ref = None; clos_env = ist; clos_var = ids; clos_exp = e } in let f = interp_closure cls in na, cls, f | _ -> anomaly (str "Ill-formed recursive function") in let fixs = List.map map el in let fold accu (na, _, cls) =match na with | Anonymous -> accu | Name id -> Id.Map.add id cls accu in let ist = List.fold_left fold ist fixs in (* Hack to make a cycle imperatively in the environment *) let iter (_, e, _) = e.clos_env <- ist in let () = List.iter iter fixs in ist and interp_closure f = let ans = fun args -> let { clos_env = ist; clos_var = ids; clos_exp = e; clos_ref = kn } = f in let frame = match kn with | None -> FrAnon e | Some kn -> FrLtac kn in let ist = { env_ist = ist } in let ist = List.fold_left2 push_name ist ids args in with_frame frame (interp ist e) in Tac2ffi.(of_closure (abstract (List.length f.clos_var) ans)) and interp_case ist e cse0 cse1 = if Valexpr.is_int e then interp ist cse0.(Tac2ffi.to_int e) else let (n, args) = Tac2ffi.to_block e in let (ids, e) = cse1.(n) in let ist = CArray.fold_left2 push_name ist ids args in interp ist e and interp_with ist e cse def = let (kn, args) = Tac2ffi.to_open e in let br = try Some (KNmap.find kn cse) with Not_found -> None in begin match br with | None -> let (self, def) = def in let ist = push_name ist self e in interp ist def | Some (self, ids, p) -> let ist = push_name ist self e in let ist = CArray.fold_left2 push_name ist ids args in interp ist p end and interp_full_match ist e = function | [] -> CErrors.anomaly Pp.(str "ltac2 match not exhaustive") | (pat,br) :: rest -> begin match match_pattern_against ist pat e with | exception NoMatch -> interp_full_match ist e rest | ist -> interp ist br end and interp_proj ist e p = return (Valexpr.field e p) and interp_set ist e p r = let () = Valexpr.set_field e p r in return (Valexpr.make_int 0) and eval_pure bnd kn = function | GTacVar id -> Id.Map.get id bnd | GTacAtm (AtmInt n) -> Valexpr.make_int n | GTacRef kn -> begin match Tac2env.get_compiled_global kn with | Some (_info,v) -> v | None -> let { Tac2env.gdata_expr = e } = try Tac2env.interp_global kn with Not_found -> assert false in eval_pure bnd (Some kn) e end | GTacFun (na, e) -> let cls = { clos_ref = kn; clos_env = bnd; clos_var = na; clos_exp = e } in interp_closure cls | GTacCst (_, n, []) -> Valexpr.make_int n | GTacCst (_, n, el) -> Valexpr.make_block n (eval_pure_args bnd el) | GTacOpn (kn, el) -> Tac2ffi.of_open (kn, eval_pure_args bnd el) | GTacLet (false, vals, body) -> let fold accu (na, e) = match na with | Anonymous -> (* No need to evaluate, we know this is a value *) accu | Name id -> let v = eval_pure bnd None e in Id.Map.add id v accu in let bnd = List.fold_left fold bnd vals in eval_pure bnd kn body | GTacLet (true, el, body) -> let bnd = push_let_rec bnd el in eval_pure bnd kn body | GTacPrj (_,e,i) -> let v = eval_pure bnd kn e in Valexpr.field v i | GTacPrm ml -> Tac2env.interp_primitive ml | GTacAtm (AtmStr _) | GTacSet _ | GTacApp _ | GTacCse _ | GTacExt _ | GTacWth _ | GTacFullMatch _ -> anomaly (Pp.str "Term is not a syntactical value") and eval_pure_args bnd args = let map e = eval_pure bnd None e in Array.map_of_list map args let interp_value ist tac = eval_pure ist.env_ist None tac let eval_global kn = eval_pure Id.Map.empty (Some kn) (Tac2env.interp_global kn).gdata_expr (** Cross-boundary hacks. *) open Geninterp let val_env : environment Val.typ = Val.create "ltac2:env" let env_ref = Id.of_string_soft "@@ltac2_env@@" let extract_env (Val.Dyn (tag, v)) : environment = match Val.eq tag val_env with | None -> assert false | Some Refl -> v let get_env ist = try extract_env (Id.Map.find env_ref ist) with Not_found -> empty_environment let set_env env ist = Id.Map.add env_ref (Val.Dyn (val_env, env)) ist
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>