Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
rename verify -> validation
Browse files Browse the repository at this point in the history
doug-q committed Jun 6, 2024
1 parent aa93068 commit 3993a2d
Showing 3 changed files with 60 additions and 60 deletions.
64 changes: 33 additions & 31 deletions hugr-passes/src/const_fold.rs
Original file line number Diff line number Diff line change
@@ -23,21 +23,21 @@ use hugr_core::{
Hugr, HugrView, IncomingPort, Node, SimpleReplacement,
};

use crate::verify::{VerifyError, VerifyLevel};
use crate::validation::{ValidatePassError, ValidationLevel};

#[derive(Error, Debug)]
#[allow(missing_docs)]
pub enum ConstFoldError {
#[error(transparent)]
SimpleReplacementError(#[from] SimpleReplacementError),
#[error(transparent)]
VerifyError(#[from] VerifyError),
ValidationError(#[from] ValidatePassError),
}

#[derive(Debug, Clone, Copy, Default)]
/// A configuration for the Constant Folding pass.
pub struct ConstantFoldPass {
verify: VerifyLevel,
validation: ValidationLevel,
}

impl ConstantFoldPass {
@@ -46,9 +46,9 @@ impl ConstantFoldPass {
Self::default()
}

/// Build a `ConstFoldConfig` with the given [VerifyLevel].
pub fn verify_level(mut self, verify: VerifyLevel) -> Self {
self.verify = verify;
/// Build a `ConstFoldConfig` with the given [ValidationLevel].
pub fn validation_level(mut self, level: ValidationLevel) -> Self {
self.validation = level;
self
}

@@ -58,33 +58,35 @@ impl ConstantFoldPass {
hugr: &mut H,
reg: &ExtensionRegistry,
) -> Result<(), ConstFoldError> {
self.verify.run_verified_pass(hugr, reg, |hugr: &mut H, _| {
loop {
// We can only safely apply a single replacement. Applying a
// replacement removes nodes and edges which may be referenced by
// further replacements returned by find_consts. Even worse, if we
// attempted to apply those replacements, expecting them to fail if
// the nodes and edges they reference had been deleted, they may
// succeed because new nodes and edges reused the ids.
//
// We could be a lot smarter here, keeping track of `LoadConstant`
// nodes and only looking at their out neighbours.
let Some((replace, removes)) = find_consts(hugr, hugr.nodes(), reg).next() else {
break Ok(());
};
hugr.apply_rewrite(replace)?;
for rem in removes {
// We are optimistically applying these [RemoveLoadConstant] and
// [RemoveConst] rewrites without checking whether the nodes
// they attempt to remove have remaining uses. If they do, then
// the rewrite fails and we move on.
if let Ok(const_node) = hugr.apply_rewrite(rem) {
// if the LoadConst was removed, try removing the Const too.
let _ = hugr.apply_rewrite(RemoveConst(const_node));
self.validation
.run_validated_pass(hugr, reg, |hugr: &mut H, _| {
loop {
// We can only safely apply a single replacement. Applying a
// replacement removes nodes and edges which may be referenced by
// further replacements returned by find_consts. Even worse, if we
// attempted to apply those replacements, expecting them to fail if
// the nodes and edges they reference had been deleted, they may
// succeed because new nodes and edges reused the ids.
//
// We could be a lot smarter here, keeping track of `LoadConstant`
// nodes and only looking at their out neighbours.
let Some((replace, removes)) = find_consts(hugr, hugr.nodes(), reg).next()
else {
break Ok(());
};
hugr.apply_rewrite(replace)?;
for rem in removes {
// We are optimistically applying these [RemoveLoadConstant] and
// [RemoveConst] rewrites without checking whether the nodes
// they attempt to remove have remaining uses. If they do, then
// the rewrite fails and we move on.
if let Ok(const_node) = hugr.apply_rewrite(rem) {
// if the LoadConst was removed, try removing the Const too.
let _ = hugr.apply_rewrite(RemoveConst(const_node));
}
}
}
}
})
})
}
}

2 changes: 1 addition & 1 deletion hugr-passes/src/lib.rs
Original file line number Diff line number Diff line change
@@ -4,4 +4,4 @@ pub mod const_fold;
mod half_node;
pub mod merge_bbs;
pub mod nest_cfgs;
pub mod verify;
pub mod validation;
54 changes: 26 additions & 28 deletions hugr-passes/src/verify.rs → hugr-passes/src/validation.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//! Provides [VerifyLevel] with tools to run passes with configurable
//! verification.
//! Provides [ValidationLevel] with tools to run passes with configurable
//! validation.
use thiserror::Error;

@@ -12,38 +12,38 @@ use hugr_core::{
#[derive(Debug, Clone, Copy, Ord, Eq, PartialOrd, PartialEq)]
/// A type for running [HugrMut] algorithms with verification.
///
/// Provides [VerifyLevel::run_verified_pass] to invoke a closure with pre and post
/// verification.
/// Provides [ValidationLevel::run_validated_pass] to invoke a closure with pre and post
/// validation.
///
/// The default level is `None` because verification can be expensive.
pub enum VerifyLevel {
/// The default level is `None` because validation can be expensive.
pub enum ValidationLevel {
/// Do no verification.
None,
/// Verify using [HugrView::validate_no_extensions]. This is useful when you
/// Validate using [HugrView::validate_no_extensions]. This is useful when you
/// do not expect valid Extension annotations on Nodes.
WithoutExtensions,
/// Verify using [HugrView::validate].
/// Validate using [HugrView::validate].
WithExtensions,
}

#[derive(Error, Debug)]
#[allow(missing_docs)]
pub enum VerifyError {
#[error("Failed to verify input HUGR: {err}\n{pretty_hugr}")]
pub enum ValidatePassError {
#[error("Failed to validate input HUGR: {err}\n{pretty_hugr}")]
InputError {
#[source]
err: ValidationError,
pretty_hugr: String,
},
#[error("Failed to verify output HUGR: {err}\n{pretty_hugr}")]
#[error("Failed to validate output HUGR: {err}\n{pretty_hugr}")]
OutputError {
#[source]
err: ValidationError,
pretty_hugr: String,
},
}

impl Default for VerifyLevel {
impl Default for ValidationLevel {
fn default() -> Self {
if cfg!(test) {
// Many tests fail when run with Self::WithExtensions
@@ -54,44 +54,42 @@ impl Default for VerifyLevel {
}
}

impl VerifyLevel {
impl ValidationLevel {
/// Run an operation on a [HugrMut]. `hugr` will be verified according to
/// [self](VerifyLevel), then `pass` will be invoked. If `pass` succeeds
/// [self](ValidationLevel), then `pass` will be invoked. If `pass` succeeds
/// then `hugr` will be verified again.
pub fn run_verified_pass<H: HugrMut, E, T>(
pub fn run_validated_pass<H: HugrMut, E, T>(
&self,
hugr: &mut H,
reg: &ExtensionRegistry,
pass: impl FnOnce(&mut H, &Self) -> Result<T, E>,
) -> Result<T, E>
where
VerifyError: Into<E>,
ValidatePassError: Into<E>,
{
self.verify_impl(hugr, reg, |err, pretty_hugr| VerifyError::InputError {
err,
pretty_hugr,
self.validation_impl(hugr, reg, |err, pretty_hugr| {
ValidatePassError::InputError { err, pretty_hugr }
})?;
let result = pass(hugr, self)?;
self.verify_impl(hugr, reg, |err, pretty_hugr| VerifyError::OutputError {
err,
pretty_hugr,
self.validation_impl(hugr, reg, |err, pretty_hugr| {
ValidatePassError::OutputError { err, pretty_hugr }
})?;
Ok(result)
}

fn verify_impl<E>(
fn validation_impl<E>(
&self,
hugr: &impl HugrView,
reg: &ExtensionRegistry,
mk_err: impl FnOnce(ValidationError, String) -> VerifyError,
mk_err: impl FnOnce(ValidationError, String) -> ValidatePassError,
) -> Result<(), E>
where
VerifyError: Into<E>,
ValidatePassError: Into<E>,
{
match self {
VerifyLevel::None => Ok(()),
VerifyLevel::WithoutExtensions => hugr.validate_no_extensions(reg),
VerifyLevel::WithExtensions => hugr.validate(reg),
ValidationLevel::None => Ok(()),
ValidationLevel::WithoutExtensions => hugr.validate_no_extensions(reg),
ValidationLevel::WithExtensions => hugr.validate(reg),
}
.map_err(|err| mk_err(err, hugr.mermaid_string()).into())
}

0 comments on commit 3993a2d

Please sign in to comment.