Source file export.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
open Names
open EConstr
open Evd
open Catt
open Common
open Kernel
open Unchecked_types.Unchecked_types (Coh)
let run_catt_on_file f =
Prover.reset ();
match Prover.parse_file f with
| Ok f -> Command.exec ~loop_fn:Prover.loop f
| Error () -> ()
let rec catt_var_to_coq_name v =
match v with
| Var.Db i -> "catt_db_" ^ string_of_int i
| Var.Name s -> "catt_name_" ^ s
| Var.New i -> "catt_new_" ^ string_of_int i
| Var.Plus v -> catt_var_to_coq_name v ^ "_plus"
| Var.Bridge v -> catt_var_to_coq_name v ^ "_bridge"
let c_Q env sigma =
let gr = Coqlib.lib_ref "core.eq.type" in
Evd.fresh_global env sigma gr
let c_R env sigma =
let gr = Coqlib.lib_ref "core.eq.refl" in
Evd.fresh_global env sigma gr
let rec find_db ctx x =
match ctx with
| [] -> Error.fatal "variable not found"
| (y, _) :: _ when x = y -> 1
| _ :: ctx -> 1 + find_db ctx x
module Translate : sig
val tm : Environ.env -> evar_map -> ctx -> tm -> evar_map * econstr
val coh : Environ.env -> evar_map -> Coh.t -> evar_map * econstr
end = struct
let catt_to_coq_db ctx var =
match var with
| Var.Db n ->
let l = List.length ctx - n in
(EConstr.mkRel l, l)
| _ -> assert false
let induction_vars ps =
let rec find_vars_list lv start l onto =
match l with
| [] -> (start + 1, onto)
| ps :: l ->
let start, varsl = find_vars_list lv start l onto in
find_vars_ps lv (start + 1) ps varsl
and find_vars_ps lv start ps onto =
let onto = if lv > 0 then Var.Db start :: onto else onto in
match ps with Br l -> find_vars_list (lv + 1) start l onto
in
snd (find_vars_ps 0 0 ps [])
let induction_data list_vars ctx =
let find_data var =
match fst (List.assoc var ctx) with
| Obj -> assert false
| Meta_ty _ -> Error.fatal "unresolved meta variable"
| Arr (ty, s, _) -> (
match s with Var s -> (var, s, ty) | _ -> assert false)
in
List.map find_data list_vars
let abstract env sigma econstr i_lm =
let lm = Names.Id.of_string "lm" in
let tgt = Names.Id.of_string "tm_tgt" in
let econstr = EConstr.Vars.lift 2 econstr in
let econstr =
EConstr.Vars.substnl
[ EConstr.mkVar lm; EConstr.mkVar tgt ]
(i_lm + 1) econstr
in
let econstr = EConstr.Vars.subst_vars sigma [ lm; tgt ] econstr in
let econstr = EConstr.Vars.liftn 2 (i_lm + 2) econstr in
econstr
let instantiate econstr tysrc src refl =
EConstr.Vars.substl [ EConstr.mkApp (refl, [| tysrc; src |]); src ] econstr
let rec ctx_to_lambda env sigma obj_type eq_type refl ctx inner_tm =
match ctx with
| [] ->
( sigma,
EConstr.mkLambda
(nameR (Names.Id.of_string "catt_Obj"), obj_type, inner_tm) )
| (x, (ty, _)) :: ctx ->
let sigma, ty = ty_to_lambda env sigma obj_type eq_type refl ctx ty in
let id_lambda = Names.Id.of_string (catt_var_to_coq_name x) in
let lambda = EConstr.mkLambda (nameR id_lambda, ty, inner_tm) in
ctx_to_lambda env sigma obj_type eq_type refl ctx lambda
and ty_to_lambda env sigma obj_type eq_type refl ctx ty =
match ty with
| Obj -> (sigma, EConstr.mkRel (List.length ctx + 1))
| Arr (ty, u, v) ->
let sigma, ty = ty_to_lambda env sigma obj_type eq_type refl ctx ty in
let sigma, u = tm_to_lambda env sigma obj_type eq_type refl ctx u in
let sigma, v = tm_to_lambda env sigma obj_type eq_type refl ctx v in
(sigma, EConstr.mkApp (eq_type, [| ty; u; v |]))
| Meta_ty _ -> Error.fatal "unresolved type meta-variable"
and tm_to_lambda env sigma obj_type eq_type refl ctx tm =
match tm with
| Var x -> (sigma, EConstr.mkRel (find_db ctx x))
| Coh (c, s) ->
let sigma, c = coh_to_lambda env sigma eq_type refl c in
let sigma, s = sub_ps_to_lambda env sigma obj_type eq_type refl ctx s in
(sigma, EConstr.mkApp (c, s))
| Meta_tm _ -> Error.fatal "unresolved term meta-variable"
and sub_ps_to_lambda env sigma obj_type eq_type refl ctx sub_ps =
let l = List.length sub_ps in
let array = Array.make (l + 1) (EConstr.mkRel 0) in
let rec set_next i (sigma : Evd.evar_map) sub_ps =
match sub_ps with
| [] ->
Array.set array 0 (EConstr.mkRel (List.length ctx + 1));
sigma
| (t, _) :: s ->
let sigma, tm = tm_to_lambda env sigma obj_type eq_type refl ctx t in
Array.set array i tm;
set_next (i - 1) sigma s
in
(set_next l sigma sub_ps, array)
and coh_to_lambda env sigma eq_type refl coh =
let sigma, obj_type = Evarutil.new_Type sigma in
let ps, ty, _ = Coh.forget coh in
let ctx = Unchecked.ps_to_ctx ps in
let l_ind = induction_vars ps in
let l_ind = induction_data l_ind ctx in
let sigma, ty = ty_to_lambda env sigma obj_type eq_type refl ctx ty in
let (eq_ind, univ), _ = Inductiveops.find_inductive env sigma eq_type in
let catt_to_coq_db = catt_to_coq_db ctx in
let rec body l_ind ty =
match l_ind with
| [] ->
let _, args = EConstr.destApp sigma ty in
EConstr.mkApp (refl, [| args.(0); args.(1) |])
| (m, s_m, ty_m) :: l_ind ->
let v1 =
{
Context.binder_name = Names.Name.Anonymous;
Context.binder_relevance = ERelevance.relevant;
}
in
let m_coq, i_lm = catt_to_coq_db m in
let s_coq, _ = catt_to_coq_db s_m in
let sigma, ty_m_coq =
ty_to_lambda env sigma obj_type eq_type refl ctx ty_m
in
let ty = abstract env sigma ty i_lm in
let case_return = (([| v1; v1 |], ty), ERelevance.relevant) in
let ty = instantiate ty ty_m_coq s_coq refl in
let case_branches = [| ([||], body l_ind ty) |] in
let pcase =
( Inductiveops.make_case_info env eq_ind RegularStyle,
univ,
[| ty_m_coq; s_coq |],
case_return,
Constr.NoInvert,
m_coq,
case_branches )
in
EConstr.mkCase pcase
in
ctx_to_lambda env sigma obj_type eq_type refl ctx (body l_ind ty)
let tm env sigma ctx tm =
let sigma, obj_type = Evarutil.new_Type sigma in
let sigma, eq_type = c_Q env sigma in
let sigma, refl = c_R env sigma in
let sigma, tm = tm_to_lambda env sigma obj_type eq_type refl ctx tm in
ctx_to_lambda env sigma obj_type eq_type refl ctx tm
let coh env sigma coh =
let sigma, eq_type = c_Q env sigma in
let sigma, refl = c_R env sigma in
coh_to_lambda env sigma eq_type refl coh
end
let catt_tm file tm_names =
run_catt_on_file file;
let register_tm tm_name =
let env = Global.env () in
let sigma = Evd.from_env env in
let sigma, body =
match Environment.val_var (Var.Name tm_name) with
| Coh c -> Translate.coh env sigma c
| Tm (ctx, tm) -> Translate.tm env sigma ctx tm
in
let sigma, body = Typing.solve_evars env sigma body in
let body = Evarutil.nf_evar sigma body in
let info = Declare.Info.make () in
let cinfo =
Declare.CInfo.make ~name:Id.(of_string ("catt_" ^ tm_name)) ~typ:None ()
in
let gr =
Declare.declare_definition ~info ~cinfo ~opaque:false ~body sigma
in
Coqlib.register_ref ("catt." ^ tm_name) gr
in
List.iter register_tm tm_names