feat
* remove more Rc's * reconstruct Value::Builtin only when needed Co-authored-by: Lucas Rosa <x@rvcas.dev>
This commit is contained in:
parent
09a6ea51d6
commit
564939ab61
4
add.uplc
4
add.uplc
|
@ -1,4 +0,0 @@
|
||||||
(program
|
|
||||||
1.0.0
|
|
||||||
(lam x [ [ (builtin addInteger) (con integer 1) ] x ])
|
|
||||||
)
|
|
|
@ -22,13 +22,13 @@ use self::{
|
||||||
enum MachineState {
|
enum MachineState {
|
||||||
Return(Context, Value),
|
Return(Context, Value),
|
||||||
Compute(Context, Env, Term<NamedDeBruijn>),
|
Compute(Context, Env, Term<NamedDeBruijn>),
|
||||||
Done(Rc<Term<NamedDeBruijn>>),
|
Done(Term<NamedDeBruijn>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
enum Context {
|
enum Context {
|
||||||
FrameApplyFun(Value, Box<Context>),
|
FrameApplyFun(Value, Box<Context>),
|
||||||
FrameApplyArg(Env, Rc<Term<NamedDeBruijn>>, Box<Context>),
|
FrameApplyArg(Env, Term<NamedDeBruijn>, Box<Context>),
|
||||||
FrameForce(Box<Context>),
|
FrameForce(Box<Context>),
|
||||||
NoFrame,
|
NoFrame,
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,7 @@ impl Machine {
|
||||||
Compute(context, env, t) => self.compute(context, env, t)?,
|
Compute(context, env, t) => self.compute(context, env, t)?,
|
||||||
Return(context, value) => self.return_compute(context, value)?,
|
Return(context, value) => self.return_compute(context, value)?,
|
||||||
Done(t) => {
|
Done(t) => {
|
||||||
return Ok(t.as_ref().clone());
|
return Ok(t);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -117,7 +117,7 @@ impl Machine {
|
||||||
self.step_and_maybe_spend(StepKind::Apply)?;
|
self.step_and_maybe_spend(StepKind::Apply)?;
|
||||||
|
|
||||||
Ok(MachineState::Compute(
|
Ok(MachineState::Compute(
|
||||||
Context::FrameApplyArg(Rc::clone(&env), argument, context.into()),
|
Context::FrameApplyArg(env.clone(), argument.as_ref().clone(), context.into()),
|
||||||
env,
|
env,
|
||||||
function.as_ref().clone(),
|
function.as_ref().clone(),
|
||||||
))
|
))
|
||||||
|
@ -156,7 +156,7 @@ impl Machine {
|
||||||
Context::FrameApplyArg(arg_var_env, arg, ctx) => Ok(MachineState::Compute(
|
Context::FrameApplyArg(arg_var_env, arg, ctx) => Ok(MachineState::Compute(
|
||||||
Context::FrameApplyFun(value, ctx),
|
Context::FrameApplyFun(value, ctx),
|
||||||
arg_var_env,
|
arg_var_env,
|
||||||
arg.as_ref().clone(),
|
arg,
|
||||||
)),
|
)),
|
||||||
Context::FrameForce(ctx) => self.force_evaluate(*ctx, value),
|
Context::FrameForce(ctx) => self.force_evaluate(*ctx, value),
|
||||||
Context::NoFrame => {
|
Context::NoFrame => {
|
||||||
|
@ -188,9 +188,9 @@ impl Machine {
|
||||||
|
|
||||||
Ok(MachineState::Return(context, res))
|
Ok(MachineState::Return(context, res))
|
||||||
} else {
|
} else {
|
||||||
Err(Error::BuiltinTermArgumentExpected(Term::Constant(
|
let term = discharge::value_as_term(Value::Builtin { fun, runtime });
|
||||||
Constant::Unit.into(),
|
|
||||||
)))
|
Err(Error::BuiltinTermArgumentExpected(term))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rest => Err(Error::NonPolymorphicInstantiation(rest)),
|
rest => Err(Error::NonPolymorphicInstantiation(rest)),
|
||||||
|
@ -216,8 +216,6 @@ impl Machine {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
Value::Builtin { fun, runtime } => {
|
Value::Builtin { fun, runtime } => {
|
||||||
// let arg_term = discharge::value_as_term(argument.clone());
|
|
||||||
|
|
||||||
if runtime.is_arrow() && !runtime.needs_force() {
|
if runtime.is_arrow() && !runtime.needs_force() {
|
||||||
let mut runtime = runtime;
|
let mut runtime = runtime;
|
||||||
|
|
||||||
|
@ -231,9 +229,9 @@ impl Machine {
|
||||||
|
|
||||||
Ok(MachineState::Return(context, res))
|
Ok(MachineState::Return(context, res))
|
||||||
} else {
|
} else {
|
||||||
Err(Error::UnexpectedBuiltinTermArgument(Term::Constant(
|
let term = discharge::value_as_term(Value::Builtin { fun, runtime });
|
||||||
Constant::Unit.into(),
|
|
||||||
)))
|
Err(Error::UnexpectedBuiltinTermArgument(term))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rest => Err(Error::NonFunctionalApplication(rest, argument)),
|
rest => Err(Error::NonFunctionalApplication(rest, argument)),
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use crate::ast::{Constant, NamedDeBruijn, Term};
|
use crate::ast::{NamedDeBruijn, Term};
|
||||||
|
|
||||||
use super::value::{Env, Value};
|
use super::value::{Env, Value};
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ enum DischargeStep {
|
||||||
PopArgStack(PartialTerm),
|
PopArgStack(PartialTerm),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn value_as_term(value: Value) -> Rc<Term<NamedDeBruijn>> {
|
pub(super) fn value_as_term(value: Value) -> Term<NamedDeBruijn> {
|
||||||
let mut stack = vec![DischargeStep::DischargeValue(value)];
|
let mut stack = vec![DischargeStep::DischargeValue(value)];
|
||||||
|
|
||||||
let mut arg_stack = vec![];
|
let mut arg_stack = vec![];
|
||||||
|
@ -27,9 +27,18 @@ pub(super) fn value_as_term(value: Value) -> Rc<Term<NamedDeBruijn>> {
|
||||||
while let Some(stack_frame) = stack.pop() {
|
while let Some(stack_frame) = stack.pop() {
|
||||||
match stack_frame {
|
match stack_frame {
|
||||||
DischargeStep::DischargeValue(value) => match value {
|
DischargeStep::DischargeValue(value) => match value {
|
||||||
Value::Con(x) => arg_stack.push(Term::Constant(x.clone()).into()),
|
Value::Con(x) => arg_stack.push(Term::Constant(x.clone())),
|
||||||
Value::Builtin { .. } => {
|
Value::Builtin { runtime, fun } => {
|
||||||
arg_stack.push(Term::Constant(Constant::Unit.into()).into())
|
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) => {
|
Value::Delay(body, env) => {
|
||||||
stack.push(DischargeStep::DischargeValueEnv(
|
stack.push(DischargeStep::DischargeValueEnv(
|
||||||
|
@ -59,14 +68,14 @@ pub(super) fn value_as_term(value: Value) -> Rc<Term<NamedDeBruijn>> {
|
||||||
let index: usize = name.index.into();
|
let index: usize = name.index.into();
|
||||||
|
|
||||||
if lam_cnt >= index {
|
if lam_cnt >= index {
|
||||||
arg_stack.push(Rc::new(Term::Var(name.clone())));
|
arg_stack.push(Term::Var(name.clone()));
|
||||||
} else {
|
} else {
|
||||||
let env = env.get::<usize>(env.len() - (index - lam_cnt)).cloned();
|
let env = env.get::<usize>(env.len() - (index - lam_cnt)).cloned();
|
||||||
|
|
||||||
if let Some(v) = env {
|
if let Some(v) = env {
|
||||||
stack.push(DischargeStep::DischargeValue(v));
|
stack.push(DischargeStep::DischargeValue(v));
|
||||||
} else {
|
} 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<Term<NamedDeBruijn>> {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
rest => {
|
rest => {
|
||||||
arg_stack.push(rest.to_owned().into());
|
arg_stack.push(rest.to_owned());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
DischargeStep::PopArgStack(term) => match term {
|
DischargeStep::PopArgStack(term) => match term {
|
||||||
PartialTerm::Delay => {
|
PartialTerm::Delay => {
|
||||||
let body = arg_stack.pop().unwrap();
|
let body = arg_stack.pop().unwrap();
|
||||||
arg_stack.push(Term::Delay(body).into())
|
|
||||||
|
arg_stack.push(Term::Delay(body.into()))
|
||||||
}
|
}
|
||||||
PartialTerm::Lambda(parameter_name) => {
|
PartialTerm::Lambda(parameter_name) => {
|
||||||
let body = arg_stack.pop().unwrap();
|
let body = arg_stack.pop().unwrap();
|
||||||
arg_stack.push(
|
|
||||||
Term::Lambda {
|
arg_stack.push(Term::Lambda {
|
||||||
parameter_name,
|
parameter_name,
|
||||||
body,
|
body: body.into(),
|
||||||
}
|
})
|
||||||
.into(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
PartialTerm::Apply => {
|
PartialTerm::Apply => {
|
||||||
let argument = arg_stack.pop().unwrap();
|
let argument = arg_stack.pop().unwrap();
|
||||||
let function = 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 => {
|
PartialTerm::Force => {
|
||||||
let body = arg_stack.pop().unwrap();
|
let body = arg_stack.pop().unwrap();
|
||||||
arg_stack.push(Term::Force(body).into())
|
|
||||||
|
arg_stack.push(body.force())
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,9 +23,9 @@ use super::{
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct BuiltinRuntime {
|
pub struct BuiltinRuntime {
|
||||||
args: Vec<Value>,
|
pub(super) args: Vec<Value>,
|
||||||
fun: DefaultFunction,
|
fun: DefaultFunction,
|
||||||
forces: u32,
|
pub(super) forces: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BuiltinRuntime {
|
impl BuiltinRuntime {
|
||||||
|
|
Loading…
Reference in New Issue