aboutsummaryrefslogtreecommitdiffhomepage
path: root/contrib/field/field.ml4
blob: 19b8534d1dc374280e81c7ec71410f14525cdd0b (plain)
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
(***********************************************************************)
(*  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 kernel/names.cmo parsing/ast.cmo parsing/g_tactic.cmo  parsing/g_ltac.cmo parsing/g_constr.cmo" i*)

(* $Id$ *)

open Names
open Proof_type
open Tacinterp
open Tacmach
open Term
open Util
open Vernacinterp

(* Interpretation of constr's *)
let constr_of com = Astterm.interp_constr Evd.empty (Global.env()) com

(* Construction of constants *)
let constant dir s =
  let dir = "Coq"::"field"::dir in
  let id = id_of_string s in
  try 
    Declare.global_reference_in_absolute_module dir id
  with Not_found ->
    anomaly ("Field: cannot find "^
	     (Nametab.string_of_qualid (Nametab.make_qualid dir id)))

(* 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 ((Hashtbl.create 53) : (constr,constr) Hashtbl.t)

let lookup typ = Hashtbl.find !th_tab typ

let _ = 
  let init () = th_tab := (Hashtbl.create 53) 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)) = Hashtbl.add !th_tab typ th
let export_addfield x = Some x

(* Declaration of the Add Field library object *)
let (in_addfield,out_addfield)=
  Libobject.declare_object
    ("ADD_FIELD",
     { Libobject.load_function = load_addfield;
       Libobject.open_function = cache_addfield;
       Libobject.cache_function = cache_addfield;
       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
    Lib.add_anonymous_leaf (in_addfield (a,th))
  end

(* Vernac command declaration *)
let _ =
  let rec opt_arg (aminus_o,adiv_o) = function
    | (VARG_STRING "minus")::(VARG_CONSTR aminus)::l ->
      (match aminus_o with
      |	None -> opt_arg ((Some aminus),adiv_o) l
      |	_ -> anomaly "AddField")
    | (VARG_STRING "div")::(VARG_CONSTR adiv)::l ->
      (match adiv_o with
      |	None -> opt_arg (aminus_o,(Some adiv)) l
      |	_ -> anomaly "AddField")
    | _ -> (aminus_o,adiv_o) in
  vinterp_add "AddField"
    (function 
       | (VARG_CONSTR a)::(VARG_CONSTR aplus)::(VARG_CONSTR amult)
	 ::(VARG_CONSTR aone)::(VARG_CONSTR azero)::(VARG_CONSTR aopp)
	 ::(VARG_CONSTR aeq)::(VARG_CONSTR ainv)::(VARG_CONSTR rth)
         ::(VARG_CONSTR ainv_l)::l ->
         (fun () ->
           let (aminus_o,adiv_o) = opt_arg (None,None) l 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))
       | _ -> anomaly "AddField")

(* Guesses the type and calls Field_Gen with the right theory *)
let field g =
  let evc = project g
  and env = pf_env g in
  let typ = constr_of_Constr (interp_tacarg (evc,env,[],[],Some g,get_debug ())
    <:tactic<
      Match Context With
      | [|-(eq ?1 ? ?)] -> ?1
      |	[|-(eqT ?1 ? ?)] -> ?1>>) in
  let th = VArg (Constr (lookup typ)) in
  (tac_interp [("FT",th)] [] (get_debug ()) <:tactic<Field_Gen FT>>) g

(* Declaration of Field *)
let _ = hide_tactic "Field" (function _ -> field)