1#![cfg_attr(coverage_nightly, coverage(off))]
3
4use super::*;
5
6pub struct PQLRunner {}
7
8impl PQLRunner {
9 #[allow(clippy::missing_panics_doc)]
13 pub fn try_run_stmt(stmt: &ast::Stmt<'_>) -> PQLResult<RunnerOutput> {
14 let mut rng = rand::rng();
15 let mut vm = Vm::from_stmt(stmt)?;
16 let n_trails = vm.static_data.n_trails;
17 let game = vm.static_data.game;
18
19 let mut output = RunnerOutput::new(game, &stmt.selectors);
20
21 for (idx, selector) in stmt.selectors.iter().enumerate() {
22 let program = vm::compile_selector(&mut vm, selector)?;
23 while output.n_succ < n_trails {
24 if output.n_fail == n_trails {
25 return Err(((0, 1), VmError::SamplingFailed).into());
27 }
28
29 match vm.sample(&mut rng) {
30 Some(()) => {
31 output.push_value(
32 idx,
33 program.execute(&mut vm.as_context())?,
34 );
35 output.n_succ += 1;
36 }
37 None => output.n_fail += 1,
38 }
39 }
40 }
41
42 Ok(output)
43 }
44
45 pub fn run<S: io::Write, T: io::Write>(
47 src: &str,
48 stream_out: &mut S,
49 stream_err: &mut T,
50 ) -> io::Result<()> {
51 match parse_pql(src) {
52 Ok(stmts) => {
53 for (i, stmt) in stmts.iter().enumerate() {
54 if i > 0 {
55 writeln!(stream_out, "{:-<80}", "")?;
56 }
57
58 match Self::try_run_stmt(stmt) {
59 Ok(output) => {
60 output.report_to_stream(stmt, stream_out)?;
61 writeln!(stream_out, "{} trials", output.n_succ)?;
62 }
63 Err(err) => {
64 writeln!(
65 stream_err,
66 "{err:?} {}",
67 &src[err.loc.0..err.loc.1]
68 )?;
69 }
70 }
71 }
72 }
73 Err(err) => writeln!(stream_err, "{err:?}")?,
74 }
75 Ok(())
76 }
77}