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
58 module Make (E:Engine) =
60 type goal_switch = Open of E.goal | Closed of E.goal
61 type 'a stack = 'a list
63 E.proof * ((int * goal_switch) list * E.goal list * E.goal list) stack
75 | Select of E.goal list
77 | Tactical of tactical
80 let goal_of = function _, Open g -> g | _, Closed g -> g
81 let is_open = function _, Open _ -> true | _, Closed _ -> false
82 let open_all = List.map (fun p, g -> p, Open g)
86 let complementary part full = (* not really efficient *)
87 List.fold_left (fun acc g -> if List.mem g part then acc else g::acc)
93 | p, Open g when List.mem g to_close -> p, Closed g
96 let map_stack f g h = List.map (fun (a,b,c) -> f a, g b, h c)
99 let add_dummy_pos g = dummy_pos, g
100 let map_dummy_pos = List.map add_dummy_pos
106 | g :: tl -> (pos, Open g) :: aux (pos + 1) tl
110 let eval_tactical tactical proof switch =
111 match tactical, switch with
112 | Tactic tac, Open n -> E.apply_tactic tac proof n
113 | Skip, Closed n -> proof, [], [n]
114 | Tactic _, Closed _ -> fail "can't apply tactic to a closed goal"
115 | Skip, Open _ -> fail "can't skip an open goal"
117 let eval continuational status =
118 match continuational, status with
119 | _, (_, []) -> assert false
120 | Tactical t, (proof, (env, todo, left)::tail) ->
121 assert (List.length env > 1);
122 let proof, opened, closed =
124 (fun (proof, opened, closed) cur_goal ->
125 if List.exists ((=) (goal_of cur_goal)) closed then
126 proof, opened, closed
128 let proof, newopened, newclosed =
129 eval_tactical t proof (snd cur_goal)
132 union (complementary newclosed opened) newopened,
133 union closed newclosed
137 let stack_opened = List.map (fun g -> incr pos; !pos, g) opened in
139 (open_all stack_opened,
140 complementary closed todo,
141 complementary opened left)
143 (close closed) (complementary closed) (complementary opened) tail
144 | Semicolon, (proof, stack) -> proof, stack
145 | Dot, (proof, (env, todo, left)::tail) ->
147 match List.filter is_open env, left with
148 | [], [] -> fail "There is nothig to do for '.'"
149 | g::env,left -> [g], union (List.map goal_of env) left
150 | [], g::left -> [dummy_pos, Open g], left
152 proof, (env, todo, left)::tail
153 | Branch, (proof, (g1::tl, todo, left)::tail) ->
154 assert (List.length tl >= 1);
155 proof, ([g1], [], [])::(tl, todo, left)::tail
156 | Branch, (_, _) -> fail "can't branch on a singleton context"
157 | Shift opt_pos, (proof, (leftopen, t, l)::(goals, todo, left)::tail) ->
158 let next_goal, rem_goals =
159 match opt_pos, goals with
160 | None, g1 :: tl -> g1, tl
163 list_assoc_extract pos goals
164 with Not_found -> fail (sprintf "position %d not found" pos))
165 | None, [] -> fail "no more goals to shift"
168 union t (union (List.map goal_of (List.filter is_open leftopen)) l)
170 proof, ([next_goal], t, [])::(rem_goals, todo,left)::tail
171 | Shift _, (_, _) -> fail "no more goals to shift"
172 | Merge, (proof, (leftopen,t,l)::(not_processed,todo,left)::tail) ->
174 (union (open_all (map_dummy_pos t))
175 (union (open_all (map_dummy_pos l))
176 (union not_processed (List.filter is_open leftopen))))
178 proof, (env,todo,left)::tail
179 | Merge, (_, [_]) -> fail "can't merge here"
180 | Select gl, (proof, stack) ->
183 if not (E.is_goal_closed g proof) then
184 fail "you can't select a closed goal")
186 (proof, (open_all (map_dummy_pos gl),[],[])::stack)
187 | End_select, (proof, stack) ->
189 | ([], [], [])::tail -> proof, tail
190 | _ -> fail "select left some goals open")
191 | Qed, (proof, [[], [], []]) -> status
192 | Qed, _ -> fail "can't qed an unfinished proof"
196 [ map_open_pos (E.goals_of_proof proof), [], [] ]