Skip to content

Commit

Permalink
add details to error messages in EvalError variants;
Browse files Browse the repository at this point in the history
  • Loading branch information
greenhat committed Aug 21, 2023
1 parent b019605 commit 46b0d68
Show file tree
Hide file tree
Showing 9 changed files with 58 additions and 36 deletions.
5 changes: 3 additions & 2 deletions ergotree-interpreter/src/eval/decode_point.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ impl Evaluable for DecodePoint {
fn eval(&self, env: &mut Env, ctx: &mut EvalContext) -> Result<Value, EvalError> {
let point_bytes = self.input.eval(env, ctx)?.try_extract_into::<Vec<u8>>()?;
let point: EcPoint = SigmaSerializable::sigma_parse_bytes(&point_bytes).map_err(|_| {
Misc(String::from(
"DecodePoint: Failed to parse EC point from bytes",
Misc(format!(
"DecodePoint: Failed to parse EC point from bytes {:?}",
point_bytes,
))
})?;
Ok(point.into())
Expand Down
6 changes: 3 additions & 3 deletions ergotree-interpreter/src/eval/deserialize_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@ impl Evaluable for DeserializeContext {
let expected_tpe = SType::SColl(SType::SByte.into());
if c.tpe != expected_tpe {
Err(EvalError::UnexpectedExpr(format!(
"DeserializeContext: expected extension value to have type {:?} got {:?}",
expected_tpe, c.tpe
"DeserializeContext: expected extension value {} with id {} to have type {:?} got {:?}",
c, self.id, expected_tpe, c.tpe
)))
} else {
let bytes = c.v.clone().try_extract_into::<Vec<u8>>()?;
let expr = Expr::sigma_parse_bytes(bytes.as_slice())?;
if expr.tpe() != self.tpe {
return Err(EvalError::UnexpectedExpr(format!("DeserializeContext: expected deserialized expr to have type {:?}, got {:?}", self.tpe, expr.tpe())));
return Err(EvalError::UnexpectedExpr(format!("DeserializeContext: expected deserialized expr from extension value {} with id {} to have type {:?}, got {:?}", c, self.id, self.tpe, expr.tpe())));
}
expr.eval(env, ctx)
}
Expand Down
27 changes: 11 additions & 16 deletions ergotree-interpreter/src/eval/deserialize_register.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::convert::TryInto;

use ergotree_ir::chain::ergo_box::RegisterId;
use ergotree_ir::mir::constant::TryExtractInto;
use ergotree_ir::mir::deserialize_register::DeserializeRegister;
use ergotree_ir::mir::expr::Expr;
Expand All @@ -14,26 +15,22 @@ use crate::eval::Evaluable;

impl Evaluable for DeserializeRegister {
fn eval(&self, env: &mut Env, ctx: &mut EvalContext) -> Result<Value, EvalError> {
match ctx
.ctx
.self_box
.get_register(self.reg.try_into().map_err(|e| {
EvalError::RegisterIdOutOfBounds(format!(
"register index is out of bounds: {:?} ",
e
))
})?) {
let reg_id: RegisterId = self.reg.try_into().map_err(|e| {
EvalError::RegisterIdOutOfBounds(format!("register index is out of bounds: {:?} ", e))
})?;
match ctx.ctx.self_box.get_register(reg_id) {
Ok(Some(c)) => {
if c.tpe != SType::SColl(SType::SByte.into()) {
Err(EvalError::UnexpectedExpr(format!(
"DeserializeRegister: expected value to have type SColl(SByte), got {:?}",
c.tpe
"DeserializeRegister: expected register {} value {} to have type SColl(SByte), got {:?}",
reg_id, c, c.tpe
)))
} else {
let bytes = c.v.try_extract_into::<Vec<u8>>()?;
let expr = Expr::sigma_parse_bytes(bytes.as_slice())?;
if expr.tpe() != self.tpe {
Err(EvalError::UnexpectedExpr(format!("DeserializeRegister: expected deserialized expr to have type {:?}, got {:?}", self.tpe, expr.tpe())))
let pretty_expr = expr.to_string_pretty();
Err(EvalError::UnexpectedExpr(format!("DeserializeRegister: expected register {reg_id} deserialized expr {pretty_expr} to have type {:?}, got {:?}", self.tpe, expr.tpe())))
} else {
expr.eval(env, ctx)
}
Expand All @@ -42,15 +39,13 @@ impl Evaluable for DeserializeRegister {
Ok(None) => match &self.default {
Some(default_expr) => eval_default(&self.tpe, default_expr, env, ctx),
None => Err(EvalError::NotFound(format!(
"DeserializeRegister: register {:?} is empty",
self.reg
"DeserializeRegister: register {reg_id} is empty"
))),
},
Err(e) => match &self.default {
Some(default_expr) => eval_default(&self.tpe, default_expr, env, ctx),
None => Err(EvalError::NotFound(format!(
"DeserializeRegister: failed to get the register id {} with error: {e:?}",
self.reg
"DeserializeRegister: failed to get the register id {reg_id} with error: {e:?}"
))),
},
}
Expand Down
3 changes: 0 additions & 3 deletions ergotree-interpreter/src/eval/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,6 @@ pub enum EvalError {
/// ErgoTree error
#[error("ErgoTree error: {0}")]
ErgoTreeError(#[from] ErgoTreeError),
/// Not yet implemented
#[error("evaluation is not yet implemented: {0}")]
NotImplementedYet(&'static str),
/// Invalid item quantity for BoundedVec
#[error("Invalid item quantity for BoundedVec: {0}")]
BoundedVecError(#[from] BoundedVecOutOfBounds),
Expand Down
8 changes: 5 additions & 3 deletions ergotree-interpreter/src/eval/extract_reg_as.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@ impl Evaluable for ExtractRegisterAs {
.eval(env, ctx)?
.try_extract_into::<Arc<ErgoBox>>()?;
let id = self.register_id.try_into().map_err(|e| {
EvalError::RegisterIdOutOfBounds(format!("register index is out of bounds: {:?} ", e))
EvalError::RegisterIdOutOfBounds(format!(
"register index {} is out of bounds: {:?} ",
self.register_id, e
))
})?;
let reg_val_opt = ir_box.get_register(id).map_err(|e| {
EvalError::NotFound(format!(
"Error getting the register id {:?} with error {e:?}",
id
"Error getting the register id {id} with error {e:?}"
))
})?;
Ok(Value::Opt(Box::new(reg_val_opt.map(|c| Value::from(c.v)))))
Expand Down
15 changes: 8 additions & 7 deletions ergotree-interpreter/src/eval/sbox.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,20 @@ pub(crate) static GET_REG_EVAL_FN: EvalFn = |_env, _ctx, obj, args| {
.get(0)
.cloned()
.ok_or_else(|| EvalError::NotFound("register index is missing".to_string()))?
.try_extract_into::<i8>()?
.try_into()
.map_err(|e| {
EvalError::RegisterIdOutOfBounds(format!("register index is out of bounds: {:?} ", e))
})?;
.try_extract_into::<i8>()?;
let reg_id = reg_id.try_into().map_err(|e| {
EvalError::RegisterIdOutOfBounds(format!(
"register index {reg_id} is out of bounds: {:?} ",
e
))
})?;

Ok(Value::Opt(Box::new(
obj.try_extract_into::<Arc<ErgoBox>>()?
.get_register(reg_id)
.map_err(|e| {
EvalError::NotFound(format!(
"Error getting the register id {:?} with error {e:?}",
reg_id
"Error getting the register id {reg_id} with error {e:?}"
))
})?
.map(|c| Value::from(c.v)),
Expand Down
15 changes: 13 additions & 2 deletions ergotree-ir/src/chain/ergo_box/register/id.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::fmt::Display;

use derive_more::From;
use thiserror::Error;

Expand Down Expand Up @@ -52,8 +54,17 @@ impl TryFrom<u8> for RegisterId {
}
}

impl Display for RegisterId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
RegisterId::MandatoryRegisterId(id) => write!(f, "{}", id),
RegisterId::NonMandatoryRegisterId(id) => write!(f, "{}", id),
}
}
}

/// Register ids that every box have (box properties exposed as registers)
#[derive(PartialEq, Eq, Debug, Clone, Copy)]
#[derive(PartialEq, Eq, Debug, Clone, Copy, derive_more::Display)]
pub enum MandatoryRegisterId {
/// Monetary value, in Ergo tokens
R0 = 0,
Expand All @@ -80,7 +91,7 @@ impl TryFrom<i8> for MandatoryRegisterId {
}

/// newtype for additional registers R4 - R9
#[derive(PartialEq, Eq, Hash, Debug, Clone, Copy)]
#[derive(PartialEq, Eq, Hash, Debug, Clone, Copy, derive_more::Display)]
#[cfg_attr(feature = "json", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "json", serde(into = "String", try_from = "String"))]
#[repr(u8)]
Expand Down
10 changes: 10 additions & 0 deletions ergotree-ir/src/mir/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
use std::convert::TryFrom;
use std::convert::TryInto;

use crate::pretty_printer::PosTrackingWriter;
use crate::pretty_printer::Print;
use crate::source_span::Spanned;
use crate::types::stype::LiftIntoSType;
use crate::types::stype::SType;
Expand Down Expand Up @@ -328,6 +330,14 @@ impl Expr {
let tree = format!("{:#?}", self);
tree
}

/// Pretty prints the tree
pub fn to_string_pretty(&self) -> String {
let mut printer = PosTrackingWriter::new();
#[allow(clippy::unwrap_used)] // it only fail due to formatting errors
let _spanned_expr = self.print(&mut printer).unwrap();
printer.as_string()
}
}

impl<T: Into<Literal> + LiftIntoSType> From<T> for Expr {
Expand Down
5 changes: 5 additions & 0 deletions ergotree-ir/src/pretty_printer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,11 @@ impl PosTrackingWriter {
pub fn get_buf(&self) -> &str {
&self.print_buf
}

/// Get printed buffer as String
pub fn as_string(self) -> String {
self.print_buf
}
}

impl Default for PosTrackingWriter {
Expand Down

0 comments on commit 46b0d68

Please sign in to comment.