@@ -5,6 +5,8 @@ import Prelude.Kore
5
5
import Control.Monad.Catch
6
6
( MonadCatch
7
7
, SomeException
8
+ , displayException
9
+ , finally
8
10
, handle
9
11
, throwM
10
12
)
@@ -18,6 +20,7 @@ import Data.Default
18
20
import qualified Data.Foldable as Foldable
19
21
import Data.Limit
20
22
( Limit (.. )
23
+ , maybeLimit
21
24
)
22
25
import Data.List
23
26
( intercalate
@@ -28,6 +31,7 @@ import Data.Semigroup
28
31
)
29
32
import Data.Text
30
33
( Text
34
+ , unpack
31
35
)
32
36
import qualified Data.Text as Text
33
37
( null
@@ -56,7 +60,14 @@ import Options.Applicative
56
60
)
57
61
import qualified Options.Applicative as Options
58
62
import System.Directory
59
- ( doesFileExist
63
+ ( copyFile
64
+ , doesFileExist
65
+ , emptyPermissions
66
+ , setOwnerExecutable
67
+ , setOwnerReadable
68
+ , setOwnerSearchable
69
+ , setOwnerWritable
70
+ , setPermissions
60
71
)
61
72
import System.Exit
62
73
( ExitCode (.. )
@@ -69,6 +80,10 @@ import System.IO
69
80
70
81
import qualified Data.Limit as Limit
71
82
import Kore.Attribute.Symbol as Attribute
83
+ import Kore.BugReport
84
+ ( BugReport (.. )
85
+ , parseBugReport
86
+ )
72
87
import Kore.Exec
73
88
import Kore.IndexedModule.IndexedModule
74
89
( VerifiedModule
@@ -102,9 +117,11 @@ import Kore.Log
102
117
, LogMessage
103
118
, SomeEntry (.. )
104
119
, WithLog
120
+ , archiveDirectoryReport
105
121
, logEntry
106
122
, parseKoreLogOptions
107
123
, runKoreLog
124
+ , unparseKoreLogOptions
108
125
)
109
126
import Kore.Log.ErrorException
110
127
( errorException
@@ -131,14 +148,17 @@ import Kore.Step.Search
131
148
)
132
149
import qualified Kore.Step.Search as Search
133
150
import Kore.Step.SMT.Lemma
151
+ import Kore.Step.Strategy
152
+ ( GraphSearchOrder (.. )
153
+ )
134
154
import qualified Kore.Strategies.Goal as Goal
135
155
import Kore.Strategies.Verification
136
156
( Stuck (.. )
137
157
)
138
158
import Kore.Syntax.Definition
139
159
( Definition (Definition )
140
160
, Module (Module )
141
- , ModuleName (ModuleName )
161
+ , ModuleName (.. )
142
162
, Sentence (.. )
143
163
)
144
164
import qualified Kore.Syntax.Definition as Definition.DoNotUse
@@ -154,11 +174,16 @@ import Pretty
154
174
)
155
175
import SMT
156
176
( MonadSMT
177
+ , TimeOut (.. )
157
178
)
158
179
import qualified SMT
159
180
import Stats
181
+ import qualified System.IO.Temp as Temp
160
182
161
183
import GlobalMain
184
+ import System.FilePath.Posix
185
+ ( (</>)
186
+ )
162
187
163
188
{-
164
189
Main module to run kore-exec
@@ -203,19 +228,19 @@ parseKoreSearchOptions =
203
228
204
229
parseSum :: String -> String -> String -> [(String , value )] -> Parser value
205
230
parseSum metaName longName helpMsg options =
206
- option (readSum longName options)
231
+ option (snd <$> readSum longName options)
207
232
( metavar metaName
208
233
<> long longName
209
234
<> help (helpMsg <> " : " <> knownOptions)
210
235
)
211
236
where
212
237
knownOptions = intercalate " , " (map fst options)
213
238
214
- readSum :: String -> [(String , value )] -> Options. ReadM value
239
+ readSum :: String -> [(String , value )] -> Options. ReadM ( String , value )
215
240
readSum longName options = do
216
241
opt <- str
217
242
case lookup opt options of
218
- Just val -> pure val
243
+ Just val -> pure (opt, val)
219
244
_ -> readerError (unknown opt ++ known)
220
245
where
221
246
knownOptions = intercalate " , " (map fst options)
@@ -232,7 +257,7 @@ applyKoreSearchOptions koreSearchOptions@(Just koreSearchOpts) koreExecOpts =
232
257
{ koreSearchOptions
233
258
, strategy =
234
259
-- Search relies on exploring the entire space of states.
235
- priorityAllStrategy
260
+ ( " all " , priorityAllStrategy)
236
261
, depthLimit = min depthLimit searchTypeDepthLimit
237
262
}
238
263
where
@@ -250,7 +275,7 @@ data Solver = Z3 | None
250
275
251
276
parseSolver :: Parser Solver
252
277
parseSolver =
253
- option (readSum longName options)
278
+ option (snd <$> readSum longName options)
254
279
$ metavar " SOLVER"
255
280
<> long longName
256
281
<> help (" SMT solver for checking constraints: " <> knownOptions)
@@ -275,12 +300,13 @@ data KoreExecOptions = KoreExecOptions
275
300
, smtSolver :: ! Solver
276
301
, breadthLimit :: ! (Limit Natural )
277
302
, depthLimit :: ! (Limit Natural )
278
- , strategy :: ! ([Rewrite ] -> Strategy (Prim Rewrite ))
303
+ , strategy :: ! (String , [Rewrite ] -> Strategy (Prim Rewrite ))
279
304
, koreLogOptions :: ! KoreLogOptions
280
305
, koreSearchOptions :: ! (Maybe KoreSearchOptions )
281
306
, koreProveOptions :: ! (Maybe KoreProveOptions )
282
307
, koreMergeOptions :: ! (Maybe KoreMergeOptions )
283
308
, rtsStatistics :: ! (Maybe FilePath )
309
+ , bugReport :: ! BugReport
284
310
}
285
311
286
312
-- | Command Line Argument Parser
@@ -334,6 +360,7 @@ parseKoreExecOptions =
334
360
<*> optional parseKoreProveOptions
335
361
<*> optional parseKoreMergeOptions
336
362
<*> optional parseRtsStatistics
363
+ <*> parseBugReport
337
364
SMT. Config { timeOut = defaultTimeOut } = SMT. defaultConfig
338
365
readSMTTimeOut = do
339
366
i <- auto
@@ -348,7 +375,7 @@ parseKoreExecOptions =
348
375
<> long " strategy"
349
376
-- TODO (thomas.tuegel): Make defaultStrategy the default when it
350
377
-- works correctly.
351
- <> value priorityAnyStrategy
378
+ <> value ( " any " , priorityAnyStrategy)
352
379
<> help " Select rewrites using STRATEGY."
353
380
)
354
381
where
@@ -392,6 +419,135 @@ parserInfoModifiers =
392
419
\in PATTERN_FILE."
393
420
<> header " kore-exec - an interpreter for Kore definitions"
394
421
422
+ unparseKoreSearchOptions :: KoreSearchOptions -> [String ]
423
+ unparseKoreSearchOptions (KoreSearchOptions _ bound searchType) =
424
+ [ " --search searchFile.kore"
425
+ , maybeLimit " " (\ limit -> " --bound " <> show limit) bound
426
+ , " --searchType " <> show searchType
427
+ ]
428
+
429
+ unparseKoreMergeOptions :: KoreMergeOptions -> [String ]
430
+ unparseKoreMergeOptions (KoreMergeOptions _ maybeBatchSize) =
431
+ [ " --merge-rules mergeRules.kore" ]
432
+ <> maybe mempty ((: [] ) . (" --merge-batch-size " <> ) . show ) maybeBatchSize
433
+
434
+ unparseKoreProveOptions :: KoreProveOptions -> [String ]
435
+ unparseKoreProveOptions
436
+ ( KoreProveOptions
437
+ _
438
+ (ModuleName moduleName)
439
+ graphSearch
440
+ bmc
441
+ saveProofs
442
+ )
443
+ =
444
+ [ " --prove spec.kore"
445
+ , " --spec-module " <> unpack moduleName
446
+ , " --graph-search "
447
+ <> if graphSearch == DepthFirst then " depth-first" else " breadth-first"
448
+ , if bmc then " --bmc" else " "
449
+ , maybe " " (" --save-proofs " <> ) saveProofs
450
+ ]
451
+
452
+ koreExecSh :: KoreExecOptions -> String
453
+ koreExecSh
454
+ ( KoreExecOptions
455
+ _
456
+ patternFileName
457
+ outputFileName
458
+ mainModuleName
459
+ (TimeOut timeout)
460
+ smtPrelude
461
+ smtSolver
462
+ breadthLimit
463
+ depthLimit
464
+ strategy
465
+ koreLogOptions
466
+ koreSearchOptions
467
+ koreProveOptions
468
+ koreMergeOptions
469
+ rtsStatistics
470
+ _
471
+ )
472
+ =
473
+ unlines $
474
+ [ " #!/bin/sh"
475
+ , " exec kore-exec \\ "
476
+ ]
477
+ <> (fmap (<> " \\ " ) . filter (not . null )) options
478
+ where
479
+ options =
480
+ [ if isJust koreProveOptions then " vdefinition.kore"
481
+ else " definition.kore"
482
+ , if isJust patternFileName then " --pattern pgm.kore" else " "
483
+ , if isJust outputFileName then " --output result.kore" else " "
484
+ , " --module " <> unpack (getModuleName mainModuleName)
485
+ , maybeLimit " " ((" --smt-timeout " <> ) . show ) timeout
486
+ , maybe " " (" --smt-prelude " <> ) smtPrelude
487
+ , " --smt " <> fmap Char. toLower (show smtSolver)
488
+ , maybeLimit " " ((" --breadth " <> ) . show ) breadthLimit
489
+ , maybeLimit " " ((" --depth " <> ) . show ) depthLimit
490
+ , " --strategy " <> fst strategy
491
+ ]
492
+ <> unparseKoreLogOptions koreLogOptions
493
+ <> maybe mempty unparseKoreSearchOptions koreSearchOptions
494
+ <> maybe mempty unparseKoreProveOptions koreProveOptions
495
+ <> maybe mempty unparseKoreMergeOptions koreMergeOptions
496
+ <> maybe mempty ((: [] ) . (" --rts-statistics " <> )) rtsStatistics
497
+
498
+ writeKoreSearchFiles :: FilePath -> KoreSearchOptions -> IO ()
499
+ writeKoreSearchFiles reportFile KoreSearchOptions { searchFileName } =
500
+ copyFile searchFileName $ reportFile <> " /searchFile.kore"
501
+
502
+ writeKoreMergeFiles :: FilePath -> KoreMergeOptions -> IO ()
503
+ writeKoreMergeFiles reportFile KoreMergeOptions { rulesFileName } =
504
+ copyFile rulesFileName $ reportFile <> " /mergeRules.kore"
505
+
506
+ writeKoreProveFiles :: FilePath -> KoreProveOptions -> IO ()
507
+ writeKoreProveFiles reportFile KoreProveOptions { specFileName, saveProofs } = do
508
+ copyFile specFileName $ reportFile <> " /spec.kore"
509
+ Foldable. forM_ saveProofs $ flip copyFile (reportFile <> " /saveProofs.kore" )
510
+
511
+ writeOptionsAndKoreFiles :: FilePath -> KoreExecOptions -> IO ()
512
+ writeOptionsAndKoreFiles
513
+ reportDirectory
514
+ opts@ KoreExecOptions
515
+ { definitionFileName
516
+ , patternFileName
517
+ , koreSearchOptions
518
+ , koreProveOptions
519
+ , koreMergeOptions
520
+ }
521
+ = do
522
+ let shellScript = reportDirectory </> " kore-exec.sh"
523
+ writeFile shellScript
524
+ . koreExecSh
525
+ $ opts
526
+ let allPermissions =
527
+ setOwnerReadable True
528
+ . setOwnerWritable True
529
+ . setOwnerExecutable True
530
+ . setOwnerSearchable True
531
+ setPermissions shellScript $ allPermissions emptyPermissions
532
+ copyFile
533
+ definitionFileName
534
+ ( reportDirectory
535
+ </> if isJust koreProveOptions
536
+ then " vdefinition.kore"
537
+ else " definition.kore"
538
+ )
539
+ Foldable. forM_ patternFileName
540
+ $ flip copyFile (reportDirectory </> " pgm.kore" )
541
+ Foldable. forM_
542
+ koreSearchOptions
543
+ (writeKoreSearchFiles reportDirectory)
544
+ Foldable. forM_
545
+ koreMergeOptions
546
+ (writeKoreMergeFiles reportDirectory)
547
+ Foldable. forM_
548
+ koreProveOptions
549
+ (writeKoreProveFiles reportDirectory)
550
+
395
551
-- TODO(virgil): Maybe add a regression test for main.
396
552
-- | Loads a kore definition file and uses it to execute kore programs
397
553
main :: IO ()
@@ -402,16 +558,24 @@ main = do
402
558
403
559
mainWithOptions :: KoreExecOptions -> IO ()
404
560
mainWithOptions execOptions = do
405
- let KoreExecOptions { koreLogOptions } = execOptions
406
- exitCode <-
407
- runKoreLog koreLogOptions
408
- $ handle handleSomeException
409
- $ handle handleSomeEntry
410
- $ handle handleWithConfiguration go
411
- let KoreExecOptions { rtsStatistics } = execOptions
412
- Foldable. forM_ rtsStatistics $ \ filePath ->
413
- writeStats filePath =<< getStats
414
- exitWith exitCode
561
+ let KoreExecOptions { koreLogOptions, bugReport } = execOptions
562
+ Temp. withSystemTempDirectory
563
+ (fromMaybe " report" $ toReport bugReport)
564
+ $ \ tempDirectory -> do
565
+ traceM tempDirectory
566
+ exitCode <-
567
+ runKoreLog tempDirectory koreLogOptions
568
+ $ handle (handleSomeException tempDirectory)
569
+ $ handle handleSomeEntry
570
+ $ handle handleWithConfiguration go
571
+ let KoreExecOptions { rtsStatistics } = execOptions
572
+ Foldable. forM_ rtsStatistics $ \ filePath ->
573
+ writeStats filePath =<< getStats
574
+ let reportPath = maybe tempDirectory (" ./" <> ) (toReport bugReport)
575
+ finally
576
+ (writeInReportDirectory tempDirectory)
577
+ (archiveDirectoryReport tempDirectory reportPath)
578
+ exitWith exitCode
415
579
where
416
580
KoreExecOptions { koreProveOptions } = execOptions
417
581
KoreExecOptions { koreSearchOptions } = execOptions
@@ -423,9 +587,13 @@ mainWithOptions execOptions = do
423
587
logEntry entry
424
588
return $ ExitFailure 1
425
589
426
- handleSomeException :: SomeException -> Main ExitCode
427
- handleSomeException someException = do
590
+ handleSomeException :: FilePath -> SomeException -> Main ExitCode
591
+ handleSomeException tempDirectory someException = do
428
592
errorException someException
593
+ lift
594
+ $ writeFile
595
+ (tempDirectory <> " /error.log" )
596
+ (displayException someException)
429
597
return $ ExitFailure 1
430
598
431
599
handleWithConfiguration :: Goal. WithConfiguration -> Main ExitCode
@@ -453,6 +621,13 @@ mainWithOptions execOptions = do
453
621
| otherwise =
454
622
koreRun execOptions
455
623
624
+ writeInReportDirectory :: FilePath -> IO ()
625
+ writeInReportDirectory tempDirectory = do
626
+ when . isJust . toReport . bugReport
627
+ <*> writeOptionsAndKoreFiles tempDirectory $ execOptions
628
+ Foldable. forM_ (outputFileName execOptions)
629
+ $ flip copyFile (tempDirectory <> " /outputFile.kore" )
630
+
456
631
koreSearch :: KoreExecOptions -> KoreSearchOptions -> Main ExitCode
457
632
koreSearch execOptions searchOptions = do
458
633
let KoreExecOptions { definitionFileName } = execOptions
@@ -472,7 +647,7 @@ koreSearch execOptions searchOptions = do
472
647
KoreSearchOptions { bound, searchType } = searchOptions
473
648
config = Search. Config { bound, searchType }
474
649
KoreExecOptions { breadthLimit, depthLimit, strategy } = execOptions
475
- strategy' = Limit. replicate depthLimit . strategy
650
+ strategy' = Limit. replicate depthLimit . snd strategy
476
651
477
652
koreRun :: KoreExecOptions -> Main ExitCode
478
653
koreRun execOptions = do
@@ -490,7 +665,7 @@ koreRun execOptions = do
490
665
return exitCode
491
666
where
492
667
KoreExecOptions { breadthLimit, depthLimit, strategy } = execOptions
493
- strategy' = Limit. replicate depthLimit . strategy
668
+ strategy' = Limit. replicate depthLimit . snd strategy
494
669
495
670
koreProve :: KoreExecOptions -> KoreProveOptions -> Main ExitCode
496
671
koreProve execOptions proveOptions = do
0 commit comments