]> matita.cs.unibo.it Git - helm.git/blob - helm/matita/matitaInterpreter.ml
snapshot
[helm.git] / helm / matita / matitaInterpreter.ml
1 (* Copyright (C) 2004, HELM Team.
2  * 
3  * This file is part of HELM, an Hypertextual, Electronic
4  * Library of Mathematics, developed at the Computer Science
5  * Department, University of Bologna, Italy.
6  * 
7  * HELM is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  * 
12  * HELM is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with HELM; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
20  * MA  02111-1307, USA.
21  * 
22  * For details, see the HELM World-Wide-Web page,
23  * http://helm.cs.unibo.it/
24  *)
25
26 (** Interpreter for textual phrases coming from matita's console (textual entry
27 * window at the bottom of the main window).
28 *
29 * Interpreter is either in `Command state or in `Proof state (see state_tag type
30 * below). In `Command state commands for starting proofs are accepted, but
31 * tactic and tactical applications are not. In `Proof state both
32 * tactic/tacticals and commands are accepted.
33 *)
34
35 open Printf
36
37 type state_tag = [ `Command | `Proof ]
38
39 exception Command_error of string
40
41 class virtual interpreterState ~(console: MatitaConsole.console) =
42   object (self)
43       (** eval a toplevel phrase in the current state and return the new state
44       *)
45     method parsePhrase s = CicTextualParser2.parse_tactical (Stream.of_string s)
46
47     method virtual evalTactical:
48       (CicAst.term, string) TacticAst.tactical -> state_tag
49
50     method evalPhrase s = self#evalTactical (self#parsePhrase s)
51   end
52
53   (** Implements phrases that should be accepted in all states *)
54 class sharedState
55   ~(disambiguator: MatitaTypes.disambiguator)
56   ~(proof_handler: MatitaTypes.proof_handler)
57   ~(console: MatitaConsole.console)
58   ()
59 =
60   object (self)
61     inherit interpreterState ~console
62     method evalTactical = function
63       | TacticAst.Command TacticAst.Quit ->
64           proof_handler.MatitaTypes.quit ();
65           `Command (* dummy answer, useless *)
66       | TacticAst.Command TacticAst.Proof ->
67             (* do nothing, just for compatibility with coq syntax *)
68           `Command
69       | tactical ->
70           raise (Command_error (TacticAstPp.pp_tactical tactical))
71   end
72
73   (** Implements phrases that should be accepted only in `Command state *)
74 class commandState
75   ~(disambiguator: MatitaTypes.disambiguator)
76   ~(proof_handler: MatitaTypes.proof_handler)
77   ~(console: MatitaConsole.console)
78   ()
79 =
80   let shared = new sharedState ~disambiguator ~proof_handler ~console () in
81   object (self)
82     inherit interpreterState ~console
83
84     method evalTactical = function
85       | TacticAst.LocatedTactical (_, tactical) -> self#evalTactical tactical
86       | TacticAst.Command (TacticAst.Theorem (_, Some name, ast, None)) ->
87           let (_, metasenv, expr) = disambiguator#disambiguateTermAst ast in
88           let proof = MatitaProof.proof ~typ:expr ~metasenv () in
89           proof_handler.MatitaTypes.new_proof proof;
90           `Proof
91       | TacticAst.Command TacticAst.Quit ->
92           proof_handler.MatitaTypes.quit ();
93           `Command (* dummy answer, useless *)
94       | TacticAst.Command TacticAst.Proof ->
95             (* do nothing, just for compatibility with coq syntax *)
96           `Command
97       | tactical -> shared#evalTactical tactical
98   end
99
100 let rec lookup_tactic = function
101   | TacticAst.LocatedTactic (_, tactic) -> lookup_tactic tactic
102   | TacticAst.Intros (_, names) ->
103       let namer =
104         (** use names given by the user as long as they are availble, then
105           * fallback on default fresh name generator *)
106         let len = List.length names in
107         let count = ref 0 in
108         fun metasenv context name ~typ ->
109           if !count < len then begin
110             let name = Cic.Name (List.nth names !count) in
111             incr count;
112             name
113           end else
114             FreshNamesGenerator.mk_fresh_name metasenv context name ~typ
115       in
116       PrimitiveTactics.intros_tac ~mk_fresh_name_callback:namer ()
117   | TacticAst.Reflexivity -> EqualityTactics.reflexivity_tac
118   | TacticAst.Assumption -> VariousTactics.assumption_tac
119   | TacticAst.Contradiction -> NegationTactics.contradiction_tac
120   | TacticAst.Exists -> IntroductionTactics.exists_tac
121   | TacticAst.Fourier -> FourierR.fourier_tac
122   | TacticAst.Left -> IntroductionTactics.left_tac
123   | TacticAst.Right -> IntroductionTactics.right_tac
124   | TacticAst.Ring -> Ring.ring_tac
125   | TacticAst.Split -> IntroductionTactics.split_tac
126   | TacticAst.Symmetry -> EqualityTactics.symmetry_tac
127 (*
128   (* TODO Zack a lot more of tactics to be implemented here ... *)
129   | TacticAst.Absurd
130   | TacticAst.Apply of 'term
131   | TacticAst.Change of 'term * 'term * 'ident option
132   | TacticAst.Change_pattern of 'term pattern * 'term * 'ident option
133   | TacticAst.Cut of 'term
134   | TacticAst.Decompose of 'ident * 'ident list
135   | TacticAst.Discriminate of 'ident
136   | TacticAst.Elim of 'term * 'term option
137   | TacticAst.ElimType of 'term
138   | TacticAst.Exact of 'term
139   | TacticAst.Fold of reduction_kind * 'term
140   | TacticAst.Injection of 'ident
141   | TacticAst.Intros of int option * 'ident list
142   | TacticAst.LetIn of 'term * 'ident
143   | TacticAst.Reduce of reduction_kind * 'term pattern * 'ident option
144   | TacticAst.Replace of 'term * 'term
145   | TacticAst.Replace_pattern of 'term pattern * 'term
146   | TacticAst.Rewrite of direction * 'term * 'ident option
147   | TacticAst.Transitivity of 'term
148 *)
149   | _ ->
150       MatitaTypes.not_implemented "some tactic"
151
152   (** Implements phrases that should be accepted only in `Proof state, basically
153   * tacticals *)
154 class proofState
155   ~(disambiguator: MatitaTypes.disambiguator)
156   ~(proof_handler: MatitaTypes.proof_handler)
157   ~(console: MatitaConsole.console)
158   ()
159 =
160   let shared = new sharedState ~disambiguator ~proof_handler ~console () in
161   object (self)
162     inherit interpreterState ~console
163
164     method evalTactical = function
165       | TacticAst.LocatedTactical (_, tactical) -> self#evalTactical tactical
166       | TacticAst.Command TacticAst.Abort ->
167           proof_handler.MatitaTypes.set_proof None;
168           `Command
169       | TacticAst.Seq tacticals ->
170           (* TODO Zack check for proof completed at each step? *)
171           List.iter (fun t -> ignore (self#evalTactical t)) tacticals;
172           `Proof
173       | TacticAst.Tactic tactic_phrase ->
174           let tactic = lookup_tactic tactic_phrase in
175           (proof_handler.MatitaTypes.get_proof ())#apply_tactic tactic;
176           `Proof
177       | tactical -> shared#evalTactical tactical
178   end
179
180 class interpreter
181   ~(disambiguator: MatitaTypes.disambiguator)
182   ~(proof_handler: MatitaTypes.proof_handler)
183   ~(console: MatitaConsole.console)
184   ()
185 =
186   let commandState =
187     new commandState ~disambiguator ~proof_handler ~console ()
188   in
189   let proofState = new proofState ~disambiguator ~proof_handler ~console () in
190   object
191     val mutable state = commandState
192
193     method evalPhrase s =
194       try
195         (match state#evalPhrase s with
196         | `Command -> state <- commandState
197         | `Proof -> state <- proofState)
198       with exn ->
199         console#echo_error (sprintf "Uncaught exception: %s"
200           (Printexc.to_string exn))
201   end
202