root/trunk/GUI/History.hs @ 11229

Revision 11229, 12.0 kB (checked in by rpascanu, 11 months ago)

Changes to GUI to use common datatypes in Interfaces

  • Property svn:eol-style set to native
  • Property svn:executable set to *
Line 
1{- |
2Module      :  $Header$
3Description :  Manages the history of proof commands
4Copyright   :  (c) Markus Gross 2008
5License     :  similar to LGPL, see HetCATS/LICENSE.txt or LIZENZ.txt
6
7Maintainer  :  Markus.Gross@dfki.de
8Stability   :  provisional
9Portability :  portable
10
11Manages the history of proof commands.
12-}
13module GUI.History (CommandHistory,
14                    emptyCommandHistory,
15                    initCommandHistory,
16                    addMenuItemToHist,
17                    addProveToHist,
18                    askSaveProofScript) where
19
20import Common.OrderedMap (keys)
21import Common.Utils (joinWith, splitOn)
22import Driver.Options (rmSuffix)
23import GUI.GraphAbstraction (GraphInfo, showTemporaryMessage)
24import GUI.Utils (infoDialog, fileSaveDialog)
25import Logic.Comorphism (AnyComorphism(..))
26import Logic.Grothendieck (SigId(..))
27import Logic.Logic (language_name)
28import Logic.Prover
29import Proofs.AbstractState
30import Static.GTheory (G_theory(..))
31
32import Control.Monad (when)
33import Data.IORef
34import Data.List (isPrefixOf, stripPrefix)
35import Data.Maybe (fromMaybe)
36import System.Directory (getCurrentDirectory)
37
38-- This datastructure holds all information for the history.
39data CommandHistory = CommandHistory {file :: String,
40                                      hist :: IORef [Command]}
41
42-- Represents a command in the history.
43data Command = DGComm DGCommand | NodeChange Node | ProveCommand Prove
44               deriving Eq
45
46instance Show Command where
47    show (DGComm c)       = show c
48    show (NodeChange n)   = show n
49    show (ProveCommand p) = show p
50
51-- This is used to recognize a change of node between the proofs.
52data Node = Node Int String deriving Eq
53
54instance Show Node where
55    show (Node _ nName) =
56        "\n# " ++ (replicate 78 '-') ++ "\n\ndg basic " ++ nName ++ "\n"
57
58-- This represents a dg menu-item.
59data DGCommand = AllAuto      | AllGlobSubsume | AllGlobDecomp | AllLocInfer |
60                 AllLocDecomp | AllComp        | AllCompNew    | AllHideThm  |
61                 AllThmHide   deriving Eq
62
63instance Show DGCommand where
64    show AllAuto        = "dg-all auto"
65    show AllGlobSubsume = "dg-all glob-subsume"
66    show AllGlobDecomp  = "dg-all glob-decomp"
67    show AllLocInfer    = "dg-all loc-infer"
68    show AllLocDecomp   = "dg-all loc-decomp"
69    show AllComp        = "dg-all comp"
70    show AllCompNew     = "dg-all comp-new"
71    show AllHideThm     = "dg-all hide-thm"
72    show AllThmHide     = "dg-all thm-hide"
73
74-- This represents a prove with all properties needed to add it to the history.
75data Prove = Prove {prover      :: Maybe String,        -- name of the prover
76                    translation :: Maybe AnyComorphism, -- used translation
77                    provenGoals :: [ProvenGoal],        -- proven goals
78                    allAxioms   :: [String]             -- all available axioms
79                   } deriving Eq
80
81instance Show Prove where
82    show p =
83        "drop-translations\n"
84        ++
85        -- selected translation
86        (maybe "" (unlines . splitComorphism) $ translation p)
87        ++
88        -- selected prover
89        (maybe "# no prover chosen" ("prover " ++) $ prover p) ++ "\n\n"
90        ++
91        -- proven goals
92        (joinWith '\n' $ map (goalToString p) $ provenGoals p)
93
94-- This represents the information about a proved goal
95data ProvenGoal = ProvenGoal {name      :: String,   -- name of the goal
96                              axioms    :: [String], -- used axioms in the prove
97                              timeLimit :: Int       -- chosen time-limit
98                             } deriving Eq
99
100-- Converts a proven goal to a string.
101goalToString :: Prove -> ProvenGoal -> String
102goalToString p g =
103    "set goals " ++ (name g)
104    ++
105    -- axioms to include in prove
106    '\n':(if (allAxioms p == axioms g) || (null $ axioms g)
107              then "set-all axioms"
108              else "set axioms " ++ (joinWith ' ' $ axioms g))
109    ++
110    -- selected time-limit
111    "\nset time-limit " ++ (show $ timeLimit g) ++ "\nprove\n"
112
113-- Creates an empty command history.
114emptyCommandHistory :: IO CommandHistory
115emptyCommandHistory = initCommandHistory ""
116
117-- Initializes the command history with a filename.
118initCommandHistory :: String -> IO CommandHistory
119initCommandHistory f =
120    do
121    ff <- tryRemoveAbsolutePathComponent f
122    ch <- newIORef []
123    return $ CommandHistory {file = rmSuffix ff, hist = ch}
124
125-- Adds a single command to the history.
126addToHist :: CommandHistory -> Command -> IO ()
127addToHist (CommandHistory {hist = c}) cm =
128    readIORef c >>= (\h -> writeIORef c $ h ++ [cm])
129
130-- Adds a menu item to the history.
131addMenuItemToHist :: CommandHistory -> String -> IO ()
132addMenuItemToHist ch item =
133    maybe (return ()) (addToHist ch . DGComm) (lookup item menuItems)
134
135-- A List of menu items and their corresponding proof-script command.
136menuItems :: [(String, DGCommand)]
137menuItems = [
138    ("Automatic",                            AllAuto),
139    ("Global Subsumption",                   AllGlobSubsume),
140    ("Global Decomposition",                 AllGlobDecomp),
141    ("Local Inference",                      AllLocInfer),
142    ("Local Decomposition (merge of rules)", AllLocDecomp),
143    ("Composition (merge of rules)",         AllComp),
144    ("Composition - creating new links",     AllCompNew),
145    ("Hide Theorem Shift",                   AllHideThm),
146    ("Theorem Hide Shift",                   AllThmHide)
147    ]
148
149-- If at least one goal was proved and the prove is not the same as last time
150-- the prove gets added, otherwise not.
151addProveToHist :: CommandHistory
152        -> ProofState lid sentence         -- current proofstate
153        -> Maybe (G_prover, AnyComorphism) -- possible used translation
154        -> [Proof_status proof_tree]       -- goals included in prove
155        -> IO ()
156addProveToHist ch st pcm pt
157    | null $ filter (wasProved) pt = return ()
158    | otherwise = do
159                  p' <- proofTreeToProve st pcm pt
160                  mp <- getLastProve ch
161                  case mp of
162                      Just p  -> when (p /= p') (addProve p')
163                      Nothing -> addProve p'
164    where
165        -- Drops the filename as prefix from a node-name.
166        dropName :: String -> String
167        dropName s = maybe s (tail) (stripPrefix (file ch) s)
168        -- Adds a prove to the history.
169        addProve :: Prove -> IO ()
170        addProve p =
171            do
172            -- Create new NodeChange and compare it with last found NodeChange.
173            let (SigId nId) = gTheorySignIdx $ theory st
174            let nc' = NodeChange $ Node nId (dropName $ theoryName st)
175            mn <- getLastNode ch
176            -- Add new NodeChange if it doesn't match.
177            case mn of
178                Just n  -> when (NodeChange n /= nc') (addToHist ch nc')
179                Nothing -> addToHist ch nc'
180            -- Finally add the prove.
181            addToHist ch $ ProveCommand p
182
183-- Converts a list of proof-trees to a prove.
184proofTreeToProve :: ProofState lid sentence -- current proofstate
185    -> Maybe (G_prover, AnyComorphism)      -- possible used translation
186    -> [Proof_status proof_tree]            -- goals included in prove
187    -> IO Prove
188proofTreeToProve st pcm pt =
189    do
190    -- selected prover
191    let prvr = maybe (selectedProver st) (Just . getProverName . fst) pcm
192    -- selected translation
193    let trans = maybe Nothing (Just . snd) pcm
194    -- 1. filter out the not proven goals
195    -- 2. reverse the list, because the last proven goals are on top
196    -- 3. convert all proof-trees to goals
197    -- 4. merge goals with same used axioms
198    let goals = mergeGoals $ reverse $ map (convertGoal) $ filter (wasProved) pt
199    -- axioms to include in prove
200    let allax = case theory st of
201                    G_theory _ _ _ axs _ -> keys axs
202    return $ Prove {prover = prvr,
203                    translation = trans,
204                    provenGoals = goals,
205                    allAxioms = allax}
206
207-- This checks wether a goal was proved or not.
208wasProved :: Proof_status proof_tree -> Bool
209wasProved g = case goalStatus g of
210    Proved _ -> True
211    _        -> False
212
213-- Converts a proof-tree into a goal.
214convertGoal :: Proof_status proof_tree -> ProvenGoal
215convertGoal pt =
216    ProvenGoal {name = goalName pt, axioms = usedAxioms pt, timeLimit = tlimit}
217    where
218        (Tactic_script script) = tacticScript pt
219        tlimit = maybe 20 (read) (parseTimeLimit $ splitOn '\n' script)
220
221-- Parses time-limit from the tactic-script of a goal.
222parseTimeLimit :: [String] -> Maybe String
223parseTimeLimit l =
224    if null l' then Nothing else Just $ drop (length tlStr) $ last l'
225    where
226        l' = filter (isPrefixOf tlStr) l
227        tlStr = "Time limit: "
228
229-- Merges goals with the same used axioms into one goal.
230mergeGoals :: [ProvenGoal] -> [ProvenGoal]
231mergeGoals []     = []
232mergeGoals (h:[]) = [h]
233mergeGoals (h:t)  | mergeAble h h' = mergeGoals $ (merge h h'):(tail t)
234                  | otherwise      = h:(mergeGoals t)
235                  where
236                      h' = head t
237                      mergeAble :: ProvenGoal -> ProvenGoal -> Bool
238                      mergeAble a b = axioms a == axioms b &&
239                                      timeLimit a == timeLimit b
240                      merge :: ProvenGoal -> ProvenGoal -> ProvenGoal
241                      merge a b = a{name = name a ++ ' ':(name b)}
242
243-- Returns the last nodechange in the history.
244getLastNode :: CommandHistory -> IO (Maybe Node)
245getLastNode (CommandHistory{hist = c}) =
246    do
247    h <- readIORef c
248    let h' = [n | NodeChange n <- h]
249    return $ if null h' then Nothing else Just $ last h'
250
251-- If the last command in history is a prove it gets returned.
252getLastProve :: CommandHistory -> IO (Maybe Prove)
253getLastProve (CommandHistory{hist = c}) =
254    do
255    h <- readIORef c
256    return $ if null h
257               then Nothing
258               else case last h of
259                        ProveCommand p -> Just p
260                        _              -> Nothing
261
262-- | Displays a Save-As dialog and writes the proof-script.
263askSaveProofScript :: GraphInfo -> CommandHistory -> IO ()
264askSaveProofScript graphInfo ch =
265    do
266    h <- readIORef $ hist ch
267    if null h
268        then infoDialog "Information" "The history is empty. No file written."
269        else do
270             f <- getProofScriptFileName ch
271             maybeFilePath <- fileSaveDialog f [ ("Proof-Script",["*.hpf"])
272                                               , ("All Files", ["*"])] Nothing
273             case maybeFilePath of
274                 Just filePath -> do
275                    showTemporaryMessage graphInfo "Saving proof-script..."
276                    saveCommandHistory ch filePath
277                    showTemporaryMessage graphInfo $ "Proof-script saved to " ++
278                                                     filePath ++ "!"
279                 Nothing -> showTemporaryMessage graphInfo $ "Aborted!"
280
281-- Saves the history of commands in a file.
282saveCommandHistory :: CommandHistory -> String -> IO ()
283saveCommandHistory (CommandHistory {file = ff, hist = c}) f =
284    do
285    h <- readIORef c
286    let history = ["# automatically generated hets proof-script", "",
287                   "use " ++ ff, ""] ++ map (show) h
288    writeFile f $ joinWith '\n' history
289
290-- Suggests a proof-script filename.
291getProofScriptFileName :: CommandHistory -> IO FilePath
292getProofScriptFileName (CommandHistory {file = f})
293    | "/" `isPrefixOf` f = return $ f ++ ".hpf"
294    | otherwise          = do
295                           dir <- getCurrentDirectory
296                           return $ dir ++ '/':f ++ ".hpf"
297
298-- Splits the comorphism string into its translations.
299splitComorphism :: AnyComorphism -> [String]
300splitComorphism (Comorphism cid) =
301    map ("translate " ++) $ tail $ splitOn ';' $ language_name cid
302
303-- If an absolute path is given,
304-- it tries to remove the current working directory as prefix of it.
305tryRemoveAbsolutePathComponent :: String -> IO String
306tryRemoveAbsolutePathComponent f
307    | "/" `isPrefixOf` f = do
308                           dir <- getCurrentDirectory
309                           return $ fromMaybe f (stripPrefix (dir ++ "/") f)
310    | otherwise          = return f
Note: See TracBrowser for help on using the browser.