machine_check_exec/
lib.rs1#![doc = include_str!("../README.md")]
2
3mod framework;
4mod model_check;
5mod precision;
6mod proposition;
7mod space;
8
9use log::{error, info, log_enabled, trace};
10use machine_check_common::ExecResult;
11use mck::concr::FullMachine;
12
13use clap::{ArgGroup, Args, Parser};
14use framework::{Framework, Strategy};
15use proposition::Proposition;
16
17#[derive(Parser, Debug)]
19#[clap(group(ArgGroup::new("property-group")
20.required(true)
21.multiple(true)
22.args(&["property", "inherent"]),
23))]
24#[clap(group(ArgGroup::new("verbosity-group")
25.required(false)
26.multiple(false)
27.args(&["silent", "verbose"]),
28))]
29#[clap(group(ArgGroup::new("assume-inherent-group")
30.required(false)
31.multiple(false)
32.conflicts_with("inherent")
33.args(&["assume_inherent"]),
34))]
35pub struct ExecArgs {
36 #[arg(long)]
37 pub silent: bool,
38
39 #[arg(short, long, action = clap::ArgAction::Count)]
40 pub verbose: u8,
41
42 #[arg(long)]
43 pub batch: bool,
44
45 #[arg(long)]
46 pub property: Option<String>,
47
48 #[arg(long)]
49 pub inherent: bool,
50
51 #[arg(long)]
53 pub naive_inputs: bool,
54 #[arg(long)]
55 pub use_decay: bool,
56 #[arg(long)]
57 pub assume_inherent: bool,
58}
59
60#[derive(Parser, Debug)]
61struct ProgramArgs<A: Args> {
62 #[clap(flatten)]
63 run_args: ExecArgs,
64 #[clap(flatten)]
65 system_args: A,
66}
67
68pub fn parse_args<A: Args>(args: impl Iterator<Item = String>) -> (ExecArgs, A) {
73 let parsed_args = ProgramArgs::<A>::parse_from(args);
74 (parsed_args.run_args, parsed_args.system_args)
75}
76
77pub fn run<M: FullMachine>(system: M) -> ExecResult {
81 let parsed_args = ExecArgs::parse_from(std::env::args());
82 execute(system, parsed_args)
83}
84
85pub fn execute<M: FullMachine>(system: M, exec_args: ExecArgs) -> ExecResult {
89 let silent = exec_args.silent;
91 let batch = exec_args.batch;
92 let mut filter_level = match exec_args.verbose {
93 0 => log::LevelFilter::Info,
94 1 => log::LevelFilter::Debug,
95 _ => log::LevelFilter::Trace,
96 };
97 if silent {
98 filter_level = log::LevelFilter::Off;
99 }
100
101 let _ = env_logger::builder().filter_level(filter_level).try_init();
103
104 info!("Starting verification.");
105
106 let verification_result = verify(system, exec_args);
107
108 if log_enabled!(log::Level::Trace) {
109 trace!("Verification result: {:?}", verification_result);
110 }
111
112 if log_enabled!(log::Level::Info) {
113 match verification_result.result {
115 Ok(_) => info!("Verification ended."),
116 Err(_) => error!("Verification failed."),
117 }
118 }
119
120 if !silent {
121 if batch {
122 if let Err(err) = serde_json::to_writer(std::io::stdout(), &verification_result) {
124 panic!("Could not serialize verification result: {:?}", err);
125 }
126 } else {
127 info!("Verification result: {:?}", verification_result);
129 }
130 }
131 verification_result
132}
133
134fn verify<M: FullMachine>(system: M, run_args: ExecArgs) -> ExecResult {
136 let strategy = Strategy {
137 naive_inputs: run_args.naive_inputs,
138 use_decay: run_args.use_decay,
139 };
140 let mut refinery = Framework::<M>::new(system, strategy);
141
142 let result = if let Some(property_str) = run_args.property {
143 Proposition::parse(&property_str).map(Some)
144 } else {
145 Ok(None)
147 };
148 let result = result
149 .and_then(|proposition| refinery.verify_property(&proposition, run_args.assume_inherent));
150
151 ExecResult {
152 result,
153 stats: refinery.info(),
154 }
155}