From 9e62181caae8ffbbd18dab0f1cdacd6149b97255 Mon Sep 17 00:00:00 2001 From: rvcas Date: Wed, 20 Jul 2022 23:53:57 -0400 Subject: [PATCH] feat: new Error not a constant --- add_integers.uplc | 8 +++--- crates/uplc/src/ast.rs | 10 +------- crates/uplc/src/flat.rs | 8 ------ crates/uplc/src/machine.rs | 39 ++++++++++++++++++------------ crates/uplc/src/machine/error.rs | 10 +++++--- crates/uplc/src/machine/runtime.rs | 10 ++------ crates/uplc/src/pretty.rs | 1 - 7 files changed, 36 insertions(+), 50 deletions(-) diff --git a/add_integers.uplc b/add_integers.uplc index eab073b4..b5f59196 100644 --- a/add_integers.uplc +++ b/add_integers.uplc @@ -1,7 +1,5 @@ (program 1.0.0 - [ - [ [ (force (builtin ifThenElse)) (con integer 2) ] (con integer 1) ] - (con string "yo") - ] -) \ No newline at end of file + [ (force (builtin ifThenElse)) (con string "yo") (con integer 3) (con integer 4) ] +) + diff --git a/crates/uplc/src/ast.rs b/crates/uplc/src/ast.rs index 2443de28..5b96f5cc 100644 --- a/crates/uplc/src/ast.rs +++ b/crates/uplc/src/ast.rs @@ -25,12 +25,6 @@ where /// We use this to apply the validator to Datum, /// then redeemer, then ScriptContext. If datum is /// even necessary (i.e. minting policy). - /// - /// ```rust - /// program.apply(&datum) - /// .apply(&redeemer) - /// .apply(&script_context); - /// ``` pub fn apply(&self, program: &Self) -> Self { let applied_term = Term::Apply { function: Box::new(self.term.clone()), @@ -86,10 +80,8 @@ pub enum Constant { // tag: 2 String(String), // tag: 3 - Char(char), - // tag: 4 Unit, - // tag: 5 + // tag: 4 Bool(bool), } diff --git a/crates/uplc/src/flat.rs b/crates/uplc/src/flat.rs index 3e4663ec..04056f9d 100644 --- a/crates/uplc/src/flat.rs +++ b/crates/uplc/src/flat.rs @@ -170,14 +170,6 @@ impl Encode for &Constant { encode_constant(2, e)?; s.encode(e)?; } - // there is no char constant tag - Constant::Char(c) => { - let mut b = [0; 4]; - - let s = c.encode_utf8(&mut b); - - s.as_bytes().encode(e)?; - } Constant::Unit => encode_constant(3, e)?, Constant::Bool(b) => { encode_constant(4, e)?; diff --git a/crates/uplc/src/machine.rs b/crates/uplc/src/machine.rs index 2bc28244..a3a7ed3b 100644 --- a/crates/uplc/src/machine.rs +++ b/crates/uplc/src/machine.rs @@ -377,22 +377,31 @@ impl Value { Value::Builtin { .. } => 1, } } -} -impl From<&Value> for Type { - fn from(value: &Value) -> Self { - match value { - Value::Con(constant) => match constant { - Constant::Integer(_) => Type::Integer, - Constant::ByteString(_) => Type::ByteString, - Constant::String(_) => Type::String, - Constant::Char(_) => todo!(), - Constant::Unit => Type::Unit, - Constant::Bool(_) => Type::Bool, - }, - Value::Delay(_) => todo!(), - Value::Lambda { .. } => todo!(), - Value::Builtin { .. } => todo!(), + pub fn expect_type(&self, r#type: Type) -> Result<(), Error> { + match self { + Value::Con(constant) => { + let constant_type = Type::from(constant); + + if constant_type == r#type { + Ok(()) + } else { + Err(Error::TypeMismatch(r#type, constant_type)) + } + } + rest => Err(Error::NotAConstant(rest.clone())), + } + } +} + +impl From<&Constant> for Type { + fn from(constant: &Constant) -> Self { + match constant { + Constant::Integer(_) => Type::Integer, + Constant::ByteString(_) => Type::ByteString, + Constant::String(_) => Type::String, + Constant::Unit => Type::Unit, + Constant::Bool(_) => Type::Bool, } } } diff --git a/crates/uplc/src/machine/error.rs b/crates/uplc/src/machine/error.rs index b104906d..9c0aa7e7 100644 --- a/crates/uplc/src/machine/error.rs +++ b/crates/uplc/src/machine/error.rs @@ -12,13 +12,13 @@ pub enum Error { OutOfExError(ExBudget), #[error("Invalid Stepkind: {0}")] InvalidStepKind(u8), - #[error("Cannot evaluate an open term: {0:#?}")] + #[error("Cannot evaluate an open term:\n\n{0:#?}")] OpenTermEvaluated(Term), #[error("The provided Plutus code called 'error'.")] EvaluationFailure, - #[error("Attempted to instantiate a non-polymorphic term: {0:#?}")] + #[error("Attempted to instantiate a non-polymorphic term:\n\n{0:#?}")] NonPolymorphicInstantiation(Value), - #[error("Attempted to apply a non-function: {0:#?}")] + #[error("Attempted to apply a non-function:\n\n{0:#?}")] NonFunctionalApplication(Value), #[error("Type mismatch expected '{0}' got '{1}'")] TypeMismatch(Type, Type), @@ -26,9 +26,11 @@ pub enum Error { UnexpectedBuiltinTermArgument(Term), #[error("A builtin expected a term argument, but something else was received:\n\n{}\n\nYou probably have an extra force wrapped around a builtin", .0.to_pretty())] BuiltinTermArgumentExpected(Term), + #[error("Unable to unlift value because it is not a constant:\n\n{0:#?}")] + NotAConstant(Value), } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq)] pub enum Type { Bool, Integer, diff --git a/crates/uplc/src/machine/runtime.rs b/crates/uplc/src/machine/runtime.rs index a213e320..2f6fef6b 100644 --- a/crates/uplc/src/machine/runtime.rs +++ b/crates/uplc/src/machine/runtime.rs @@ -188,13 +188,7 @@ impl DefaultFunction { pub fn check_type(&self, arg: &Value, args: &[Value]) -> Result<(), Error> { match self { - DefaultFunction::AddInteger => { - if arg.is_integer() { - Ok(()) - } else { - Err(Error::TypeMismatch(Type::Integer, arg.into())) - } - } + DefaultFunction::AddInteger => arg.expect_type(Type::Integer), DefaultFunction::SubtractInteger => todo!(), DefaultFunction::MultiplyInteger => todo!(), DefaultFunction::DivideInteger => todo!(), @@ -224,7 +218,7 @@ impl DefaultFunction { DefaultFunction::DecodeUtf8 => todo!(), DefaultFunction::IfThenElse => { if args.is_empty() && !arg.is_bool() { - Err(Error::TypeMismatch(Type::Bool, arg.into())) + arg.expect_type(Type::Bool) } else { Ok(()) } diff --git a/crates/uplc/src/pretty.rs b/crates/uplc/src/pretty.rs index 23bdbe1c..cf4ddc54 100644 --- a/crates/uplc/src/pretty.rs +++ b/crates/uplc/src/pretty.rs @@ -164,7 +164,6 @@ impl Constant { .append(RcDoc::text("\"")) .append(RcDoc::text(s)) .append(RcDoc::text("\"")), - Constant::Char(c) => unimplemented!("char: {}", c), Constant::Unit => RcDoc::text("unit") .append(RcDoc::line()) .append(RcDoc::text("()")),