From 598c5364fe5cbdc195383e00870c312b8ce74a98 Mon Sep 17 00:00:00 2001 From: Kasey White Date: Fri, 15 Jul 2022 20:43:22 -0400 Subject: [PATCH] implement force for builtins Co-authored-by: rvcas --- crates/uplc/src/machine.rs | 47 +++++++++++++++---- crates/uplc/src/machine/runtime.rs | 74 ++++++++++++++++++++++++++++-- 2 files changed, 106 insertions(+), 15 deletions(-) diff --git a/crates/uplc/src/machine.rs b/crates/uplc/src/machine.rs index 20e6b908..4a262b8b 100644 --- a/crates/uplc/src/machine.rs +++ b/crates/uplc/src/machine.rs @@ -193,12 +193,22 @@ impl Machine { fn force_evaluate(&mut self, value: Value) -> Result, Error> { match value { Value::Delay(body) => self.compute(&body), - Value::Builtin { fun, term, runtime } => { + Value::Builtin { + fun, + term, + mut runtime, + } => { let force_term = Term::Force(Box::new(dbg!(term))); - if runtime.is_all() {} - println!("{:#?}", runtime); - todo!() + if runtime.needs_force() { + runtime.consume_force(); + + let res = self.eval_builtin_app(fun, force_term, runtime)?; + + self.return_compute(res) + } else { + todo!() + } } rest => Err(Error::NonPolymorphicInstantiation(rest)), } @@ -228,13 +238,15 @@ impl Machine { argument: Box::new(arg_term), }; - if runtime.is_arrow() { + if runtime.is_arrow() && !runtime.needs_force() { runtime.push(argument)?; + + let res = self.eval_builtin_app(fun, t, runtime)?; + + self.return_compute(res) + } else { + todo!() } - - let res = self.eval_builtin_app(fun, t, runtime)?; - - self.return_compute(res) } rest => Err(Error::NonFunctionalApplication(rest)), } @@ -348,7 +360,22 @@ impl Value { pub fn to_ex_mem(&self) -> i64 { match self { // TODO: this is not 1 - Value::Con(_) => 1, + Value::Con(c) => match c { + Constant::Integer(i) => { + if *i == 0 { + 1 + } else { + //TODO + // std::mem::size_of( i.abs() + todo!() + } + } + Constant::ByteString(b) => (((b.len() - 1) / 8) + 1) as i64, + Constant::String(s) => s.chars().count() as i64, + Constant::Char(_) => 1, + Constant::Unit => 1, + Constant::Bool(_) => 1, + }, Value::Delay(_) => 1, Value::Lambda { .. } => 1, Value::Builtin { .. } => 1, diff --git a/crates/uplc/src/machine/runtime.rs b/crates/uplc/src/machine/runtime.rs index 93b70628..e3d0d779 100644 --- a/crates/uplc/src/machine/runtime.rs +++ b/crates/uplc/src/machine/runtime.rs @@ -23,11 +23,16 @@ use super::{ pub struct BuiltinRuntime { args: Vec, fun: DefaultFunction, + forces: u32, } impl BuiltinRuntime { pub fn new(fun: DefaultFunction) -> BuiltinRuntime { - Self { args: vec![], fun } + Self { + args: vec![], + fun, + forces: 0, + } } // fn from_builtin_runtime_options( @@ -48,8 +53,12 @@ impl BuiltinRuntime { self.args.len() == self.fun.arity() } - pub fn is_all(&self) -> bool { - self.args.is_empty() + pub fn needs_force(&self) -> bool { + self.forces < self.fun.force_count() + } + + pub fn consume_force(&mut self) { + self.forces += 1; } pub fn call(&self) -> Result { @@ -135,8 +144,63 @@ impl DefaultFunction { } } - pub fn force_count() -> i32 { - 3 + pub fn force_count(&self) -> u32 { + match self { + DefaultFunction::AddInteger => 0, + DefaultFunction::SubtractInteger => 0, + DefaultFunction::MultiplyInteger => todo!(), + DefaultFunction::DivideInteger => todo!(), + DefaultFunction::QuotientInteger => todo!(), + DefaultFunction::RemainderInteger => todo!(), + DefaultFunction::ModInteger => todo!(), + DefaultFunction::EqualsInteger => todo!(), + DefaultFunction::LessThanInteger => todo!(), + DefaultFunction::LessThanEqualsInteger => todo!(), + DefaultFunction::AppendByteString => todo!(), + DefaultFunction::ConsByteString => todo!(), + DefaultFunction::SliceByteString => todo!(), + DefaultFunction::LengthOfByteString => todo!(), + DefaultFunction::IndexByteString => todo!(), + DefaultFunction::EqualsByteString => todo!(), + DefaultFunction::LessThanByteString => todo!(), + DefaultFunction::LessThanEqualsByteString => todo!(), + DefaultFunction::Sha2_256 => todo!(), + DefaultFunction::Sha3_256 => todo!(), + DefaultFunction::Blake2b_256 => todo!(), + DefaultFunction::VerifySignature => todo!(), + DefaultFunction::VerifyEcdsaSecp256k1Signature => todo!(), + DefaultFunction::VerifySchnorrSecp256k1Signature => todo!(), + DefaultFunction::AppendString => todo!(), + DefaultFunction::EqualsString => todo!(), + DefaultFunction::EncodeUtf8 => todo!(), + DefaultFunction::DecodeUtf8 => todo!(), + DefaultFunction::IfThenElse => 1, + DefaultFunction::ChooseUnit => 1, + DefaultFunction::Trace => todo!(), + DefaultFunction::FstPair => todo!(), + DefaultFunction::SndPair => todo!(), + DefaultFunction::ChooseList => todo!(), + DefaultFunction::MkCons => todo!(), + DefaultFunction::HeadList => todo!(), + DefaultFunction::TailList => todo!(), + DefaultFunction::NullList => todo!(), + DefaultFunction::ChooseData => todo!(), + DefaultFunction::ConstrData => todo!(), + DefaultFunction::MapData => todo!(), + DefaultFunction::ListData => todo!(), + DefaultFunction::IData => todo!(), + DefaultFunction::BData => todo!(), + DefaultFunction::UnConstrData => todo!(), + DefaultFunction::UnMapData => todo!(), + DefaultFunction::UnListData => todo!(), + DefaultFunction::UnIData => todo!(), + DefaultFunction::UnBData => todo!(), + DefaultFunction::EqualsData => todo!(), + DefaultFunction::SerialiseData => todo!(), + DefaultFunction::MkPairData => todo!(), + DefaultFunction::MkNilData => todo!(), + DefaultFunction::MkNilPairData => todo!(), + } } pub fn check_type(&self, arg: &Value, args: &[Value]) -> Result<(), Error> {