33import logging
44import sys
55from argparse import ArgumentParser
6- from dataclasses import dataclass
76from pathlib import Path
87from typing import TYPE_CHECKING
98
10- from pyk .cli .args import KCLIArgs , LoggingOptions
9+ from pyk .cli .args import KCLIArgs
1110from pyk .kast .outer import KFlatModule , KImport
1211from pyk .proof .reachability import APRProof , APRProver
1312from pyk .proof .tui import APRProofViewer
1413
1514from .build import HASKELL_DEF_DIR , LLVM_LIB_DIR , haskell_semantics , llvm_semantics
1615from .kmir import KMIR , KMIRAPRNodePrinter
16+ from .options import GenSpecOpts , ProvePruneOpts , ProveRSOpts , ProveRunOpts , ProveViewOpts , RunOpts
1717from .parse .parser import parse_json
1818from .rust import CargoProject
1919
2222 from collections .abc import Sequence
2323 from typing import Final
2424
25+ from .options import KMirOpts
26+
2527_LOGGER : Final = logging .getLogger (__name__ )
2628_LOG_FORMAT : Final = '%(levelname)s %(asctime)s %(name)s - %(message)s'
2729
2830
29- @dataclass
30- class KMirOpts (LoggingOptions ): ...
31-
32-
33- @dataclass
34- class RunOpts (KMirOpts ):
35- bin : str | None
36- file : str | None
37- depth : int
38- start_symbol : str
39- haskell_backend : bool
40-
41-
42- @dataclass
43- class GenSpecOpts (KMirOpts ):
44- input_file : Path
45- output_file : Path | None
46- start_symbol : str
47-
48- def __init__ (self , input_file : Path , output_file : Path | str | None , start_symbol : str ) -> None :
49- self .input_file = input_file
50- if output_file is None :
51- self .output_file = None
52- else :
53- self .output_file = Path (output_file ).resolve ()
54- self .start_symbol = start_symbol
55-
56-
57- @dataclass
58- class ProveRSOpts (KMirOpts ):
59- rs_file : Path
60- bug_report : Path | None
61- max_depth : int | None
62- max_iterations : int | None
63-
64- def __init__ (
65- self ,
66- rs_file : Path ,
67- bug_report : Path | None = None ,
68- max_depth : int | None = None ,
69- max_iterations : int | None = None ,
70- ) -> None :
71- self .rs_file = rs_file
72- self .bug_report = bug_report
73- self .max_depth = max_depth
74- self .max_iterations = max_iterations
75-
76-
77- @dataclass
78- class ProveRunOpts (KMirOpts ):
79- spec_file : Path
80- proof_dir : Path | None
81- include_labels : tuple [str , ...] | None
82- exclude_labels : tuple [str , ...] | None
83- bug_report : Path | None
84- max_depth : int | None
85- max_iterations : int | None
86- reload : bool
87-
88- def __init__ (
89- self ,
90- spec_file : Path ,
91- proof_dir : Path | str | None ,
92- include_labels : str | None ,
93- exclude_labels : str | None ,
94- bug_report : Path | None = None ,
95- max_depth : int | None = None ,
96- max_iterations : int | None = None ,
97- reload : bool = False ,
98- ) -> None :
99- self .spec_file = spec_file
100- self .proof_dir = Path (proof_dir ).resolve () if proof_dir is not None else None
101- self .include_labels = tuple (include_labels .split (',' )) if include_labels is not None else None
102- self .exclude_labels = tuple (exclude_labels .split (',' )) if exclude_labels is not None else None
103- self .bug_report = bug_report
104- self .max_depth = max_depth
105- self .max_iterations = max_iterations
106- self .reload = reload
107-
108-
109- @dataclass
110- class ProveViewOpts (KMirOpts ):
111- proof_dir : Path
112- id : str
113-
114-
115- @dataclass
116- class ProvePruneOpts (KMirOpts ):
117- proof_dir : Path
118- id : str
119- node_id : int
120-
121-
12231def _kmir_run (opts : RunOpts ) -> None :
12332 tools = haskell_semantics () if opts .haskell_backend else llvm_semantics ()
12433
@@ -143,10 +52,8 @@ def _kmir_run(opts: RunOpts) -> None:
14352
14453
14554def _kmir_prove_rs (opts : ProveRSOpts ) -> None :
146- if not opts .rs_file .is_file ():
147- raise ValueError (f'Rust spec file does not exist: { opts .rs_file } ' )
14855 kmir = KMIR (HASKELL_DEF_DIR , LLVM_LIB_DIR , bug_report = opts .bug_report )
149- proof = kmir .prove_rs (opts . rs_file , max_depth = opts . max_depth , max_iterations = opts . max_iterations )
56+ proof = kmir .prove_rs (opts )
15057 print (str (proof .summary ))
15158 if not proof .passed :
15259 sys .exit (1 )
@@ -264,12 +171,19 @@ def _arg_parser() -> ArgumentParser:
264171 '--start-symbol' , type = str , metavar = 'SYMBOL' , default = 'main' , help = 'Symbol name to begin execution from'
265172 )
266173
174+ prove_args = ArgumentParser (add_help = False )
175+ prove_args .add_argument ('--bug-report' , metavar = 'PATH' , help = 'path to optional bug report' )
176+ prove_args .add_argument ('--max-depth' , metavar = 'DEPTH' , type = int , help = 'max steps to take between nodes in kcfg' )
177+ prove_args .add_argument (
178+ '--max-iterations' , metavar = 'ITERATIONS' , type = int , help = 'max number of proof iterations to take'
179+ )
180+
267181 prove_parser = command_parser .add_parser (
268182 'prove' , help = 'Utilities for working with proofs over SMIR' , parents = [kcli_args .logging_args ]
269183 )
270184 prove_command_parser = prove_parser .add_subparsers (dest = 'prove_command' , required = True )
271185
272- prove_run_parser = prove_command_parser .add_parser ('run' , help = 'Run the prover on a spec' )
186+ prove_run_parser = prove_command_parser .add_parser ('run' , help = 'Run the prover on a spec' , parents = [ prove_args ] )
273187 prove_run_parser .add_argument ('input_file' , metavar = 'FILE' , help = 'K File with the spec module' )
274188 prove_run_parser .add_argument ('--proof-dir' , metavar = 'DIR' , help = 'Proof directory' )
275189 prove_run_parser .add_argument (
@@ -278,14 +192,7 @@ def _arg_parser() -> ArgumentParser:
278192 prove_run_parser .add_argument (
279193 '--exclude-labels' , metavar = 'LABELS' , help = 'Comma separated list of claim labels to exclude'
280194 )
281- prove_run_parser .add_argument ('--bug-report' , metavar = 'PATH' , help = 'path to optional bug report' )
282- prove_run_parser .add_argument (
283- '--max-depth' , metavar = 'DEPTH' , type = int , help = 'max steps to take between nodes in kcfg'
284- )
285195 prove_run_parser .add_argument ('--reload' , action = 'store_true' , help = 'Force restarting proof' )
286- prove_run_parser .add_argument (
287- '--max-iterations' , metavar = 'ITERATIONS' , type = int , help = 'max number of proof iterations to take'
288- )
289196
290197 prove_view_parser = prove_command_parser .add_parser ('view' , help = 'View a saved proof' )
291198 prove_view_parser .add_argument ('id' , metavar = 'PROOF_ID' , help = 'The id of the proof to view' )
@@ -299,18 +206,11 @@ def _arg_parser() -> ArgumentParser:
299206 prove_prune_parser .add_argument ('node_id' , metavar = 'NODE' , type = int , help = 'The node to prune' )
300207
301208 prove_rs_parser = command_parser .add_parser (
302- 'prove-rs' , help = 'Prove a rust program' , parents = [kcli_args .logging_args ]
209+ 'prove-rs' , help = 'Prove a rust program' , parents = [kcli_args .logging_args , prove_args ]
303210 )
304211 prove_rs_parser .add_argument (
305212 'rs_file' , type = Path , metavar = 'FILE' , help = 'Rust file with the spec function (e.g. main)'
306213 )
307- prove_rs_parser .add_argument ('--bug-report' , metavar = 'PATH' , help = 'path to optional bug report' )
308- prove_rs_parser .add_argument (
309- '--max-depth' , metavar = 'DEPTH' , type = int , help = 'max steps to take between nodes in kcfg'
310- )
311- prove_rs_parser .add_argument (
312- '--max-iterations' , metavar = 'ITERATIONS' , type = int , help = 'max number of proof iterations to take'
313- )
314214
315215 return parser
316216
0 commit comments