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
|
(***********************************************************************)
(* v * The Coq Proof Assistant / The Coq Development Team *)
(* <O___,, * INRIA-Rocquencourt & LRI-CNRS-Orsay *)
(* \VV/ *************************************************************)
(* // * This file is distributed under the terms of the *)
(* * GNU Lesser General Public License Version 2.1 *)
(***********************************************************************)
(*i camlp4deps: "parsing/grammar.cma" i*)
(* $Id$ *)
open Names
open Pp
open Proof_type
open Tacinterp
open Tacmach
open Term
open Typing
open Util
open Vernacinterp
open Vernacexpr
open Tacexpr
(* Interpretation of constr's *)
let constr_of c = Constrintern.interp_constr Evd.empty (Global.env()) c
(* Construction of constants *)
let constant dir s = Coqlib.gen_constant "Field" ("field"::dir) s
(* To deal with the optional arguments *)
let constr_of_opt a opt =
let ac = constr_of a in
match opt with
| None -> mkApp ((constant ["Field_Compl"] "None"),[|ac|])
| Some f -> mkApp ((constant ["Field_Compl"] "Some"),[|ac;constr_of f|])
(* Table of theories *)
let th_tab = ref (Gmap.empty : (constr,constr) Gmap.t)
let lookup typ = Gmap.find typ !th_tab
let _ =
let init () = th_tab := Gmap.empty in
let freeze () = !th_tab in
let unfreeze fs = th_tab := fs in
Summary.declare_summary "field"
{ Summary.freeze_function = freeze;
Summary.unfreeze_function = unfreeze;
Summary.init_function = init;
Summary.survive_section = false }
let load_addfield _ = ()
let cache_addfield (_,(typ,th)) = th_tab := Gmap.add typ th !th_tab
let subst_addfield (_,subst,(typ,th as obj)) =
let typ' = subst_mps subst typ in
let th' = subst_mps subst th in
if typ' == typ && th' == th then obj else
(typ',th')
let export_addfield x = Some x
(* Declaration of the Add Field library object *)
let (in_addfield,out_addfield)=
Libobject.declare_object {(Libobject.default_object "ADD_FIELD") with
Libobject.open_function = (fun i o -> if i=1 then cache_addfield o);
Libobject.cache_function = cache_addfield;
Libobject.subst_function = subst_addfield;
Libobject.classify_function = (fun (_,a) -> Libobject.Substitute a);
Libobject.export_function = export_addfield }
(* Adds a theory to the table *)
let add_field a aplus amult aone azero aopp aeq ainv aminus_o adiv_o rth
ainv_l =
begin
(try
Ring.add_theory true true false a None None None aplus amult aone azero
(Some aopp) aeq rth Quote.ConstrSet.empty
with | UserError("Add Semi Ring",_) -> ());
let th = mkApp ((constant ["Field_Theory"] "Build_Field_Theory"),
[|a;aplus;amult;aone;azero;aopp;aeq;ainv;aminus_o;adiv_o;rth;ainv_l|]) in
begin
let _ = type_of (Global.env ()) Evd.empty th in ();
Lib.add_anonymous_leaf (in_addfield (a,th))
end
end
(* Vernac command declaration *)
open Extend
open Pcoq
open Genarg
let wit_minus_div_arg, rawwit_minus_div_arg = Genarg.create_arg "minus_div_arg"
let minus_div_arg = create_generic_entry "minus_div_arg" rawwit_minus_div_arg
let _ = Tacinterp.add_genarg_interp "minus_div_arg"
(fun ist gl x ->
(in_gen wit_minus_div_arg
(out_gen (wit_pair (wit_opt wit_constr) (wit_opt wit_constr))
(Tacinterp.genarg_interp ist gl
(in_gen (wit_pair (wit_opt rawwit_constr) (wit_opt rawwit_constr))
(out_gen rawwit_minus_div_arg x))))))
open Ppconstrnew
let pp_minus_div_arg (omin,odiv) = str "still no printer for minus_div_arg"
let pp_raw_minus_div_arg (omin,odiv) =
if omin=None && odiv=None then mt() else
spc() ++ str "with" ++
pr_opt (fun c -> str "minus := " ++ pr_constr c) omin ++
pr_opt (fun c -> str "div := " ++ pr_constr c) odiv
let () =
Pptactic.declare_extra_genarg_pprule true
(rawwit_minus_div_arg,pp_raw_minus_div_arg)
(wit_minus_div_arg,pp_minus_div_arg)
open Pcoq.Constr
GEXTEND Gram
GLOBAL: minus_div_arg;
minus_arg: [ [ IDENT "minus"; ":="; aminus = constr -> aminus ] ];
div_arg: [ [ IDENT "div"; ":="; adiv = constr -> adiv ] ];
minus_div_arg:
[ [ "with"; m = minus_arg; d = OPT div_arg -> Some m, d
| "with"; d = div_arg; m = OPT minus_arg -> m, Some d
| -> None, None ] ];
END
VERNAC COMMAND EXTEND Field
[ "Add" "Field"
constr(a) constr(aplus) constr(amult) constr(aone)
constr(azero) constr(aopp) constr(aeq)
constr(ainv) constr(rth) constr(ainv_l) minus_div_arg(md) ]
-> [ let (aminus_o, adiv_o) = md in
add_field
(constr_of a) (constr_of aplus) (constr_of amult)
(constr_of aone) (constr_of azero) (constr_of aopp)
(constr_of aeq) (constr_of ainv) (constr_of_opt a aminus_o)
(constr_of_opt a adiv_o) (constr_of rth) (constr_of ainv_l) ]
END
(* Guesses the type and calls Field_Gen with the right theory *)
let field g =
Library.check_required_library ["Coq";"field";"Field"];
let ist = { lfun=[]; lmatch=[]; debug=get_debug () } in
let typ = constr_of_VConstr (pf_env g) (val_interp ist g
<:tactic<
Match Context With
| [|- (eq ?1 ? ?)] -> ?1
| [|- (eqT ?1 ? ?)] -> ?1>>) in
let th = VConstr (lookup typ) in
(tac_interp [(id_of_string "FT",th)] [] (get_debug ())
<:tactic<
Match Context With
| [|- (eq ?1 ?2 ?3)] ->
Let t = '(eqT ?1 ?2 ?3) In
Cut t;[Intro;
(Match Context With
| [id:t |- ?] -> Rewrite id;Reflexivity)|Field_Gen FT]
| [|- (eqT ? ? ?)] -> Field_Gen FT>>) g
(* Verifies that all the terms have the same type and gives the right theory *)
let guess_theory env evc = function
| c::tl ->
let t = type_of env evc c in
if List.exists (fun c1 ->
not (Reductionops.is_conv env evc t (type_of env evc c1))) tl then
errorlabstrm "Field:" (str" All the terms must have the same type")
else
lookup t
| [] -> anomaly "Field: must have a non-empty constr list here"
(* Guesses the type and calls Field_Term with the right theory *)
let field_term l g =
Library.check_required_library ["Coq";"field";"Field"];
let env = (pf_env g)
and evc = (project g) in
let th = valueIn (VConstr (guess_theory env evc l))
and nl = List.map (fun x -> valueIn (VConstr x)) (Quote.sort_subterm g l) in
(List.fold_right
(fun c a ->
let tac = (Tacinterp.interp <:tactic<(Field_Term $th $c)>>) in
Tacticals.tclTHENFIRSTn tac [|a|]) nl Tacticals.tclIDTAC) g
(* Declaration of Field *)
TACTIC EXTEND Field
| [ "Field" ] -> [ field ]
| [ "Field" ne_constr_list(l) ] -> [ field_term l ]
END
|