1 (* Copyright (C) 2005, HELM Team.
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.
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.
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.
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,
22 * For details, see the HELM World-Wide-Web page,
23 * http://helm.cs.unibo.it/
28 exception Error of string
30 let fail msg = raise (Error msg)
38 val is_goal_closed: goal -> proof -> bool
39 val goals_of_proof: proof -> goal list
42 tactic -> proof -> goal ->
43 proof * goal list * goal list
46 (** like List.assoc returning a pair: binding matching the given key,
47 * associative list without the returned binding
49 let list_assoc_extract key =
52 | [] -> raise Not_found
53 | (key', _) as hd :: tl when key = key' -> hd, (List.rev acc @ tl)
54 | hd :: tl -> aux (hd :: acc) tl
79 | Tactical of tactical
81 val eval: t -> status -> status
82 val init: proof -> status
84 val get_proof: status -> proof
85 val set_proof: proof -> status -> status
87 type goal_switch = Open of goal | Closed of goal
88 val get_goals: status -> goal_switch list
90 val is_completed: status -> bool
93 module Make (E:Engine) =
97 type tactic = E.tactic
99 type goal_switch = Open of goal | Closed of goal
100 type 'a stack = 'a list
101 type stack_tag = BranchTag | SelectTag | NoTag
103 (int * goal_switch) list * goal list * goal list * stack_tag
104 type status = proof * stack_entry stack
107 let set_proof p (_, s) = p, s
108 let get_goals (_, stack) =
110 | (goals, _, _, _) :: _ -> List.map snd goals
121 | Shift of int option
122 | Select of goal list
124 | Tactical of tactical
126 let goal_of = function _, Open g -> g | _, Closed g -> g
127 let is_open = function _, Open _ -> true | _, Closed _ -> false
128 let open_all = List.map (fun p, g -> p, Open g)
130 let union a b = a @ b
132 let complementary part full = (* not really efficient *)
133 List.fold_left (fun acc g -> if List.mem g part then acc else g::acc)
139 | p, Open g when List.mem g to_close -> p, Closed g
142 let map_stack f g h = List.map (fun (a,b,c,tag) -> f a, g b, h c, tag)
145 let add_dummy_pos g = dummy_pos, g
146 let map_dummy_pos = List.map add_dummy_pos
152 | g :: tl -> (pos, Open g) :: aux (pos + 1) tl
156 let eval_tactical tactical proof switch =
157 match tactical, switch with
158 | Tactic tac, Open n -> E.apply_tactic tac proof n
159 | Skip, Closed n -> proof, [], [n]
160 | Tactic _, Closed _ -> fail "can't apply tactic to a closed goal"
161 | Skip, Open _ -> fail "can't skip an open goal"
163 let eval continuational status =
164 match continuational, status with
165 | _, (_, []) -> assert false
166 | Tactical t, (proof, (env, todo, left,tag)::tail) ->
167 assert (List.length env > 1);
168 let proof, opened, closed =
170 (fun (proof, opened, closed) cur_goal ->
171 if List.exists ((=) (goal_of cur_goal)) closed then
172 proof, opened, closed
174 let proof, newopened, newclosed =
175 eval_tactical t proof (snd cur_goal)
178 union (complementary newclosed opened) newopened,
179 union closed newclosed
183 let stack_opened = List.map (fun g -> incr pos; !pos, g) opened in
185 (open_all stack_opened,
186 complementary closed todo,
187 complementary opened left, tag)
189 (close closed) (complementary closed) (complementary opened) tail
190 | Semicolon, (proof, stack) -> proof, stack
191 | Dot, (proof, (env, todo, left, tag)::tail) ->
193 match List.filter is_open env, left with
194 | [], [] -> fail "There is nothig to do for '.'"
195 | g::env,left -> [g], union (List.map goal_of env) left
196 | [], g::left -> [dummy_pos, Open g], left
198 proof, (env, todo, left, tag)::tail
199 | Branch, (proof, (g1::tl, todo, left, tag)::tail) ->
200 assert (List.length tl >= 1);
201 proof, ([g1], [], [], BranchTag)::(tl, todo, left, tag)::tail
202 | Branch, (_, _) -> fail "can't branch on a singleton context"
203 | Shift opt_pos, (proof, (leftopen, t, l,BranchTag)::
204 (goals, todo, left,tag)::tail) ->
205 let next_goal, rem_goals =
206 match opt_pos, goals with
207 | None, g1 :: tl -> g1, tl
210 list_assoc_extract pos goals
211 with Not_found -> fail (sprintf "position %d not found" pos))
212 | None, [] -> fail "no more goals to shift"
215 union t (union (List.map goal_of (List.filter is_open leftopen)) l)
217 proof, ([next_goal], t, [], BranchTag)::(rem_goals, todo,left,tag)::tail
218 | Shift _, (_, _) -> fail "no more goals to shift"
219 | Select gl, (proof, stack) ->
222 if E.is_goal_closed g proof then
223 fail "you can't select a closed goal")
225 (proof, (open_all (map_dummy_pos gl),[],[],SelectTag)::stack)
226 | End, (proof, stack) ->
228 | ([], [], [], SelectTag)::tail -> proof, tail
229 | (leftopen,t,l,BranchTag)::(not_processed,todo,left,tag)::tail ->
231 (union (open_all (map_dummy_pos t))
232 (union (open_all (map_dummy_pos l))
233 (union not_processed (List.filter is_open leftopen))))
235 proof, (env,todo,left,tag)::tail
236 | _ -> fail "can't end here")
240 [ map_open_pos (E.goals_of_proof proof), [], [], NoTag ]
244 | (_, [[],[],[],NoTag]) -> true