diff --git a/crates/uplc/src/ast.rs b/crates/uplc/src/ast.rs index e02570eb..e9006e6b 100644 --- a/crates/uplc/src/ast.rs +++ b/crates/uplc/src/ast.rs @@ -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 { // tag: 0 Var(T), // tag: 1 - Delay(Box>), + Delay(Rc>), // tag: 2 Lambda { parameter_name: T, - body: Box>, + body: Rc>, }, // tag: 3 Apply { - function: Box>, - argument: Box>, + function: Rc>, + argument: Rc>, }, // tag: 4 Constant(Constant), // tag: 5 - Force(Box>), + Force(Rc>), // tag: 6 Error, // tag: 7 @@ -306,7 +306,7 @@ impl TryFrom> for Term { fn try_from(value: Term) -> Result { 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> for Term { fn try_from(value: Term) -> Result { 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> for Term { fn try_from(value: Term) -> Result { 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> for Term { fn from(value: Term) -> Self { let mut converter = Converter::new(); - converter.named_debruijn_to_debruijn(value) + converter.named_debruijn_to_debruijn(&value) } } @@ -392,7 +392,7 @@ impl From> for Term { fn from(value: Term) -> 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> for Term { fn try_from(value: Term) -> Result { 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> for Term { fn from(value: Term) -> Self { let mut converter = Converter::new(); - converter.debruijn_to_named_debruijn(value) + converter.debruijn_to_named_debruijn(&value) } } @@ -449,7 +449,7 @@ impl From> for Term { fn from(value: Term) -> Self { let mut converter = Converter::new(); - converter.fake_named_debruijn_to_named_debruijn(value) + converter.fake_named_debruijn_to_named_debruijn(&value) } } diff --git a/crates/uplc/src/debruijn.rs b/crates/uplc/src/debruijn.rs index e8e17a3d..f68cf86e 100644 --- a/crates/uplc/src/debruijn.rs +++ b/crates/uplc/src/debruijn.rs @@ -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, + term: &Term, ) -> Result, 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) -> Result, Error> { + pub fn name_to_debruijn(&mut self, term: &Term) -> Result, 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, + term: &Term, ) -> Result, 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) -> Result, Error> { + pub fn debruijn_to_name(&mut self, term: &Term) -> Result, 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) -> Term { + pub fn named_debruijn_to_debruijn(&mut self, term: &Term) -> Term { 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) -> Term { + pub fn debruijn_to_named_debruijn(&mut self, term: &Term) -> Term { 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, + term: &Term, ) -> Term { 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, + term: &Term, ) -> Term { 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), } } diff --git a/crates/uplc/src/flat.rs b/crates/uplc/src/flat.rs index 427989fe..161751f8 100644 --- a/crates/uplc/src/flat.rs +++ b/crates/uplc/src/flat.rs @@ -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 { 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!( diff --git a/crates/uplc/src/machine.rs b/crates/uplc/src/machine.rs index e21afd99..48d59807 100644 --- a/crates/uplc/src/machine.rs +++ b/crates/uplc/src/machine.rs @@ -16,8 +16,8 @@ use self::{cost_model::CostModel, runtime::BuiltinRuntime}; enum MachineStep { Return(Rc, Value), - Compute(Rc, Vec, Term), - Done(Term), + Compute(Rc, Rc>, Rc>), + Done(Rc>), } impl TryFrom> for Term { @@ -25,7 +25,7 @@ impl TryFrom> for Term { fn try_from(value: Option) -> Result { 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, - env: Vec, - term: Term, + env: Rc>, + term: Rc>, ) -> 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 { + fn discharge_value(&mut self, value: Value) -> Rc> { 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, - term: Term, - ) -> Term { + env: Rc>, + term: Rc>, + ) -> Rc> { fn rec( lam_cnt: usize, - t: Term, + t: Rc>, this: &mut Machine, - env: &[Value], - ) -> Term { - match t { + env: Rc>, + ) -> Rc> { + 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::(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, 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::::Apply { - function: Box::new(term), - argument: Box::new(arg_term), - }; + let t = Rc::new(Term::::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, + term: Rc>, runtime: BuiltinRuntime, ) -> Result { if runtime.is_ready() { @@ -337,10 +356,10 @@ impl Machine { } } - fn lookup_var(&mut self, name: NamedDeBruijn, env: Vec) -> Result { + fn lookup_var(&mut self, name: &NamedDeBruijn, env: Rc>) -> Result { env.get::(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), - FrameApplyArg(Vec, Term, Rc), + FrameApplyArg(Rc>, Rc>, Rc), FrameForce(Rc), NoFrame, } @@ -395,15 +414,15 @@ enum Context { #[derive(Clone, Debug)] pub enum Value { Con(Constant), - Delay(Term, Vec), + Delay(Rc>, Rc>), Lambda { parameter_name: NamedDeBruijn, - body: Term, - env: Vec, + body: Rc>, + env: Rc>, }, Builtin { fun: DefaultFunction, - term: Term, + term: Rc>, runtime: BuiltinRuntime, }, } diff --git a/crates/uplc/src/machine/cost_model.rs b/crates/uplc/src/machine/cost_model.rs index 7d8a2fff..e44c9058 100644 --- a/crates/uplc/src/machine/cost_model.rs +++ b/crates/uplc/src/machine/cost_model.rs @@ -19,8 +19,8 @@ impl ExBudget { impl Default for ExBudget { fn default() -> Self { ExBudget { - mem: 14000000, - cpu: 10000000000, + mem: 14000000000000, + cpu: 10000000000000000, } } } diff --git a/crates/uplc/src/parser.rs b/crates/uplc/src/parser.rs index fc940c8f..5caee1ca 100644 --- a/crates/uplc/src/parser.rs +++ b/crates/uplc/src/parser.rs @@ -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 = "(" _* "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 - = "(" _* "delay" _* t:term() _* ")" { Term::Delay(Box::new(t)) } + = "(" _* "delay" _* t:term() _* ")" { Term::Delay(Rc::new(t)) } rule force() -> Term - = "(" _* "force" _* t:term() _* ")" { Term::Force(Box::new(t)) } + = "(" _* "force" _* t:term() _* ")" { Term::Force(Rc::new(t)) } rule error() -> Term = "(" _* "error" _* ")" { Term::Error } diff --git a/crates/uplc/src/parser/interner.rs b/crates/uplc/src/parser/interner.rs index ceae93aa..7b9185bc 100644 --- a/crates/uplc/src/parser/interner.rs +++ b/crates/uplc/src/parser/interner.rs @@ -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) { 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(¶meter_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(_) => (), } diff --git a/crates/uplc/src/program_builder/apply.rs b/crates/uplc/src/program_builder/apply.rs index b6808523..7170df7c 100644 --- a/crates/uplc/src/program_builder/apply.rs +++ b/crates/uplc/src/program_builder/apply.rs @@ -1,3 +1,5 @@ +use std::rc::Rc; + use crate::ast::{Name, Term}; use crate::program_builder::WithTerm; @@ -30,8 +32,8 @@ impl WithTerm for ApplyBuilderArgument { fn next(self, term: Term) -> 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) } diff --git a/crates/uplc/src/program_builder/delay.rs b/crates/uplc/src/program_builder/delay.rs index eb2850bd..e991391b 100644 --- a/crates/uplc/src/program_builder/delay.rs +++ b/crates/uplc/src/program_builder/delay.rs @@ -1,3 +1,5 @@ +use std::rc::Rc; + use crate::ast::{Name, Term}; use crate::program_builder::WithTerm; @@ -9,7 +11,7 @@ impl WithTerm for DelayBuilder { type Next = T::Next; fn next(self, term: Term) -> Self::Next { - let term = Term::Delay(Box::new(term)); + let term = Term::Delay(Rc::new(term)); self.outer.next(term) } diff --git a/crates/uplc/src/program_builder/force.rs b/crates/uplc/src/program_builder/force.rs index 3c2ff90f..b2b7a1af 100644 --- a/crates/uplc/src/program_builder/force.rs +++ b/crates/uplc/src/program_builder/force.rs @@ -1,3 +1,5 @@ +use std::rc::Rc; + use crate::ast::{Name, Term}; use crate::program_builder::WithTerm; @@ -9,7 +11,7 @@ impl WithTerm for ForceBuilder { type Next = T::Next; fn next(self, term: Term) -> Self::Next { - let term = Term::Force(Box::new(term)); + let term = Term::Force(Rc::new(term)); self.outer.next(term) } diff --git a/crates/uplc/src/program_builder/lambda.rs b/crates/uplc/src/program_builder/lambda.rs index 7518298c..b301f28b 100644 --- a/crates/uplc/src/program_builder/lambda.rs +++ b/crates/uplc/src/program_builder/lambda.rs @@ -1,3 +1,5 @@ +use std::rc::Rc; + use crate::ast::{Name, Term}; use crate::program_builder::WithTerm; @@ -12,7 +14,7 @@ impl WithTerm for LambdaBuilder { fn next(self, term: Term) -> Self::Next { let term = Term::Lambda { parameter_name: self.parameter_name, - body: Box::new(term), + body: Rc::new(term), }; self.outer.next(term) }