Using rc we now get code that runs much faster and

can run jpg contract with no inputs
This commit is contained in:
Kasey White 2022-08-17 05:21:40 -04:00 committed by Lucas
parent fb81955f51
commit 2bb482d9ec
11 changed files with 219 additions and 190 deletions

View File

@ -1,4 +1,4 @@
use std::fmt::Display;
use std::{fmt::Display, rc::Rc};
use pallas_primitives::alonzo::PlutusData;
@ -30,8 +30,8 @@ where
/// even necessary (i.e. minting policy).
pub fn apply(&self, program: &Self) -> Self {
let applied_term = Term::Apply {
function: Box::new(self.term.clone()),
argument: Box::new(program.term.clone()),
function: Rc::new(self.term.clone()),
argument: Rc::new(program.term.clone()),
};
Program {
@ -60,21 +60,21 @@ pub enum Term<T> {
// tag: 0
Var(T),
// tag: 1
Delay(Box<Term<T>>),
Delay(Rc<Term<T>>),
// tag: 2
Lambda {
parameter_name: T,
body: Box<Term<T>>,
body: Rc<Term<T>>,
},
// tag: 3
Apply {
function: Box<Term<T>>,
argument: Box<Term<T>>,
function: Rc<Term<T>>,
argument: Rc<Term<T>>,
},
// tag: 4
Constant(Constant),
// tag: 5
Force(Box<Term<T>>),
Force(Rc<Term<T>>),
// tag: 6
Error,
// tag: 7
@ -306,7 +306,7 @@ impl TryFrom<Term<Name>> for Term<NamedDeBruijn> {
fn try_from(value: Term<Name>) -> Result<Self, debruijn::Error> {
let mut converter = Converter::new();
let term = converter.name_to_named_debruijn(value)?;
let term = converter.name_to_named_debruijn(&value)?;
Ok(term)
}
@ -333,7 +333,7 @@ impl TryFrom<Term<Name>> for Term<DeBruijn> {
fn try_from(value: Term<Name>) -> Result<Self, debruijn::Error> {
let mut converter = Converter::new();
let term = converter.name_to_debruijn(value)?;
let term = converter.name_to_debruijn(&value)?;
Ok(term)
}
@ -356,7 +356,7 @@ impl TryFrom<Term<NamedDeBruijn>> for Term<Name> {
fn try_from(value: Term<NamedDeBruijn>) -> Result<Self, debruijn::Error> {
let mut converter = Converter::new();
let term = converter.named_debruijn_to_name(value)?;
let term = converter.named_debruijn_to_name(&value)?;
Ok(term)
}
@ -375,7 +375,7 @@ impl From<Term<NamedDeBruijn>> for Term<DeBruijn> {
fn from(value: Term<NamedDeBruijn>) -> Self {
let mut converter = Converter::new();
converter.named_debruijn_to_debruijn(value)
converter.named_debruijn_to_debruijn(&value)
}
}
@ -392,7 +392,7 @@ impl From<Term<NamedDeBruijn>> for Term<FakeNamedDeBruijn> {
fn from(value: Term<NamedDeBruijn>) -> Self {
let mut converter = Converter::new();
converter.named_debruijn_to_fake_named_debruijn(value)
converter.named_debruijn_to_fake_named_debruijn(&value)
}
}
@ -413,7 +413,7 @@ impl TryFrom<Term<DeBruijn>> for Term<Name> {
fn try_from(value: Term<DeBruijn>) -> Result<Self, debruijn::Error> {
let mut converter = Converter::new();
let term = converter.debruijn_to_name(value)?;
let term = converter.debruijn_to_name(&value)?;
Ok(term)
}
@ -432,7 +432,7 @@ impl From<Term<DeBruijn>> for Term<NamedDeBruijn> {
fn from(value: Term<DeBruijn>) -> Self {
let mut converter = Converter::new();
converter.debruijn_to_named_debruijn(value)
converter.debruijn_to_named_debruijn(&value)
}
}
@ -449,7 +449,7 @@ impl From<Term<FakeNamedDeBruijn>> for Term<NamedDeBruijn> {
fn from(value: Term<FakeNamedDeBruijn>) -> Self {
let mut converter = Converter::new();
converter.fake_named_debruijn_to_named_debruijn(value)
converter.fake_named_debruijn_to_named_debruijn(&value)
}
}

View File

@ -1,3 +1,5 @@
use std::rc::Rc;
use thiserror::Error;
use crate::ast::{DeBruijn, FakeNamedDeBruijn, Name, NamedDeBruijn, Term, Unique};
@ -32,14 +34,14 @@ impl Converter {
pub fn name_to_named_debruijn(
&mut self,
term: Term<Name>,
term: &Term<Name>,
) -> Result<Term<NamedDeBruijn>, Error> {
let converted_term = match term {
Term::Var(Name { text, unique }) => Term::Var(NamedDeBruijn {
text,
index: self.get_index(unique)?,
text: text.to_string(),
index: self.get_index(*unique)?,
}),
Term::Delay(term) => Term::Delay(Box::new(self.name_to_named_debruijn(*term)?)),
Term::Delay(term) => Term::Delay(Rc::new(self.name_to_named_debruijn(term)?)),
Term::Lambda {
parameter_name,
body,
@ -49,13 +51,13 @@ impl Converter {
let index = self.get_index(parameter_name.unique)?;
let name = NamedDeBruijn {
text: parameter_name.text,
text: parameter_name.text.to_string(),
index,
};
self.start_scope();
let body = self.name_to_named_debruijn(*body)?;
let body = self.name_to_named_debruijn(body)?;
self.end_scope();
@ -63,26 +65,26 @@ impl Converter {
Term::Lambda {
parameter_name: name,
body: Box::new(body),
body: Rc::new(body),
}
}
Term::Apply { function, argument } => Term::Apply {
function: Box::new(self.name_to_named_debruijn(*function)?),
argument: Box::new(self.name_to_named_debruijn(*argument)?),
function: Rc::new(self.name_to_named_debruijn(function)?),
argument: Rc::new(self.name_to_named_debruijn(argument)?),
},
Term::Constant(constant) => Term::Constant(constant),
Term::Force(term) => Term::Force(Box::new(self.name_to_named_debruijn(*term)?)),
Term::Constant(constant) => Term::Constant(constant.clone()),
Term::Force(term) => Term::Force(Rc::new(self.name_to_named_debruijn(term)?)),
Term::Error => Term::Error,
Term::Builtin(builtin) => Term::Builtin(builtin),
Term::Builtin(builtin) => Term::Builtin(*builtin),
};
Ok(converted_term)
}
pub fn name_to_debruijn(&mut self, term: Term<Name>) -> Result<Term<DeBruijn>, Error> {
pub fn name_to_debruijn(&mut self, term: &Term<Name>) -> Result<Term<DeBruijn>, Error> {
let converted_term = match term {
Term::Var(Name { unique, .. }) => Term::Var(self.get_index(unique)?),
Term::Delay(term) => Term::Delay(Box::new(self.name_to_debruijn(*term)?)),
Term::Var(Name { unique, .. }) => Term::Var(self.get_index(*unique)?),
Term::Delay(term) => Term::Delay(Rc::new(self.name_to_debruijn(term)?)),
Term::Lambda {
parameter_name,
body,
@ -93,7 +95,7 @@ impl Converter {
self.start_scope();
let body = self.name_to_debruijn(*body)?;
let body = self.name_to_debruijn(body)?;
self.end_scope();
@ -101,17 +103,17 @@ impl Converter {
Term::Lambda {
parameter_name: name,
body: Box::new(body),
body: Rc::new(body),
}
}
Term::Apply { function, argument } => Term::Apply {
function: Box::new(self.name_to_debruijn(*function)?),
argument: Box::new(self.name_to_debruijn(*argument)?),
function: Rc::new(self.name_to_debruijn(function)?),
argument: Rc::new(self.name_to_debruijn(argument)?),
},
Term::Constant(constant) => Term::Constant(constant),
Term::Force(term) => Term::Force(Box::new(self.name_to_debruijn(*term)?)),
Term::Constant(constant) => Term::Constant(constant.clone()),
Term::Force(term) => Term::Force(Rc::new(self.name_to_debruijn(term)?)),
Term::Error => Term::Error,
Term::Builtin(builtin) => Term::Builtin(builtin),
Term::Builtin(builtin) => Term::Builtin(*builtin),
};
Ok(converted_term)
@ -119,14 +121,14 @@ impl Converter {
pub fn named_debruijn_to_name(
&mut self,
term: Term<NamedDeBruijn>,
term: &Term<NamedDeBruijn>,
) -> Result<Term<Name>, Error> {
let converted_term = match term {
Term::Var(NamedDeBruijn { text, index }) => Term::Var(Name {
text,
unique: self.get_unique(index)?,
text: text.to_string(),
unique: self.get_unique(*index)?,
}),
Term::Delay(term) => Term::Delay(Box::new(self.named_debruijn_to_name(*term)?)),
Term::Delay(term) => Term::Delay(Rc::new(self.named_debruijn_to_name(term)?)),
Term::Lambda {
parameter_name,
body,
@ -136,52 +138,52 @@ impl Converter {
let unique = self.get_unique(parameter_name.index)?;
let name = Name {
text: parameter_name.text,
text: parameter_name.text.to_string(),
unique,
};
self.start_scope();
let body = self.named_debruijn_to_name(*body)?;
let body = self.named_debruijn_to_name(body)?;
self.end_scope();
Term::Lambda {
parameter_name: name,
body: Box::new(body),
body: Rc::new(body),
}
}
Term::Apply { function, argument } => Term::Apply {
function: Box::new(self.named_debruijn_to_name(*function)?),
argument: Box::new(self.named_debruijn_to_name(*argument)?),
function: Rc::new(self.named_debruijn_to_name(function)?),
argument: Rc::new(self.named_debruijn_to_name(argument)?),
},
Term::Constant(constant) => Term::Constant(constant),
Term::Force(term) => Term::Force(Box::new(self.named_debruijn_to_name(*term)?)),
Term::Constant(constant) => Term::Constant(constant.clone()),
Term::Force(term) => Term::Force(Rc::new(self.named_debruijn_to_name(term)?)),
Term::Error => Term::Error,
Term::Builtin(builtin) => Term::Builtin(builtin),
Term::Builtin(builtin) => Term::Builtin(*builtin),
};
Ok(converted_term)
}
pub fn debruijn_to_name(&mut self, term: Term<DeBruijn>) -> Result<Term<Name>, Error> {
pub fn debruijn_to_name(&mut self, term: &Term<DeBruijn>) -> Result<Term<Name>, Error> {
let converted_term = match term {
Term::Var(index) => {
let unique = self.get_unique(index)?;
let unique = self.get_unique(*index)?;
Term::Var(Name {
text: format!("i_{}", unique),
unique,
})
}
Term::Delay(term) => Term::Delay(Box::new(self.debruijn_to_name(*term)?)),
Term::Delay(term) => Term::Delay(Rc::new(self.debruijn_to_name(term)?)),
Term::Lambda {
parameter_name,
body,
} => {
self.declare_binder();
let unique = self.get_unique(parameter_name)?;
let unique = self.get_unique(*parameter_name)?;
let name = Name {
text: format!("i_{}", unique),
@ -190,127 +192,127 @@ impl Converter {
self.start_scope();
let body = self.debruijn_to_name(*body)?;
let body = self.debruijn_to_name(body)?;
self.end_scope();
Term::Lambda {
parameter_name: name,
body: Box::new(body),
body: Rc::new(body),
}
}
Term::Apply { function, argument } => Term::Apply {
function: Box::new(self.debruijn_to_name(*function)?),
argument: Box::new(self.debruijn_to_name(*argument)?),
function: Rc::new(self.debruijn_to_name(function)?),
argument: Rc::new(self.debruijn_to_name(argument)?),
},
Term::Constant(constant) => Term::Constant(constant),
Term::Force(term) => Term::Force(Box::new(self.debruijn_to_name(*term)?)),
Term::Constant(constant) => Term::Constant(constant.clone()),
Term::Force(term) => Term::Force(Rc::new(self.debruijn_to_name(term)?)),
Term::Error => Term::Error,
Term::Builtin(builtin) => Term::Builtin(builtin),
Term::Builtin(builtin) => Term::Builtin(*builtin),
};
Ok(converted_term)
}
pub fn named_debruijn_to_debruijn(&mut self, term: Term<NamedDeBruijn>) -> Term<DeBruijn> {
pub fn named_debruijn_to_debruijn(&mut self, term: &Term<NamedDeBruijn>) -> Term<DeBruijn> {
match term {
Term::Var(name) => Term::Var(name.into()),
Term::Delay(term) => Term::Delay(Box::new(self.named_debruijn_to_debruijn(*term))),
Term::Var(name) => Term::Var(name.clone().into()),
Term::Delay(term) => Term::Delay(Rc::new(self.named_debruijn_to_debruijn(term))),
Term::Lambda {
parameter_name,
body,
} => Term::Lambda {
parameter_name: parameter_name.into(),
body: Box::new(self.named_debruijn_to_debruijn(*body)),
parameter_name: parameter_name.clone().into(),
body: Rc::new(self.named_debruijn_to_debruijn(body)),
},
Term::Apply { function, argument } => Term::Apply {
function: Box::new(self.named_debruijn_to_debruijn(*function)),
argument: Box::new(self.named_debruijn_to_debruijn(*argument)),
function: Rc::new(self.named_debruijn_to_debruijn(function)),
argument: Rc::new(self.named_debruijn_to_debruijn(argument)),
},
Term::Constant(constant) => Term::Constant(constant),
Term::Force(term) => Term::Force(Box::new(self.named_debruijn_to_debruijn(*term))),
Term::Constant(constant) => Term::Constant(constant.clone()),
Term::Force(term) => Term::Force(Rc::new(self.named_debruijn_to_debruijn(term))),
Term::Error => Term::Error,
Term::Builtin(builtin) => Term::Builtin(builtin),
Term::Builtin(builtin) => Term::Builtin(*builtin),
}
}
pub fn debruijn_to_named_debruijn(&mut self, term: Term<DeBruijn>) -> Term<NamedDeBruijn> {
pub fn debruijn_to_named_debruijn(&mut self, term: &Term<DeBruijn>) -> Term<NamedDeBruijn> {
match term {
Term::Var(name) => Term::Var(name.into()),
Term::Delay(term) => Term::Delay(Box::new(self.debruijn_to_named_debruijn(*term))),
Term::Var(name) => Term::Var((*name).into()),
Term::Delay(term) => Term::Delay(Rc::new(self.debruijn_to_named_debruijn(term))),
Term::Lambda {
parameter_name,
body,
} => Term::Lambda {
parameter_name: parameter_name.into(),
body: Box::new(self.debruijn_to_named_debruijn(*body)),
parameter_name: (*parameter_name).into(),
body: Rc::new(self.debruijn_to_named_debruijn(body)),
},
Term::Apply { function, argument } => Term::Apply {
function: Box::new(self.debruijn_to_named_debruijn(*function)),
argument: Box::new(self.debruijn_to_named_debruijn(*argument)),
function: Rc::new(self.debruijn_to_named_debruijn(function)),
argument: Rc::new(self.debruijn_to_named_debruijn(argument)),
},
Term::Constant(constant) => Term::Constant(constant),
Term::Force(term) => Term::Force(Box::new(self.debruijn_to_named_debruijn(*term))),
Term::Constant(constant) => Term::Constant(constant.clone()),
Term::Force(term) => Term::Force(Rc::new(self.debruijn_to_named_debruijn(term))),
Term::Error => Term::Error,
Term::Builtin(builtin) => Term::Builtin(builtin),
Term::Builtin(builtin) => Term::Builtin(*builtin),
}
}
pub fn fake_named_debruijn_to_named_debruijn(
&mut self,
term: Term<FakeNamedDeBruijn>,
term: &Term<FakeNamedDeBruijn>,
) -> Term<NamedDeBruijn> {
match term {
Term::Var(name) => Term::Var(name.into()),
Term::Var(name) => Term::Var(name.clone().into()),
Term::Delay(term) => {
Term::Delay(Box::new(self.fake_named_debruijn_to_named_debruijn(*term)))
Term::Delay(Rc::new(self.fake_named_debruijn_to_named_debruijn(term)))
}
Term::Lambda {
parameter_name,
body,
} => Term::Lambda {
parameter_name: parameter_name.into(),
body: Box::new(self.fake_named_debruijn_to_named_debruijn(*body)),
parameter_name: parameter_name.clone().into(),
body: Rc::new(self.fake_named_debruijn_to_named_debruijn(body)),
},
Term::Apply { function, argument } => Term::Apply {
function: Box::new(self.fake_named_debruijn_to_named_debruijn(*function)),
argument: Box::new(self.fake_named_debruijn_to_named_debruijn(*argument)),
function: Rc::new(self.fake_named_debruijn_to_named_debruijn(function)),
argument: Rc::new(self.fake_named_debruijn_to_named_debruijn(argument)),
},
Term::Constant(constant) => Term::Constant(constant),
Term::Constant(constant) => Term::Constant(constant.clone()),
Term::Force(term) => {
Term::Force(Box::new(self.fake_named_debruijn_to_named_debruijn(*term)))
Term::Force(Rc::new(self.fake_named_debruijn_to_named_debruijn(term)))
}
Term::Error => Term::Error,
Term::Builtin(builtin) => Term::Builtin(builtin),
Term::Builtin(builtin) => Term::Builtin(*builtin),
}
}
pub fn named_debruijn_to_fake_named_debruijn(
&mut self,
term: Term<NamedDeBruijn>,
term: &Term<NamedDeBruijn>,
) -> Term<FakeNamedDeBruijn> {
match term {
Term::Var(name) => Term::Var(name.into()),
Term::Var(name) => Term::Var(name.clone().into()),
Term::Delay(term) => {
Term::Delay(Box::new(self.named_debruijn_to_fake_named_debruijn(*term)))
Term::Delay(Rc::new(self.named_debruijn_to_fake_named_debruijn(term)))
}
Term::Lambda {
parameter_name,
body,
} => Term::Lambda {
parameter_name: parameter_name.into(),
body: Box::new(self.named_debruijn_to_fake_named_debruijn(*body)),
parameter_name: parameter_name.clone().into(),
body: Rc::new(self.named_debruijn_to_fake_named_debruijn(body)),
},
Term::Apply { function, argument } => Term::Apply {
function: Box::new(self.named_debruijn_to_fake_named_debruijn(*function)),
argument: Box::new(self.named_debruijn_to_fake_named_debruijn(*argument)),
function: Rc::new(self.named_debruijn_to_fake_named_debruijn(function)),
argument: Rc::new(self.named_debruijn_to_fake_named_debruijn(argument)),
},
Term::Constant(constant) => Term::Constant(constant),
Term::Constant(constant) => Term::Constant(constant.clone()),
Term::Force(term) => {
Term::Force(Box::new(self.named_debruijn_to_fake_named_debruijn(*term)))
Term::Force(Rc::new(self.named_debruijn_to_fake_named_debruijn(term)))
}
Term::Error => Term::Error,
Term::Builtin(builtin) => Term::Builtin(builtin),
Term::Builtin(builtin) => Term::Builtin(*builtin),
}
}

View File

@ -1,4 +1,4 @@
use std::{collections::VecDeque, fmt::Debug};
use std::{collections::VecDeque, fmt::Debug, rc::Rc};
use flat_rs::{
de::{self, Decode, Decoder},
@ -164,18 +164,18 @@ where
fn decode(d: &mut Decoder) -> Result<Self, de::Error> {
match decode_term_tag(d)? {
0 => Ok(Term::Var(T::decode(d)?)),
1 => Ok(Term::Delay(Box::new(Term::decode(d)?))),
1 => Ok(Term::Delay(Rc::new(Term::decode(d)?))),
2 => Ok(Term::Lambda {
parameter_name: T::binder_decode(d)?,
body: Box::new(Term::decode(d)?),
body: Rc::new(Term::decode(d)?),
}),
3 => Ok(Term::Apply {
function: Box::new(Term::decode(d)?),
argument: Box::new(Term::decode(d)?),
function: Rc::new(Term::decode(d)?),
argument: Rc::new(Term::decode(d)?),
}),
// Need size limit for Constant
4 => Ok(Term::Constant(Constant::decode(d)?)),
5 => Ok(Term::Force(Box::new(Term::decode(d)?))),
5 => Ok(Term::Force(Rc::new(Term::decode(d)?))),
6 => Ok(Term::Error),
7 => Ok(Term::Builtin(DefaultFunction::decode(d)?)),
x => Err(de::Error::Message(format!(

View File

@ -16,8 +16,8 @@ use self::{cost_model::CostModel, runtime::BuiltinRuntime};
enum MachineStep {
Return(Rc<Context>, Value),
Compute(Rc<Context>, Vec<Value>, Term<NamedDeBruijn>),
Done(Term<NamedDeBruijn>),
Compute(Rc<Context>, Rc<Vec<Value>>, Rc<Term<NamedDeBruijn>>),
Done(Rc<Term<NamedDeBruijn>>),
}
impl TryFrom<Option<MachineStep>> for Term<NamedDeBruijn> {
@ -25,7 +25,7 @@ impl TryFrom<Option<MachineStep>> for Term<NamedDeBruijn> {
fn try_from(value: Option<MachineStep>) -> Result<Self, Error> {
match value {
Some(MachineStep::Done(term)) => Ok(term),
Some(MachineStep::Done(term)) => Ok(Rc::as_ref(&term).clone()),
_ => Err(Error::MachineNeverReachedDone),
}
}
@ -59,8 +59,11 @@ impl Machine {
self.spend_budget(startup_budget)?;
self.stack
.push(Compute(Rc::new(Context::NoFrame), vec![], term.clone()));
self.stack.push(Compute(
Rc::new(Context::NoFrame),
Rc::new(vec![]),
Rc::new(term.clone()),
));
while let Some(step) = self.stack.pop() {
match step {
@ -84,10 +87,10 @@ impl Machine {
fn compute(
&mut self,
context: Rc<Context>,
env: Vec<Value>,
term: Term<NamedDeBruijn>,
env: Rc<Vec<Value>>,
term: Rc<Term<NamedDeBruijn>>,
) -> Result<(), Error> {
match term {
match term.as_ref() {
Term::Var(name) => {
self.step_and_maybe_spend(StepKind::Var)?;
@ -98,8 +101,10 @@ impl Machine {
Term::Delay(body) => {
self.step_and_maybe_spend(StepKind::Delay)?;
self.stack
.push(MachineStep::Return(context, Value::Delay(*body, env)));
self.stack.push(MachineStep::Return(
context,
Value::Delay(Rc::clone(body), env),
));
}
Term::Lambda {
parameter_name,
@ -110,8 +115,8 @@ impl Machine {
self.stack.push(MachineStep::Return(
context,
Value::Lambda {
parameter_name,
body: *body,
parameter_name: parameter_name.clone(),
body: Rc::clone(body),
env,
},
));
@ -120,15 +125,20 @@ impl Machine {
self.step_and_maybe_spend(StepKind::Apply)?;
self.stack.push(MachineStep::Compute(
Rc::new(Context::FrameApplyArg(env.clone(), *argument, context)),
Rc::new(Context::FrameApplyArg(
Rc::clone(&env),
Rc::clone(argument),
context,
)),
env,
*function,
Rc::clone(function),
));
}
Term::Constant(x) => {
self.step_and_maybe_spend(StepKind::Constant)?;
self.stack.push(MachineStep::Return(context, Value::Con(x)));
self.stack
.push(MachineStep::Return(context, Value::Con(x.clone())));
}
Term::Force(body) => {
self.step_and_maybe_spend(StepKind::Force)?;
@ -136,18 +146,22 @@ impl Machine {
self.stack.push(MachineStep::Compute(
Rc::new(Context::FrameForce(context)),
env,
*body,
Rc::clone(body),
));
}
Term::Error => return Err(Error::EvaluationFailure),
Term::Builtin(fun) => {
self.step_and_maybe_spend(StepKind::Builtin)?;
let runtime: BuiltinRuntime = (fun).into();
let runtime: BuiltinRuntime = (*fun).into();
self.stack.push(MachineStep::Return(
context,
Value::Builtin { fun, term, runtime },
Value::Builtin {
fun: *fun,
term,
runtime,
},
));
}
};
@ -164,7 +178,7 @@ impl Machine {
self.stack.push(MachineStep::Compute(
Rc::new(Context::FrameApplyFun(value, ctx.to_owned())),
arg_var_env.to_owned(),
arg.to_owned(),
Rc::clone(arg),
));
}
Context::FrameForce(ctx) => self.force_evaluate(ctx.to_owned(), value)?,
@ -182,68 +196,70 @@ impl Machine {
Ok(())
}
fn discharge_value(&mut self, value: Value) -> Term<NamedDeBruijn> {
fn discharge_value(&mut self, value: Value) -> Rc<Term<NamedDeBruijn>> {
match value {
Value::Con(x) => Term::Constant(x),
Value::Con(x) => Rc::new(Term::Constant(x)),
Value::Builtin { term, .. } => term,
Value::Delay(body, env) => self.discharge_value_env(env, Term::Delay(Box::new(body))),
Value::Delay(body, env) => self.discharge_value_env(env, Rc::new(Term::Delay(body))),
Value::Lambda {
parameter_name,
body,
env,
} => self.discharge_value_env(
env,
Term::Lambda {
Rc::new(Term::Lambda {
parameter_name: NamedDeBruijn {
text: parameter_name.text,
index: 0.into(),
},
body: Box::new(body),
},
body,
}),
),
}
}
fn discharge_value_env(
&mut self,
env: Vec<Value>,
term: Term<NamedDeBruijn>,
) -> Term<NamedDeBruijn> {
env: Rc<Vec<Value>>,
term: Rc<Term<NamedDeBruijn>>,
) -> Rc<Term<NamedDeBruijn>> {
fn rec(
lam_cnt: usize,
t: Term<NamedDeBruijn>,
t: Rc<Term<NamedDeBruijn>>,
this: &mut Machine,
env: &[Value],
) -> Term<NamedDeBruijn> {
match t {
env: Rc<Vec<Value>>,
) -> Rc<Term<NamedDeBruijn>> {
match t.as_ref() {
Term::Var(name) => {
let index: usize = name.index.into();
if lam_cnt >= index {
Term::Var(name)
Rc::new(Term::Var(name.clone()))
} else {
env.get::<usize>(env.len() - (index - lam_cnt))
.cloned()
.map_or(Term::Var(name), |v| this.discharge_value(v))
.map_or(Rc::new(Term::Var(name.clone())), |v| {
this.discharge_value(v)
})
}
}
Term::Lambda {
parameter_name,
body,
} => Term::Lambda {
parameter_name,
body: Box::new(rec(lam_cnt + 1, *body, this, env)),
},
Term::Apply { function, argument } => Term::Apply {
function: Box::new(rec(lam_cnt, *function, this, env)),
argument: Box::new(rec(lam_cnt, *argument, this, env)),
},
} => Rc::new(Term::Lambda {
parameter_name: parameter_name.clone(),
body: rec(lam_cnt + 1, Rc::clone(body), this, env),
}),
Term::Apply { function, argument } => Rc::new(Term::Apply {
function: rec(lam_cnt, Rc::clone(function), this, Rc::clone(&env)),
argument: rec(lam_cnt, Rc::clone(argument), this, env),
}),
Term::Delay(x) => Term::Delay(Box::new(rec(lam_cnt, *x, this, env))),
Term::Force(x) => Term::Force(Box::new(rec(lam_cnt, *x, this, env))),
rest => rest,
Term::Delay(x) => Rc::new(Term::Delay(rec(lam_cnt, Rc::clone(x), this, env))),
Term::Force(x) => Rc::new(Term::Force(rec(lam_cnt, Rc::clone(x), this, env))),
rest => Rc::new(rest.clone()),
}
}
rec(0, term, self, &env)
rec(0, term, self, env)
}
fn force_evaluate(&mut self, context: Rc<Context>, value: Value) -> Result<(), Error> {
@ -258,7 +274,7 @@ impl Machine {
term,
mut runtime,
} => {
let force_term = Term::Force(Box::new(term));
let force_term = Rc::new(Term::Force(term));
if runtime.needs_force() {
runtime.consume_force();
@ -269,7 +285,9 @@ impl Machine {
Ok(())
} else {
Err(Error::BuiltinTermArgumentExpected(force_term))
Err(Error::BuiltinTermArgumentExpected(
force_term.as_ref().clone(),
))
}
}
rest => Err(Error::NonPolymorphicInstantiation(rest)),
@ -283,12 +301,13 @@ impl Machine {
argument: Value,
) -> Result<(), Error> {
match function {
Value::Lambda { body, env, .. } => {
let mut e = env;
Value::Lambda { body, mut env, .. } => {
let e = Rc::make_mut(&mut env);
e.push(argument);
self.stack.push(MachineStep::Compute(context, e, body));
self.stack
.push(MachineStep::Compute(context, Rc::new(e.clone()), body));
Ok(())
}
@ -299,10 +318,10 @@ impl Machine {
} => {
let arg_term = self.discharge_value(argument.clone());
let t = Term::<NamedDeBruijn>::Apply {
function: Box::new(term),
argument: Box::new(arg_term),
};
let t = Rc::new(Term::<NamedDeBruijn>::Apply {
function: term,
argument: arg_term,
});
if runtime.is_arrow() && !runtime.needs_force() {
runtime.push(argument)?;
@ -313,7 +332,7 @@ impl Machine {
Ok(())
} else {
Err(Error::UnexpectedBuiltinTermArgument(t))
Err(Error::UnexpectedBuiltinTermArgument(t.as_ref().clone()))
}
}
rest => Err(Error::NonFunctionalApplication(rest)),
@ -323,7 +342,7 @@ impl Machine {
fn eval_builtin_app(
&mut self,
fun: DefaultFunction,
term: Term<NamedDeBruijn>,
term: Rc<Term<NamedDeBruijn>>,
runtime: BuiltinRuntime,
) -> Result<Value, Error> {
if runtime.is_ready() {
@ -337,10 +356,10 @@ impl Machine {
}
}
fn lookup_var(&mut self, name: NamedDeBruijn, env: Vec<Value>) -> Result<Value, Error> {
fn lookup_var(&mut self, name: &NamedDeBruijn, env: Rc<Vec<Value>>) -> Result<Value, Error> {
env.get::<usize>(env.len() - usize::from(name.index))
.cloned()
.ok_or(Error::OpenTermEvaluated(Term::Var(name)))
.ok_or_else(|| Error::OpenTermEvaluated(Term::Var(name.clone())))
}
fn step_and_maybe_spend(&mut self, step: StepKind) -> Result<(), Error> {
@ -387,7 +406,7 @@ impl Machine {
#[derive(Clone)]
enum Context {
FrameApplyFun(Value, Rc<Context>),
FrameApplyArg(Vec<Value>, Term<NamedDeBruijn>, Rc<Context>),
FrameApplyArg(Rc<Vec<Value>>, Rc<Term<NamedDeBruijn>>, Rc<Context>),
FrameForce(Rc<Context>),
NoFrame,
}
@ -395,15 +414,15 @@ enum Context {
#[derive(Clone, Debug)]
pub enum Value {
Con(Constant),
Delay(Term<NamedDeBruijn>, Vec<Value>),
Delay(Rc<Term<NamedDeBruijn>>, Rc<Vec<Value>>),
Lambda {
parameter_name: NamedDeBruijn,
body: Term<NamedDeBruijn>,
env: Vec<Value>,
body: Rc<Term<NamedDeBruijn>>,
env: Rc<Vec<Value>>,
},
Builtin {
fun: DefaultFunction,
term: Term<NamedDeBruijn>,
term: Rc<Term<NamedDeBruijn>>,
runtime: BuiltinRuntime,
},
}

View File

@ -19,8 +19,8 @@ impl ExBudget {
impl Default for ExBudget {
fn default() -> Self {
ExBudget {
mem: 14000000,
cpu: 10000000000,
mem: 14000000000000,
cpu: 10000000000000000,
}
}
}

View File

@ -1,4 +1,4 @@
use std::str::FromStr;
use std::{rc::Rc, str::FromStr};
use crate::{
ast::{Constant, Name, Program, Term},
@ -67,7 +67,7 @@ peg::parser! {
rule lambda() -> Term<Name>
= "(" _* "lam" _+ parameter_name:name() _+ t:term() _* ")" {
Term::Lambda { parameter_name, body: Box::new(t) }
Term::Lambda { parameter_name, body: Rc::new(t) }
}
#[cache_left_rec]
@ -76,16 +76,16 @@ peg::parser! {
terms
.into_iter()
.fold(initial, |lhs, rhs| Term::Apply {
function: Box::new(lhs),
argument: Box::new(rhs)
function: Rc::new(lhs),
argument: Rc::new(rhs)
})
}
rule delay() -> Term<Name>
= "(" _* "delay" _* t:term() _* ")" { Term::Delay(Box::new(t)) }
= "(" _* "delay" _* t:term() _* ")" { Term::Delay(Rc::new(t)) }
rule force() -> Term<Name>
= "(" _* "force" _* t:term() _* ")" { Term::Force(Box::new(t)) }
= "(" _* "force" _* t:term() _* ")" { Term::Force(Rc::new(t)) }
rule error() -> Term<Name>
= "(" _* "error" _* ")" { Term::Error }

View File

@ -1,4 +1,4 @@
use std::collections::HashMap;
use std::{collections::HashMap, rc::Rc};
use crate::ast::{Name, Program, Term, Unique};
@ -22,20 +22,20 @@ impl Interner {
pub fn term(&mut self, term: &mut Term<Name>) {
match term {
Term::Var(name) => name.unique = self.intern(&name.text),
Term::Delay(term) => self.term(term),
Term::Delay(term) => self.term(Rc::make_mut(term)),
Term::Lambda {
parameter_name,
body,
} => {
parameter_name.unique = self.intern(&parameter_name.text);
self.term(body);
self.term(Rc::make_mut(body));
}
Term::Apply { function, argument } => {
self.term(function);
self.term(argument);
self.term(Rc::make_mut(function));
self.term(Rc::make_mut(argument));
}
Term::Constant(_) => (),
Term::Force(term) => self.term(term),
Term::Force(term) => self.term(Rc::make_mut(term)),
Term::Error => (),
Term::Builtin(_) => (),
}

View File

@ -1,3 +1,5 @@
use std::rc::Rc;
use crate::ast::{Name, Term};
use crate::program_builder::WithTerm;
@ -30,8 +32,8 @@ impl<T: WithTerm> WithTerm for ApplyBuilderArgument<T> {
fn next(self, term: Term<Name>) -> Self::Next {
let term = Term::Apply {
function: Box::new(self.function),
argument: Box::new(term),
function: Rc::new(self.function),
argument: Rc::new(term),
};
self.outer.next(term)
}

View File

@ -1,3 +1,5 @@
use std::rc::Rc;
use crate::ast::{Name, Term};
use crate::program_builder::WithTerm;
@ -9,7 +11,7 @@ impl<T: WithTerm> WithTerm for DelayBuilder<T> {
type Next = T::Next;
fn next(self, term: Term<Name>) -> Self::Next {
let term = Term::Delay(Box::new(term));
let term = Term::Delay(Rc::new(term));
self.outer.next(term)
}

View File

@ -1,3 +1,5 @@
use std::rc::Rc;
use crate::ast::{Name, Term};
use crate::program_builder::WithTerm;
@ -9,7 +11,7 @@ impl<T: WithTerm> WithTerm for ForceBuilder<T> {
type Next = T::Next;
fn next(self, term: Term<Name>) -> Self::Next {
let term = Term::Force(Box::new(term));
let term = Term::Force(Rc::new(term));
self.outer.next(term)
}

View File

@ -1,3 +1,5 @@
use std::rc::Rc;
use crate::ast::{Name, Term};
use crate::program_builder::WithTerm;
@ -12,7 +14,7 @@ impl<T: WithTerm> WithTerm for LambdaBuilder<T> {
fn next(self, term: Term<Name>) -> Self::Next {
let term = Term::Lambda {
parameter_name: self.parameter_name,
body: Box::new(term),
body: Rc::new(term),
};
self.outer.next(term)
}