From c88e5df8b19411be00ed3eb7c4e747e28429f51f Mon Sep 17 00:00:00 2001 From: Kasey White Date: Mon, 29 Aug 2022 23:46:24 -0400 Subject: [PATCH] finish up builtin implementations for Vasil --- add_integers.uplc | 2 +- crates/uplc/src/machine.rs | 12 ++++++ crates/uplc/src/machine/cost_model.rs | 28 +++++++++++-- crates/uplc/src/machine/error.rs | 2 + crates/uplc/src/machine/runtime.rs | 60 ++++++++++++++++++++------- 5 files changed, 83 insertions(+), 21 deletions(-) diff --git a/add_integers.uplc b/add_integers.uplc index d01743f8..fa621147 100644 --- a/add_integers.uplc +++ b/add_integers.uplc @@ -1,5 +1,5 @@ (program 1.0.0 - [(builtin iData) (con integer 1)] + [(force (force (builtin fstPair))) (con (pair integer bytestring) (22, #1122aabb))] ) diff --git a/crates/uplc/src/machine.rs b/crates/uplc/src/machine.rs index 6b80e518..0394d737 100644 --- a/crates/uplc/src/machine.rs +++ b/crates/uplc/src/machine.rs @@ -553,6 +553,18 @@ impl Value { Err(Error::ListTypeMismatch(constant_type)) } } + + pub fn expect_pair(&self) -> Result<(), Error> { + let constant: Constant = self.clone().try_into()?; + + let constant_type = Type::from(&constant); + + if matches!(constant_type, Type::Pair(_, _)) { + Ok(()) + } else { + Err(Error::PairTypeMismatch(constant_type)) + } + } } impl TryFrom for Type { diff --git a/crates/uplc/src/machine/cost_model.rs b/crates/uplc/src/machine/cost_model.rs index dab14661..78ddcf42 100644 --- a/crates/uplc/src/machine/cost_model.rs +++ b/crates/uplc/src/machine/cost_model.rs @@ -794,9 +794,26 @@ impl BuiltinCosts { .cpu .cost(args[0].to_ex_mem(), args[1].to_ex_mem()), }, - DefaultFunction::FstPair => todo!(), - DefaultFunction::SndPair => todo!(), - DefaultFunction::ChooseList => todo!(), + DefaultFunction::FstPair => ExBudget { + mem: self.fst_pair.mem.cost(args[0].to_ex_mem()), + cpu: self.fst_pair.cpu.cost(args[0].to_ex_mem()), + }, + DefaultFunction::SndPair => ExBudget { + mem: self.snd_pair.mem.cost(args[0].to_ex_mem()), + cpu: self.snd_pair.cpu.cost(args[0].to_ex_mem()), + }, + DefaultFunction::ChooseList => ExBudget { + mem: self.choose_list.mem.cost( + args[0].to_ex_mem(), + args[1].to_ex_mem(), + args[2].to_ex_mem(), + ), + cpu: self.choose_list.cpu.cost( + args[0].to_ex_mem(), + args[1].to_ex_mem(), + args[2].to_ex_mem(), + ), + }, DefaultFunction::MkCons => ExBudget { mem: self .mk_cons @@ -893,7 +910,10 @@ impl BuiltinCosts { .cpu .cost(args[0].to_ex_mem(), args[1].to_ex_mem()), }, - DefaultFunction::SerialiseData => todo!(), + DefaultFunction::SerialiseData => ExBudget { + mem: self.serialise_data.mem.cost(args[0].to_ex_mem()), + cpu: self.serialise_data.cpu.cost(args[0].to_ex_mem()), + }, DefaultFunction::MkPairData => ExBudget { mem: self .mk_pair_data diff --git a/crates/uplc/src/machine/error.rs b/crates/uplc/src/machine/error.rs index cd789dcb..93bc1b57 100644 --- a/crates/uplc/src/machine/error.rs +++ b/crates/uplc/src/machine/error.rs @@ -24,6 +24,8 @@ pub enum Error { TypeMismatch(Type, Type), #[error("Type mismatch expected '(list a)' got '{0}'")] ListTypeMismatch(Type), + #[error("Type mismatch expected '(pair a b)' got '{0}'")] + PairTypeMismatch(Type), #[error("Empty List:\n\n{0:#?}")] EmptyList(Value), #[error("A builtin received a term argument when something else was expected:\n\n{0}\n\nYou probably forgot to wrap the builtin with a force.")] diff --git a/crates/uplc/src/machine/runtime.rs b/crates/uplc/src/machine/runtime.rs index 3d59307a..afac6f39 100644 --- a/crates/uplc/src/machine/runtime.rs +++ b/crates/uplc/src/machine/runtime.rs @@ -6,6 +6,7 @@ use pallas_primitives::babbage::{BigInt, Constr, PlutusData}; use crate::{ ast::{Constant, Type}, builtins::DefaultFunction, + plutus_data_to_bytes, }; use super::{ @@ -108,9 +109,9 @@ impl DefaultFunction { DefaultFunction::IfThenElse => 3, DefaultFunction::ChooseUnit => 2, DefaultFunction::Trace => 2, - DefaultFunction::FstPair => todo!(), - DefaultFunction::SndPair => todo!(), - DefaultFunction::ChooseList => todo!(), + DefaultFunction::FstPair => 1, + DefaultFunction::SndPair => 1, + DefaultFunction::ChooseList => 3, DefaultFunction::MkCons => 2, DefaultFunction::HeadList => 1, DefaultFunction::TailList => 1, @@ -127,7 +128,7 @@ impl DefaultFunction { DefaultFunction::UnIData => 1, DefaultFunction::UnBData => 1, DefaultFunction::EqualsData => 2, - DefaultFunction::SerialiseData => todo!(), + DefaultFunction::SerialiseData => 1, DefaultFunction::MkPairData => 2, DefaultFunction::MkNilData => 1, DefaultFunction::MkNilPairData => 1, @@ -167,9 +168,9 @@ impl DefaultFunction { DefaultFunction::IfThenElse => 1, DefaultFunction::ChooseUnit => 1, DefaultFunction::Trace => 1, - DefaultFunction::FstPair => todo!(), - DefaultFunction::SndPair => todo!(), - DefaultFunction::ChooseList => todo!(), + DefaultFunction::FstPair => 2, + DefaultFunction::SndPair => 2, + DefaultFunction::ChooseList => 2, DefaultFunction::MkCons => 1, DefaultFunction::HeadList => 1, DefaultFunction::TailList => 1, @@ -186,7 +187,7 @@ impl DefaultFunction { DefaultFunction::UnIData => 0, DefaultFunction::UnBData => 0, DefaultFunction::EqualsData => 0, - DefaultFunction::SerialiseData => todo!(), + DefaultFunction::SerialiseData => 0, DefaultFunction::MkPairData => 0, DefaultFunction::MkNilData => 0, DefaultFunction::MkNilPairData => 0, @@ -262,9 +263,15 @@ impl DefaultFunction { Ok(()) } } - DefaultFunction::FstPair => todo!(), - DefaultFunction::SndPair => todo!(), - DefaultFunction::ChooseList => todo!(), + DefaultFunction::FstPair => arg.expect_pair(), + DefaultFunction::SndPair => arg.expect_pair(), + DefaultFunction::ChooseList => { + if args.is_empty() { + arg.expect_list() + } else { + Ok(()) + } + } DefaultFunction::MkCons => { if args.is_empty() { Ok(()) @@ -304,7 +311,7 @@ impl DefaultFunction { DefaultFunction::UnIData => arg.expect_type(Type::Data), DefaultFunction::UnBData => arg.expect_type(Type::Data), DefaultFunction::EqualsData => arg.expect_type(Type::Data), - DefaultFunction::SerialiseData => todo!(), + DefaultFunction::SerialiseData => arg.expect_type(Type::Data), DefaultFunction::MkPairData => arg.expect_type(Type::Data), DefaultFunction::MkNilData => arg.expect_type(Type::Unit), DefaultFunction::MkNilPairData => arg.expect_type(Type::Unit), @@ -598,9 +605,24 @@ impl DefaultFunction { } _ => unreachable!(), }, - DefaultFunction::FstPair => todo!(), - DefaultFunction::SndPair => todo!(), - DefaultFunction::ChooseList => todo!(), + DefaultFunction::FstPair => match &args[0] { + Value::Con(Constant::ProtoPair(_, _, first, _)) => Ok(Value::Con(*first.clone())), + _ => unreachable!(), + }, + DefaultFunction::SndPair => match &args[0] { + Value::Con(Constant::ProtoPair(_, _, _, second)) => Ok(Value::Con(*second.clone())), + _ => unreachable!(), + }, + DefaultFunction::ChooseList => match &args[0] { + Value::Con(Constant::ProtoList(_, list)) => { + if list.is_empty() { + Ok(args[1].clone()) + } else { + Ok(args[2].clone()) + } + } + _ => unreachable!(), + }, DefaultFunction::MkCons => match (&args[0], &args[1]) { (Value::Con(item), Value::Con(Constant::ProtoList(r#type, list))) => { let mut ret = vec![item.clone()]; @@ -793,7 +815,13 @@ impl DefaultFunction { } _ => unreachable!(), }, - DefaultFunction::SerialiseData => todo!(), + DefaultFunction::SerialiseData => match &args[0] { + Value::Con(Constant::Data(d)) => { + let serialized_data = plutus_data_to_bytes(d).unwrap(); + Ok(Value::Con(Constant::ByteString(serialized_data))) + } + _ => unreachable!(), + }, DefaultFunction::MkPairData => match (&args[0], &args[1]) { (Value::Con(Constant::Data(d1)), Value::Con(Constant::Data(d2))) => { Ok(Value::Con(Constant::ProtoPair(