Skip to main content

firmion_validation_phase/
validation_phase.rs

1// Assert validation and pre-output print phase.
2//
3// ValidationPhase walks the IR in source order, firing print and assert
4// instructions that appear before the IRKind::Output sentinel.  Print output
5// is visible even when a later assert fails.  The phase stops on the first
6// failed assert so that prints and notes preceding it have already appeared.
7//
8// NOTE: If extension return values are implemented, keep ValidationPhase
9// ordered after execute_extensions so extension output flows into ParmValDb
10// before assert evaluation.
11
12// Don't clutter upstream docs.rs for an otherwise private library.
13#![doc(hidden)]
14
15use anyhow::{Result, anyhow};
16use diags::Diags;
17use ir::IRKind;
18use irdb::IRDb;
19use ireval::{ParmValDb, evaluate_string_expr, execute_assert};
20
21#[allow(unused_imports)]
22use tracing::trace;
23
24pub struct ValidationPhase {}
25
26impl ValidationPhase {
27    pub fn validate(argvaldb: &ParmValDb, irdb: &IRDb, diags: &mut Diags) -> Result<()> {
28        trace!("ValidationPhase::validate:");
29        for ir in &irdb.ir_vec {
30            match ir.kind {
31                IRKind::Print if !diags.noprint => {
32                    if let Some(s) =
33                        evaluate_string_expr(&argvaldb.parms, &irdb.parms, &ir.operands, diags)
34                    {
35                        print!("{}", s);
36                    }
37                }
38                IRKind::Trace if diags.trace_enabled() => {
39                    if let Some(mut s) =
40                        evaluate_string_expr(&argvaldb.parms, &irdb.parms, &ir.operands, diags)
41                    {
42                        let prefix = format!("[Trace-{}] ", diags.trace_iteration);
43                        s.insert_str(0, &prefix);
44                        print!("{}", s);
45                    }
46                }
47                IRKind::Assert
48                    if !execute_assert(&argvaldb.parms, &irdb.parms, &irdb.ir_vec, ir, diags) =>
49                {
50                    return Err(anyhow!("Error detected"));
51                }
52                IRKind::Output => break,
53                _ => {}
54            }
55        }
56        Ok(())
57    }
58
59}