diff --git a/add.uplc b/add.uplc deleted file mode 100644 index 71065f37..00000000 --- a/add.uplc +++ /dev/null @@ -1,4 +0,0 @@ -(program - 1.0.0 - (lam x [ [ (builtin addInteger) (con integer 1) ] x ]) -) \ No newline at end of file diff --git a/crates/uplc/src/machine.rs b/crates/uplc/src/machine.rs index aa54f915..26e40477 100644 --- a/crates/uplc/src/machine.rs +++ b/crates/uplc/src/machine.rs @@ -22,13 +22,13 @@ use self::{ enum MachineState { Return(Context, Value), Compute(Context, Env, Term), - Done(Rc>), + Done(Term), } #[derive(Clone)] enum Context { FrameApplyFun(Value, Box), - FrameApplyArg(Env, Rc>, Box), + FrameApplyArg(Env, Term, Box), FrameForce(Box), NoFrame, } @@ -73,7 +73,7 @@ impl Machine { Compute(context, env, t) => self.compute(context, env, t)?, Return(context, value) => self.return_compute(context, value)?, Done(t) => { - return Ok(t.as_ref().clone()); + return Ok(t); } }; } @@ -117,7 +117,7 @@ impl Machine { self.step_and_maybe_spend(StepKind::Apply)?; Ok(MachineState::Compute( - Context::FrameApplyArg(Rc::clone(&env), argument, context.into()), + Context::FrameApplyArg(env.clone(), argument.as_ref().clone(), context.into()), env, function.as_ref().clone(), )) @@ -156,7 +156,7 @@ impl Machine { Context::FrameApplyArg(arg_var_env, arg, ctx) => Ok(MachineState::Compute( Context::FrameApplyFun(value, ctx), arg_var_env, - arg.as_ref().clone(), + arg, )), Context::FrameForce(ctx) => self.force_evaluate(*ctx, value), Context::NoFrame => { @@ -188,9 +188,9 @@ impl Machine { Ok(MachineState::Return(context, res)) } else { - Err(Error::BuiltinTermArgumentExpected(Term::Constant( - Constant::Unit.into(), - ))) + let term = discharge::value_as_term(Value::Builtin { fun, runtime }); + + Err(Error::BuiltinTermArgumentExpected(term)) } } rest => Err(Error::NonPolymorphicInstantiation(rest)), @@ -216,8 +216,6 @@ impl Machine { )) } Value::Builtin { fun, runtime } => { - // let arg_term = discharge::value_as_term(argument.clone()); - if runtime.is_arrow() && !runtime.needs_force() { let mut runtime = runtime; @@ -231,9 +229,9 @@ impl Machine { Ok(MachineState::Return(context, res)) } else { - Err(Error::UnexpectedBuiltinTermArgument(Term::Constant( - Constant::Unit.into(), - ))) + let term = discharge::value_as_term(Value::Builtin { fun, runtime }); + + Err(Error::UnexpectedBuiltinTermArgument(term)) } } rest => Err(Error::NonFunctionalApplication(rest, argument)), diff --git a/crates/uplc/src/machine/discharge.rs b/crates/uplc/src/machine/discharge.rs index 335de7a6..9981b002 100644 --- a/crates/uplc/src/machine/discharge.rs +++ b/crates/uplc/src/machine/discharge.rs @@ -1,6 +1,6 @@ use std::rc::Rc; -use crate::ast::{Constant, NamedDeBruijn, Term}; +use crate::ast::{NamedDeBruijn, Term}; use super::value::{Env, Value}; @@ -19,7 +19,7 @@ enum DischargeStep { PopArgStack(PartialTerm), } -pub(super) fn value_as_term(value: Value) -> Rc> { +pub(super) fn value_as_term(value: Value) -> Term { let mut stack = vec![DischargeStep::DischargeValue(value)]; let mut arg_stack = vec![]; @@ -27,9 +27,18 @@ pub(super) fn value_as_term(value: Value) -> Rc> { while let Some(stack_frame) = stack.pop() { match stack_frame { DischargeStep::DischargeValue(value) => match value { - Value::Con(x) => arg_stack.push(Term::Constant(x.clone()).into()), - Value::Builtin { .. } => { - arg_stack.push(Term::Constant(Constant::Unit.into()).into()) + Value::Con(x) => arg_stack.push(Term::Constant(x.clone())), + Value::Builtin { runtime, fun } => { + let mut term = Term::Builtin(fun); + + for _ in 0..runtime.forces { + term = term.force(); + } + + for arg in runtime.args { + term = term.apply(value_as_term(arg)); + } + arg_stack.push(term) } Value::Delay(body, env) => { stack.push(DischargeStep::DischargeValueEnv( @@ -59,14 +68,14 @@ pub(super) fn value_as_term(value: Value) -> Rc> { let index: usize = name.index.into(); if lam_cnt >= index { - arg_stack.push(Rc::new(Term::Var(name.clone()))); + arg_stack.push(Term::Var(name.clone())); } else { let env = env.get::(env.len() - (index - lam_cnt)).cloned(); if let Some(v) = env { stack.push(DischargeStep::DischargeValue(v)); } else { - arg_stack.push(Rc::new(Term::Var(name.clone()))); + arg_stack.push(Term::Var(name.clone())); } } } @@ -114,33 +123,33 @@ pub(super) fn value_as_term(value: Value) -> Rc> { )); } rest => { - arg_stack.push(rest.to_owned().into()); + arg_stack.push(rest.to_owned()); } }, DischargeStep::PopArgStack(term) => match term { PartialTerm::Delay => { let body = arg_stack.pop().unwrap(); - arg_stack.push(Term::Delay(body).into()) + + arg_stack.push(Term::Delay(body.into())) } PartialTerm::Lambda(parameter_name) => { let body = arg_stack.pop().unwrap(); - arg_stack.push( - Term::Lambda { - parameter_name, - body, - } - .into(), - ) + + arg_stack.push(Term::Lambda { + parameter_name, + body: body.into(), + }) } PartialTerm::Apply => { let argument = arg_stack.pop().unwrap(); let function = arg_stack.pop().unwrap(); - arg_stack.push(Term::Apply { function, argument }.into()); + arg_stack.push(function.apply(argument)); } PartialTerm::Force => { let body = arg_stack.pop().unwrap(); - arg_stack.push(Term::Force(body).into()) + + arg_stack.push(body.force()) } }, } diff --git a/crates/uplc/src/machine/runtime.rs b/crates/uplc/src/machine/runtime.rs index 9137a33d..91b9594e 100644 --- a/crates/uplc/src/machine/runtime.rs +++ b/crates/uplc/src/machine/runtime.rs @@ -23,9 +23,9 @@ use super::{ #[derive(Clone, Debug)] pub struct BuiltinRuntime { - args: Vec, + pub(super) args: Vec, fun: DefaultFunction, - forces: u32, + pub(super) forces: u32, } impl BuiltinRuntime {