feat: basic builtin execution
Co-authored-by: Kasey White <kwhitemsg@gmail.com>
This commit is contained in:
parent
9ea57aa461
commit
d55409d8c5
|
@ -0,0 +1,4 @@
|
||||||
|
(program
|
||||||
|
1.0.0
|
||||||
|
[ (builtin addInteger) (con integer 2) (con integer 3) ]
|
||||||
|
)
|
|
@ -10,6 +10,8 @@ mod runtime;
|
||||||
use cost_model::{ExBudget, MachineCosts, StepKind};
|
use cost_model::{ExBudget, MachineCosts, StepKind};
|
||||||
pub use error::Error;
|
pub use error::Error;
|
||||||
|
|
||||||
|
use self::runtime::BuiltinRuntime;
|
||||||
|
|
||||||
pub struct Machine {
|
pub struct Machine {
|
||||||
costs: MachineCosts,
|
costs: MachineCosts,
|
||||||
ex_budget: ExBudget,
|
ex_budget: ExBudget,
|
||||||
|
@ -89,9 +91,16 @@ impl Machine {
|
||||||
self.compute(body)
|
self.compute(body)
|
||||||
}
|
}
|
||||||
Term::Error => Err(Error::EvaluationFailure),
|
Term::Error => Err(Error::EvaluationFailure),
|
||||||
Term::Builtin(_bn) => {
|
Term::Builtin(fun) => {
|
||||||
self.step_and_maybe_spend(StepKind::Builtin)?;
|
self.step_and_maybe_spend(StepKind::Builtin)?;
|
||||||
todo!()
|
|
||||||
|
let runtime: BuiltinRuntime = (*fun).into();
|
||||||
|
|
||||||
|
self.return_compute(Value::Builtin {
|
||||||
|
fun: *fun,
|
||||||
|
term: term.clone(),
|
||||||
|
runtime,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -135,7 +144,7 @@ impl Machine {
|
||||||
fn discharge_value(&mut self, value: Value) -> Term<NamedDeBruijn> {
|
fn discharge_value(&mut self, value: Value) -> Term<NamedDeBruijn> {
|
||||||
match value {
|
match value {
|
||||||
Value::Con(x) => Term::Constant(x),
|
Value::Con(x) => Term::Constant(x),
|
||||||
Value::Builtin(_, t) => t,
|
Value::Builtin { term, .. } => term,
|
||||||
Value::Delay(body) => self.discharge_value_env(Term::Delay(Box::new(body))),
|
Value::Delay(body) => self.discharge_value_env(Term::Delay(Box::new(body))),
|
||||||
Value::Lambda {
|
Value::Lambda {
|
||||||
parameter_name,
|
parameter_name,
|
||||||
|
@ -187,7 +196,7 @@ impl Machine {
|
||||||
fn force_evaluate(&mut self, value: Value) -> Result<Term<NamedDeBruijn>, Error> {
|
fn force_evaluate(&mut self, value: Value) -> Result<Term<NamedDeBruijn>, Error> {
|
||||||
match value {
|
match value {
|
||||||
Value::Delay(body) => self.compute(&body),
|
Value::Delay(body) => self.compute(&body),
|
||||||
Value::Builtin(_, _) => todo!(),
|
Value::Builtin { .. } => todo!(),
|
||||||
rest => Err(Error::NonPolymorphicInstantiation(rest)),
|
rest => Err(Error::NonPolymorphicInstantiation(rest)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -204,11 +213,45 @@ impl Machine {
|
||||||
self.env.pop();
|
self.env.pop();
|
||||||
Ok(term)
|
Ok(term)
|
||||||
}
|
}
|
||||||
Value::Builtin(_, _) => todo!(),
|
Value::Builtin {
|
||||||
|
fun,
|
||||||
|
term,
|
||||||
|
mut runtime,
|
||||||
|
} => {
|
||||||
|
let arg_term = self.discharge_value(argument.clone());
|
||||||
|
|
||||||
|
let t = Term::<NamedDeBruijn>::Apply {
|
||||||
|
function: Box::new(term),
|
||||||
|
argument: Box::new(arg_term),
|
||||||
|
};
|
||||||
|
|
||||||
|
if runtime.is_arrow() {
|
||||||
|
runtime.push(argument)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let res = self.eval_builtin_app(fun, t, runtime)?;
|
||||||
|
|
||||||
|
self.return_compute(res)
|
||||||
|
}
|
||||||
rest => Err(Error::NonFunctionalApplication(rest)),
|
rest => Err(Error::NonFunctionalApplication(rest)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn eval_builtin_app(
|
||||||
|
&mut self,
|
||||||
|
fun: DefaultFunction,
|
||||||
|
term: Term<NamedDeBruijn>,
|
||||||
|
runtime: BuiltinRuntime,
|
||||||
|
) -> Result<Value, Error> {
|
||||||
|
if runtime.is_ready() {
|
||||||
|
self.spend_budget(ExBudget::default())?;
|
||||||
|
|
||||||
|
runtime.call()
|
||||||
|
} else {
|
||||||
|
Ok(Value::Builtin { fun, term, runtime })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn push_frame(&mut self, frame: Context) {
|
fn push_frame(&mut self, frame: Context) {
|
||||||
self.frames.push(frame);
|
self.frames.push(frame);
|
||||||
}
|
}
|
||||||
|
@ -280,10 +323,15 @@ pub enum Value {
|
||||||
parameter_name: NamedDeBruijn,
|
parameter_name: NamedDeBruijn,
|
||||||
body: Term<NamedDeBruijn>,
|
body: Term<NamedDeBruijn>,
|
||||||
},
|
},
|
||||||
Builtin(
|
Builtin {
|
||||||
DefaultFunction,
|
fun: DefaultFunction,
|
||||||
Term<NamedDeBruijn>,
|
term: Term<NamedDeBruijn>,
|
||||||
// Need to figure out run time stuff
|
runtime: BuiltinRuntime,
|
||||||
// BuiltinRuntime (CekValue uni fun)
|
},
|
||||||
),
|
}
|
||||||
|
|
||||||
|
impl Value {
|
||||||
|
pub fn is_integer(&self) -> bool {
|
||||||
|
matches!(self, Value::Con(Constant::Integer(_)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,44 +1,279 @@
|
||||||
use super::cost_model::{CostingFun, ExBudget};
|
use crate::{ast::Constant, builtins::DefaultFunction};
|
||||||
|
|
||||||
enum RuntimeScheme {
|
use super::{
|
||||||
RuntimeSchemeResult,
|
// cost_model::{CostingFun, ExBudget},
|
||||||
RuntimeSchemeArrow(usize),
|
Error,
|
||||||
RuntimeSchemeAll(usize),
|
Value,
|
||||||
|
};
|
||||||
|
|
||||||
|
//#[derive(std::cmp::PartialEq)]
|
||||||
|
//pub enum EvalMode {
|
||||||
|
// Immediate,
|
||||||
|
// Deferred,
|
||||||
|
//}
|
||||||
|
|
||||||
|
// pub struct BuiltinRuntimeOptions<T, G> {
|
||||||
|
// immediate_eval: T,
|
||||||
|
// deferred_eval: T,
|
||||||
|
// budget: fn(CostingFun<G>) -> fn(Vec<u32>) -> ExBudget,
|
||||||
|
// }
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct BuiltinRuntime {
|
||||||
|
meaning: BuiltinMeaning,
|
||||||
|
// budget: fn(Vec<u32>) -> ExBudget,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(std::cmp::PartialEq)]
|
#[derive(Clone, Debug)]
|
||||||
enum EvalMode {
|
struct BuiltinMeaning {
|
||||||
Immediate,
|
args: Vec<Value>,
|
||||||
Deferred,
|
fun: DefaultFunction,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct BuiltinRuntimeOptions<T, G> {
|
impl BuiltinMeaning {
|
||||||
runtime_scheme: Vec<RuntimeScheme>,
|
pub fn new(fun: DefaultFunction) -> BuiltinMeaning {
|
||||||
immediate_eval: T,
|
Self { args: vec![], fun }
|
||||||
deferred_eval: T,
|
}
|
||||||
budget: fn(CostingFun<G>) -> fn(Vec<u32>) -> ExBudget,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct BuiltinRuntime<T> {
|
impl BuiltinRuntime {
|
||||||
runtime_scheme: Vec<RuntimeScheme>,
|
// fn from_builtin_runtime_options<G>(
|
||||||
runtime_denotation: T,
|
// eval_mode: EvalMode,
|
||||||
budget: fn(Vec<u32>) -> ExBudget,
|
// cost: CostingFun<G>,
|
||||||
|
// runtime_options: BuiltinRuntimeOptions<T, G>,
|
||||||
|
// ) -> BuiltinRuntime {
|
||||||
|
// Self {
|
||||||
|
// budget: (runtime_options.budget)(cost),
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
pub fn is_arrow(&self) -> bool {
|
||||||
|
self.meaning.args.len() != self.meaning.fun.arity()
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> BuiltinRuntime<T> {
|
pub fn is_ready(&self) -> bool {
|
||||||
fn from_builtin_runtime_options<G>(
|
self.meaning.args.len() == self.meaning.fun.arity()
|
||||||
eval_mode: EvalMode,
|
}
|
||||||
cost: CostingFun<G>,
|
|
||||||
runtime_options: BuiltinRuntimeOptions<T, G>,
|
pub fn call(&self) -> Result<Value, Error> {
|
||||||
) -> BuiltinRuntime<T> {
|
self.meaning.fun.call(&self.meaning.args)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push(&mut self, arg: Value) -> Result<(), Error> {
|
||||||
|
self.meaning.fun.check_type(&arg)?;
|
||||||
|
|
||||||
|
self.meaning.args.push(arg);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<DefaultFunction> for BuiltinMeaning {
|
||||||
|
fn from(fun: DefaultFunction) -> Self {
|
||||||
|
BuiltinMeaning::new(fun)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<DefaultFunction> for BuiltinRuntime {
|
||||||
|
fn from(fun: DefaultFunction) -> Self {
|
||||||
BuiltinRuntime {
|
BuiltinRuntime {
|
||||||
runtime_scheme: runtime_options.runtime_scheme,
|
meaning: fun.into(),
|
||||||
runtime_denotation: if eval_mode == EvalMode::Immediate {
|
}
|
||||||
runtime_options.immediate_eval
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DefaultFunction {
|
||||||
|
pub fn arity(&self) -> usize {
|
||||||
|
match self {
|
||||||
|
DefaultFunction::AddInteger => 2,
|
||||||
|
DefaultFunction::SubtractInteger => todo!(),
|
||||||
|
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 => todo!(),
|
||||||
|
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 check_type(&self, arg: &Value) -> Result<(), Error> {
|
||||||
|
match self {
|
||||||
|
DefaultFunction::AddInteger => {
|
||||||
|
if arg.is_integer() {
|
||||||
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
runtime_options.deferred_eval
|
todo!("type error")
|
||||||
},
|
}
|
||||||
budget: (runtime_options.budget)(cost),
|
}
|
||||||
|
DefaultFunction::SubtractInteger => todo!(),
|
||||||
|
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 => todo!(),
|
||||||
|
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 call(&self, args: &[Value]) -> Result<Value, Error> {
|
||||||
|
match self {
|
||||||
|
DefaultFunction::AddInteger => {
|
||||||
|
assert_eq!(args.len(), self.arity());
|
||||||
|
|
||||||
|
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)))
|
||||||
|
}
|
||||||
|
_ => todo!("handle error"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DefaultFunction::SubtractInteger => todo!(),
|
||||||
|
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 => todo!(),
|
||||||
|
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!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue