aiken/crates/uplc/src/machine/runtime.rs

352 lines
15 KiB
Rust

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<Value>,
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<Value, Error> {
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<DefaultFunction> 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<Value, Error> {
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!(),
}
}
}