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/
26 exception Error of string
34 type metasenv = conjecture list
37 val goal_of_conjecture: conjecture -> goal
38 val goal_mem: goal -> metasenv -> bool
41 tactic -> metasenv -> goal ->
42 metasenv * goal list * goal list
45 (** like List.assoc returning a pair: binding matching the given key,
46 * associative list without the returned binding
48 let list_assoc_extract key =
51 | [] -> raise Not_found
52 | (key', _) as hd :: tl when key = key' -> hd, (List.rev acc @ tl)
53 | hd :: tl -> aux (hd :: acc) tl
57 module Make (E:Engine) =
59 type goal_switch = Open of E.goal | Closed of E.goal
60 type 'a stack = 'a list
62 E.metasenv * ((int * goal_switch) list * E.goal list * E.goal list) stack
74 | Select of E.goal list
76 | Tactical of tactical
79 let goal_of = function _, Open g -> g | _, Closed g -> g
80 let is_open = function _, Open _ -> true | _, Closed _ -> false
81 let open_all = L.map (fun p, g -> p, Open g)
85 let complementary part full = (* not really efficient *)
86 L.fold_left (fun acc g -> if L.mem g part then acc else g::acc) full []
88 let close to_close l =
89 L.map (function p, Open g when L.mem g to_close -> p, Closed g | g -> g) l
91 let stack_map f g h stack =
92 L.map (fun (a,b,c) -> f a, g b, h c) stack
95 let add_dummy_pos g = dummy_pos, g
96 let map_dummy_pos = List.map add_dummy_pos
102 | g :: tl -> (pos, Open g) :: aux (pos + 1) tl
106 let eval_tactical tactical metasenv switch =
107 match tactical, switch with
108 | Tactic tac, Open n -> E.apply_tactic tac metasenv n
109 | Skip, Closed n -> metasenv, [], [n]
110 | Tactic _, Closed _ -> raise (Error "can't apply tactic to a closed goal")
111 | Skip, Open _ -> raise (Error "can't skip an open goal")
113 let eval continuational status =
114 match continuational, status with
115 | _, (_, []) -> assert false
116 | Tactical t, (metasenv, (env, todo, left)::tail) ->
117 assert (L.length env > 1);
118 let metasenv, opened, closed =
120 (fun (metasenv, opened, closed) cur_goal ->
121 if L.exists ((=) (goal_of cur_goal)) closed then
122 metasenv, opened, closed
124 let metasenv, newopened, newclosed =
125 eval_tactical t metasenv (snd cur_goal)
128 union (complementary newclosed opened) newopened,
129 union closed newclosed
130 ) (metasenv, [],[]) env
133 let stack_opened = List.map (fun g -> incr pos; !pos, g) opened in
135 (open_all stack_opened,
136 complementary closed todo,
137 complementary opened left)
139 (close closed) (complementary closed) (complementary opened) tail
140 | Semicolon, (metasenv, stack) -> metasenv, stack
141 | Dot, (metasenv, (env, todo, left)::tail) ->
143 match L.filter is_open env, left with
144 | [], [] -> raise (Error "There is nothig to do for '.'")
145 | g::env,left -> [g], union (L.map goal_of env) left
146 | [], g::left -> [dummy_pos, Open g], left
148 metasenv, (env, todo, left)::tail
149 | Branch, (metasenv, (g1::tl, todo, left)::tail) ->
150 assert (L.length tl >= 1);
151 metasenv, ([g1], [], [])::(tl, todo, left)::tail
152 | Branch, (_, _) -> raise (Error "can't branch on a singleton context")
153 | Shift opt_pos, (metasenv, (leftopen, t, l)::(goals, todo, left)::tail) ->
154 let next_goal, rem_goals =
155 match opt_pos, goals with
156 | None, g1 :: tl -> g1, tl
159 list_assoc_extract pos goals
161 raise (Error (Printf.sprintf "position %d not found" pos)))
162 | None, [] -> raise (Error "no more goals to shift")
164 let t = union t (union (L.map goal_of (L.filter is_open leftopen)) l) in
165 metasenv, ([next_goal], t, [])::(rem_goals, todo,left)::tail
166 | Shift _, (_, _) -> raise (Error "no more goals to shift")
167 | Merge, (metasenv, (leftopen,t,l)::(not_processed,todo,left)::tail) ->
169 (union (open_all (map_dummy_pos t))
170 (union (open_all (map_dummy_pos l))
171 (union not_processed (L.filter is_open leftopen ))))
173 metasenv, (env,todo,left)::tail
174 | Merge, (_, [_]) -> raise (Error "can't merge here")
175 | Select gl, (metasenv, stack) ->
177 (fun g -> if not (E.goal_mem g metasenv) then
178 raise (Error "you can't select a closed goal")) gl;
179 (metasenv, (open_all (map_dummy_pos gl),[],[])::stack)
180 | End_select, (metasenv, stack) ->
182 | ([], [], [])::tail -> metasenv, tail
183 | _ -> raise (Error "select left some goals open"))
184 | Qed, (metasenv, [[], [], []]) -> status
185 | Qed, _ -> raise (Error "can't qed an unfinished proof")
189 [ map_open_pos (List.map E.goal_of_conjecture metasenv), [], [] ]