Skip to content

Commit

Permalink
Switch to the "kind" style for ValidationError (#288)
Browse files Browse the repository at this point in the history
In prepartion for adding data alongside it.
  • Loading branch information
jblebrun authored Jan 21, 2024
1 parent 2dd20cb commit b52fde6
Show file tree
Hide file tree
Showing 11 changed files with 102 additions and 68 deletions.
2 changes: 1 addition & 1 deletion tests-integration/src/spec/error.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use {
super::format::ActionResult,
wrausmt_format::{loader::LoaderError, text::location::Location, ValidationError},
wrausmt_format::{compiler::ValidationError, loader::LoaderError, text::location::Location},
wrausmt_runtime::{
runtime::{error::RuntimeError, values::Value},
syntax::Id,
Expand Down
27 changes: 14 additions & 13 deletions tests-integration/src/spec/error_mappings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@ use {
error::{BinaryParseError, BinaryParseErrorKind},
leb128::LEB128Error,
},
compiler::ValidationError,
loader::LoaderError,
text::{
parse::error::{ParseError, ParseErrorKind},
resolve::ResolveError,
},
ValidationError,
ValidationErrorKind,
},
wrausmt_runtime::runtime::error::{RuntimeErrorKind, TrapKind},
};
Expand Down Expand Up @@ -196,18 +197,18 @@ fn matches_resolve_error(failure: &str, err: &ResolveError) -> bool {
}

fn matches_validation_error(failure: &str, err: &ValidationError) -> bool {
match err {
ValidationError::ValStackUnderflow => ["type mismatch"].contains(&failure),
ValidationError::TypeMismatch { .. } => ["type mismatch"].contains(&failure),
ValidationError::ExpectedRef { .. } => ["type mismatch"].contains(&failure),
ValidationError::UnknownData => ["unknown data"].contains(&failure),
ValidationError::UnknownFunc => ["unknown func"].contains(&failure),
ValidationError::UnknownGlobal => ["unknown global"].contains(&failure),
ValidationError::UnknownMemory => ["unknown memory"].contains(&failure),
ValidationError::UnknownTable => ["unknown table"].contains(&failure),
ValidationError::UnknownType => ["unknown type"].contains(&failure),
ValidationError::ImmutableGlobal => ["global is immutable"].contains(&failure),
ValidationError::WrongTableType => ["wrong table type"].contains(&failure),
match err.kind() {
ValidationErrorKind::ValStackUnderflow => ["type mismatch"].contains(&failure),
ValidationErrorKind::TypeMismatch { .. } => ["type mismatch"].contains(&failure),
ValidationErrorKind::ExpectedRef { .. } => ["type mismatch"].contains(&failure),
ValidationErrorKind::UnknownData => ["unknown data"].contains(&failure),
ValidationErrorKind::UnknownFunc => ["unknown func"].contains(&failure),
ValidationErrorKind::UnknownGlobal => ["unknown global"].contains(&failure),
ValidationErrorKind::UnknownMemory => ["unknown memory"].contains(&failure),
ValidationErrorKind::UnknownTable => ["unknown table"].contains(&failure),
ValidationErrorKind::UnknownType => ["unknown type"].contains(&failure),
ValidationErrorKind::ImmutableGlobal => ["global is immutable"].contains(&failure),
ValidationErrorKind::WrongTableType => ["wrong table type"].contains(&failure),
_ => false,
}
}
9 changes: 7 additions & 2 deletions wrausmt-format/src/compiler/emitter.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use {
super::validation::{ModuleContext, Result, Validation, ValidationMode},
super::{
validation::{ModuleContext, Result, Validation, ValidationMode},
ValidationError,
},
wrausmt_runtime::{
instructions::{op_consts, opcodes},
syntax::{
Expand Down Expand Up @@ -264,7 +267,9 @@ impl<'a> ValidatingEmitter<'a> {

impl<'a> Emitter for ValidatingEmitter<'a> {
fn validate_instr(&mut self, instr: &Instruction<Resolved>) -> Result<()> {
self.validation.handle_instr(instr)
self.validation
.handle_instr(instr)
.map_err(ValidationError::new)
}

fn emit8(&mut self, v: u8) {
Expand Down
2 changes: 1 addition & 1 deletion wrausmt-format/src/compiler/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
mod emitter;
mod validation;
pub use validation::{ValidationError, ValidationMode};
pub use validation::{ValidationError, ValidationErrorKind, ValidationMode};
use {
self::{emitter::ValidatingEmitter, validation::ModuleContext},
validation::Result,
Expand Down
26 changes: 25 additions & 1 deletion wrausmt-format/src/compiler/validation/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ mod ops;
mod stacks;

#[derive(Debug)]
pub enum ValidationError {
pub enum ValidationErrorKind {
ValStackUnderflow,
CtrlStackUnderflow,
MemoryTooLarge,
Expand Down Expand Up @@ -53,6 +53,29 @@ pub enum ValidationError {
WrongTableType,
}

#[derive(Debug)]
pub struct ValidationError {
kind: ValidationErrorKind,
}

impl ValidationError {
pub fn new(kind: ValidationErrorKind) -> ValidationError {
ValidationError { kind }
}

pub fn kind(&self) -> &ValidationErrorKind {
&self.kind
}
}

impl std::fmt::Display for ValidationError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
writeln!(f, "{:?}", self.kind)
}
}

impl std::error::Error for ValidationError {}

/// How to treat Validator issues.
#[derive(Debug, Default, Clone, Copy)]
pub enum ValidationMode {
Expand All @@ -65,6 +88,7 @@ pub enum ValidationMode {
// Use panic to abort the entire process if validation fails.
Panic,
}
pub type KindResult<T> = std::result::Result<T, ValidationErrorKind>;
pub type Result<T> = std::result::Result<T, ValidationError>;

/// Type representations during validation.
Expand Down
69 changes: 36 additions & 33 deletions wrausmt-format/src/compiler/validation/ops.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use {
super::{FunctionType, Result, Validation, ValidationError, ValidationMode},
super::{FunctionType, KindResult as Result, Validation, ValidationErrorKind, ValidationMode},
crate::compiler::validation::ValidationType,
wrausmt_common::true_or::TrueOr,
wrausmt_runtime::{
Expand Down Expand Up @@ -87,7 +87,8 @@ impl<'a> Validation<'a> {
alignment: u32,
natural_alignment: u32,
) -> Result<()> {
(alignment <= natural_alignment).true_or(ValidationError::AlignmentTooLarge(alignment))?;
(alignment <= natural_alignment)
.true_or(ValidationErrorKind::AlignmentTooLarge(alignment))?;
self.stacks.pop_val(i)?;
self.stacks.push_val(o);
Ok(())
Expand All @@ -100,7 +101,8 @@ impl<'a> Validation<'a> {
alignment: u32,
natural_alignment: u32,
) -> Result<()> {
(alignment <= natural_alignment).true_or(ValidationError::AlignmentTooLarge(alignment))?;
(alignment <= natural_alignment)
.true_or(ValidationErrorKind::AlignmentTooLarge(alignment))?;
self.stacks.pop_val(v)?;
self.stacks.pop_val(a)?;
Ok(())
Expand All @@ -117,7 +119,7 @@ impl<'a> Validation<'a> {
fn local_type(&self, idx: &Index<Resolved, LocalIndex>) -> Result<ValueType> {
self.localtypes
.get(idx.value() as usize)
.ok_or(ValidationError::UnknownLocal(idx.clone()))
.ok_or(ValidationErrorKind::UnknownLocal(idx.clone()))
.copied()
}

Expand Down Expand Up @@ -151,7 +153,7 @@ impl<'a> Validation<'a> {

instr!(opcodes::ELSE) => {
let frame = self.stacks.pop_ctrl()?;
(frame.opcode == opcodes::IF).true_or(ValidationError::OpcodeMismatch)?;
(frame.opcode == opcodes::IF).true_or(ValidationErrorKind::OpcodeMismatch)?;
self.stacks
.push_ctrl(frame.opcode, frame.start_types, frame.end_types);
Ok(())
Expand Down Expand Up @@ -188,7 +190,8 @@ impl<'a> Validation<'a> {
let default_arity = self.stacks.label_arity(last)?;
for idx in idxes {
let break_arity = self.stacks.label_arity(idx)?;
(break_arity == default_arity).true_or(ValidationError::BreakTypeMismatch)?;
(break_arity == default_arity)
.true_or(ValidationErrorKind::BreakTypeMismatch)?;
self.stacks.pop_label_types(idx)?;
self.stacks.push_label_types(idx)?;
}
Expand All @@ -211,7 +214,7 @@ impl<'a> Validation<'a> {
.module
.funcs
.get(idx.value() as usize)
.ok_or(ValidationError::UnknownFunc)?;
.ok_or(ValidationErrorKind::UnknownFunc)?;
self.stacks.pop_vals(&ft.params)?;
self.stacks.push_vals(&ft.results);
Ok(())
Expand All @@ -222,13 +225,13 @@ impl<'a> Validation<'a> {
.tables
.get(tabidx.value() as usize)
.map(|t| t.reftype == RefType::Func)
.ok_or(ValidationError::UnknownTable)?
.true_or(ValidationError::WrongTableType)?;
.ok_or(ValidationErrorKind::UnknownTable)?
.true_or(ValidationErrorKind::WrongTableType)?;
let ft = self
.module
.types
.get(typeuse.index().value() as usize)
.ok_or(ValidationError::UnknownType)?;
.ok_or(ValidationErrorKind::UnknownType)?;
self.stacks.pop_val(I32)?;
self.stacks.pop_vals(&ft.params)?;
self.stacks.push_vals(&ft.results);
Expand All @@ -241,15 +244,15 @@ impl<'a> Validation<'a> {
self.stacks.pop_val(I32)?;
let n1 = self.stacks.pop_num()?;
let n2 = self.stacks.pop_num()?;
(n1 == n2).true_or(ValidationError::TypeMismatch {
(n1 == n2).true_or(ValidationErrorKind::TypeMismatch {
actual: ValidationType::Value(n2.into()),
expect: ValidationType::Value(n1.into()),
})?;
self.stacks.push_val(n1.into());
Ok(())
}
instr!(opcodes::SELECT => Operands::SelectT(t)) => {
(t.len() == 1).true_or(ValidationError::UnsupportedSelect)?;
(t.len() == 1).true_or(ValidationErrorKind::UnsupportedSelect)?;
let vt = t[0].valuetype;
self.stacks.pop_val(I32)?;
self.stacks.pop_val(vt)?;
Expand Down Expand Up @@ -278,7 +281,7 @@ impl<'a> Validation<'a> {
.module
.globals
.get(idx.value() as usize)
.ok_or(ValidationError::UnknownGlobal)?;
.ok_or(ValidationErrorKind::UnknownGlobal)?;
self.stacks.push_val(global.valtype);
Ok(())
}
Expand All @@ -287,8 +290,8 @@ impl<'a> Validation<'a> {
.module
.globals
.get(idx.value() as usize)
.ok_or(ValidationError::UnknownGlobal)?;
(global.mutable).true_or(ValidationError::ImmutableGlobal)?;
.ok_or(ValidationErrorKind::UnknownGlobal)?;
(global.mutable).true_or(ValidationErrorKind::ImmutableGlobal)?;
self.stacks.pop_val(global.valtype)?;
Ok(())
}
Expand All @@ -297,7 +300,7 @@ impl<'a> Validation<'a> {
.module
.tables
.get(idx.value() as usize)
.ok_or(ValidationError::UnknownTable)?;
.ok_or(ValidationErrorKind::UnknownTable)?;
self.stacks.pop_val(I32)?;
self.stacks.push_val(table.reftype.into());
Ok(())
Expand All @@ -307,7 +310,7 @@ impl<'a> Validation<'a> {
.module
.tables
.get(idx.value() as usize)
.ok_or(ValidationError::UnknownTable)?;
.ok_or(ValidationErrorKind::UnknownTable)?;
self.stacks.pop_val(I32)?;
self.stacks.pop_val(table.reftype.into())?;
Ok(())
Expand Down Expand Up @@ -340,12 +343,12 @@ impl<'a> Validation<'a> {
meminstr!(opcodes::I64_STORE32, align: a) => self.storeop(I64, I32, *a, 4),

instr!(opcodes::MEMORY_SIZE) => {
(!self.module.mems.is_empty()).true_or(ValidationError::UnknownMemory)?;
(!self.module.mems.is_empty()).true_or(ValidationErrorKind::UnknownMemory)?;
self.stacks.push_val(I32);
Ok(())
}
instr!(opcodes::MEMORY_GROW) => {
(!self.module.mems.is_empty()).true_or(ValidationError::UnknownMemory)?;
(!self.module.mems.is_empty()).true_or(ValidationErrorKind::UnknownMemory)?;
self.stacks.pop_val(I32)?;
self.stacks.push_val(I32);
Ok(())
Expand Down Expand Up @@ -528,7 +531,7 @@ impl<'a> Validation<'a> {
}
instr!(opcodes::REF_FUNC => Operands::FuncIndex(idx)) => {
((idx.value() as usize) < self.module.funcs.len())
.true_or(ValidationError::UnknownFunc)?;
.true_or(ValidationErrorKind::UnknownFunc)?;
self.stacks.push_val(FUNC);
Ok(())
}
Expand All @@ -545,45 +548,45 @@ impl<'a> Validation<'a> {
// 0xFC 0x08
instr!(opcodes::MEMORY_INIT => Operands::DataIndex(idx)) => {
((idx.value() as usize) < self.module.datas)
.true_or(ValidationError::UnknownData)?;
(!self.module.mems.is_empty()).true_or(ValidationError::UnknownMemory)?;
.true_or(ValidationErrorKind::UnknownData)?;
(!self.module.mems.is_empty()).true_or(ValidationErrorKind::UnknownMemory)?;
self.stacks.pop_val(I32)?;
self.stacks.pop_val(I32)?;
self.stacks.pop_val(I32)?;
Ok(())
}
instr!(opcodes::DATA_DROP => Operands::DataIndex(idx)) => {
((idx.value() as usize) < self.module.datas)
.true_or(ValidationError::UnknownData)?;
.true_or(ValidationErrorKind::UnknownData)?;
Ok(())
}
instr!(opcodes::MEMORY_COPY) | instr!(opcodes::MEMORY_FILL) => {
(0 < self.module.datas).true_or(ValidationError::UnknownMemory)?;
(0 < self.module.datas).true_or(ValidationErrorKind::UnknownMemory)?;
self.stacks.pop_val(I32)?;
self.stacks.pop_val(I32)?;
self.stacks.pop_val(I32)?;
Ok(())
}
instr!(opcodes::TABLE_INIT => Operands::TableInit(tidx, eidx)) => {
((tidx.value() as usize) < self.module.tables.len())
.true_or(ValidationError::UnknownTable)?;
.true_or(ValidationErrorKind::UnknownTable)?;
((eidx.value() as usize) < self.module.elems.len())
.true_or(ValidationError::UnknownElem)?;
.true_or(ValidationErrorKind::UnknownElem)?;
self.stacks.pop_val(I32)?;
self.stacks.pop_val(I32)?;
self.stacks.pop_val(I32)?;
Ok(())
}
instr!(opcodes::ELEM_DROP => Operands::ElemIndex(idx)) => {
((idx.value() as usize) < self.module.elems.len())
.true_or(ValidationError::UnknownElem)?;
.true_or(ValidationErrorKind::UnknownElem)?;
Ok(())
}
instr!(opcodes::TABLE_COPY => Operands::TableCopy(srcidx, dstidx)) => {
((srcidx.value() as usize) < self.module.tables.len())
.true_or(ValidationError::UnknownTable)?;
.true_or(ValidationErrorKind::UnknownTable)?;
((dstidx.value() as usize) < self.module.tables.len())
.true_or(ValidationError::UnknownTable)?;
.true_or(ValidationErrorKind::UnknownTable)?;
self.stacks.pop_val(I32)?;
self.stacks.pop_val(I32)?;
self.stacks.pop_val(I32)?;
Expand All @@ -594,15 +597,15 @@ impl<'a> Validation<'a> {
.module
.tables
.get(idx.value() as usize)
.ok_or(ValidationError::UnknownTable)?;
.ok_or(ValidationErrorKind::UnknownTable)?;
self.stacks.pop_val(I32)?;
self.stacks.pop_val(tabletype.reftype.into())?;
self.stacks.push_val(I32);
Ok(())
}
instr!(opcodes::TABLE_SIZE => Operands::TableIndex(idx)) => {
((idx.value() as usize) < self.module.tables.len())
.true_or(ValidationError::UnknownTable)?;
.true_or(ValidationErrorKind::UnknownTable)?;
self.stacks.push_val(I32);
Ok(())
}
Expand All @@ -611,15 +614,15 @@ impl<'a> Validation<'a> {
.module
.tables
.get(idx.value() as usize)
.ok_or(ValidationError::UnknownTable)?;
.ok_or(ValidationErrorKind::UnknownTable)?;
println!("TABLEF FILL FOR REFTYPE {:?}", tabletype.reftype);
self.stacks.pop_val(I32)?;
self.stacks.pop_val(tabletype.reftype.into())?;
self.stacks.pop_val(I32)?;
Ok(())
}

_ => Err(ValidationError::UnhandledInstruction(instr.clone())),
_ => Err(ValidationErrorKind::UnhandledInstruction(instr.clone())),
}
}
}
Loading

0 comments on commit b52fde6

Please sign in to comment.