use crate::{ast::Constant, builtins::DefaultFunction}; use super::{ cost_model::{BuiltinCosts, ExBudget}, error::Type, Error, Value, }; //#[derive(std::cmp::PartialEq)] //pub enum EvalMode { // Immediate, // Deferred, //} #[derive(Clone, Debug)] pub struct BuiltinRuntime { args: Vec, fun: DefaultFunction, forces: u32, } impl BuiltinRuntime { pub fn new(fun: DefaultFunction) -> BuiltinRuntime { Self { args: vec![], fun, forces: 0, } } pub fn is_arrow(&self) -> bool { self.args.len() != self.fun.arity() } pub fn is_ready(&self) -> bool { self.args.len() == self.fun.arity() } 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 { self.fun.call(&self.args) } pub fn push(&mut self, arg: Value) -> Result<(), Error> { self.fun.check_type(&arg, &self.args)?; self.args.push(arg); Ok(()) } pub fn to_ex_budget(&self, costs: &BuiltinCosts) -> ExBudget { costs.to_ex_budget(self.fun, &self.args) } } impl From for BuiltinRuntime { fn from(fun: DefaultFunction) -> Self { BuiltinRuntime::new(fun) } } impl DefaultFunction { pub fn arity(&self) -> usize { match self { DefaultFunction::AddInteger => 2, DefaultFunction::SubtractInteger => 2, DefaultFunction::MultiplyInteger => todo!(), DefaultFunction::DivideInteger => todo!(), DefaultFunction::QuotientInteger => todo!(), DefaultFunction::RemainderInteger => todo!(), DefaultFunction::ModInteger => todo!(), DefaultFunction::EqualsInteger => todo!(), DefaultFunction::LessThanInteger => todo!(), DefaultFunction::LessThanEqualsInteger => 2, 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 => 3, DefaultFunction::ChooseUnit => todo!(), 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 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 => 0, 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> { match self { DefaultFunction::AddInteger => arg.expect_type(Type::Integer), DefaultFunction::SubtractInteger => arg.expect_type(Type::Integer), DefaultFunction::MultiplyInteger => todo!(), DefaultFunction::DivideInteger => todo!(), DefaultFunction::QuotientInteger => todo!(), DefaultFunction::RemainderInteger => todo!(), DefaultFunction::ModInteger => todo!(), DefaultFunction::EqualsInteger => todo!(), DefaultFunction::LessThanInteger => todo!(), DefaultFunction::LessThanEqualsInteger => arg.expect_type(Type::Integer), 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 => { if args.is_empty() && !arg.is_bool() { arg.expect_type(Type::Bool) } else { Ok(()) } } DefaultFunction::ChooseUnit => todo!(), 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!(), } } // This should be safe because we've already checked // the types of the args as they were pushed. Although // the unreachables look ugly, it's the reality of the situation. pub fn call(&self, args: &[Value]) -> Result { match self { DefaultFunction::AddInteger => { let args = (&args[0], &args[1]); match args { (Value::Con(Constant::Integer(arg1)), Value::Con(Constant::Integer(arg2))) => { Ok(Value::Con(Constant::Integer(arg1 + arg2))) } _ => unreachable!(), } } DefaultFunction::SubtractInteger => { let args = (&args[0], &args[1]); match args { (Value::Con(Constant::Integer(arg1)), Value::Con(Constant::Integer(arg2))) => { Ok(Value::Con(Constant::Integer(arg1 - arg2))) } _ => unreachable!(), } } DefaultFunction::MultiplyInteger => todo!(), DefaultFunction::DivideInteger => todo!(), DefaultFunction::QuotientInteger => todo!(), DefaultFunction::RemainderInteger => todo!(), DefaultFunction::ModInteger => todo!(), DefaultFunction::EqualsInteger => todo!(), DefaultFunction::LessThanInteger => todo!(), DefaultFunction::LessThanEqualsInteger => { let args = (&args[0], &args[1]); match args { (Value::Con(Constant::Integer(arg1)), Value::Con(Constant::Integer(arg2))) => { Ok(Value::Con(Constant::Bool(arg1 <= arg2))) } _ => unreachable!(), } } 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 => match args[0] { Value::Con(Constant::Bool(condition)) => { if condition { Ok(args[1].clone()) } else { Ok(args[2].clone()) } } _ => unreachable!(), }, DefaultFunction::ChooseUnit => todo!(), 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!(), } } }