diff --git a/crates/uplc/src/ast.rs b/crates/uplc/src/ast.rs index f303eacf..8e40b22d 100644 --- a/crates/uplc/src/ast.rs +++ b/crates/uplc/src/ast.rs @@ -374,3 +374,14 @@ impl From> for Term { converter.fake_named_debruijn_to_named_debruijn(value) } } + +pub fn apply_program(p1: Program, p2: Program) -> Program { + let applied_term = Term::Apply { + function: Box::new(p1.term), + argument: Box::new(p2.term), + }; + Program { + version: p1.version, + term: applied_term, + } +} diff --git a/crates/uplc/src/interpreter.rs b/crates/uplc/src/interpreter.rs new file mode 100644 index 00000000..3e109624 --- /dev/null +++ b/crates/uplc/src/interpreter.rs @@ -0,0 +1,110 @@ +use crate::{ + ast::{Constant, NamedDeBruijn, Term}, + builtins::DefaultFunction, +}; + +enum StepKind { + BConst = 0, + BVar = 1, + BLamAbs = 2, + BApply = 3, + BDelay = 4, + BForce = 5, + BBuiltin = 6, +} + +enum ExBudgetCategory { + BStep(StepKind), + BBuiltinApp(DefaultFunction), + BStartup, +} +/// Can be negative +#[derive(Debug, Clone, PartialEq)] +struct ExBudget { + mem: i32, + cpu: i32, +} + +enum CekValue { + VCon(Constant), + VDelay(Term, Vec), + VLamAbs(NamedDeBruijn, Term, Vec), + VBuiltin( + DefaultFunction, + Term, + // Need to figure out run time stuff + // BuiltinRuntime (CekValue uni fun) + ), +} + +enum Context { + FrameApplyFun(Term, Term), + FrameApplyArg(Vec, Term, Box), + FrameForce(Box), + NoFrame, +} + +// For now let's just start with running cek on term with generic params +fn run_cek_debruijn(term: Term) -> (Term, usize, Vec) { + //paramerterize this + let initial_budget = ExBudget { + mem: 1000, + cpu: 1000, + }; + + let evaluation = enter_compute_cek(Context::NoFrame, Vec::new(), term); + todo!() +} + +fn spend_budget_cek( + current_budget: ExBudget, + category: ExBudgetCategory, + spend_budget: ExBudget, +) -> ExBudget { + let new_budget = ExBudget { + mem: current_budget.mem - spend_budget.mem, + cpu: current_budget.cpu - spend_budget.cpu, + }; + if new_budget.mem < 0 || new_budget.cpu < 0 { + panic!("Budget exhausted {:?}", new_budget); + } + new_budget +} + +fn enter_compute_cek( + frame: Context, + env: Vec, + term: Term, +) -> (Term, usize, Vec) { + //enter compute + compute_cek(Vec::with_capacity(8), frame, env, term) +} + +fn compute_cek( + mut unbudgeted_steps: Vec, + frame: Context, + env: Vec, + term: Term, +) -> (Term, usize, Vec) { + //TODO: parameterize slippage + let slippage = 200; + match (term) { + a @ Term::Var(_) => { + unbudgeted_steps[2] += 1; + unbudgeted_steps[7] += 1; + //TODO spend budget one slippage is met + todo!() + } + Term::Delay(_) => todo!(), + Term::Lambda { + parameter_name, + body, + } => todo!(), + Term::Apply { function, argument } => todo!(), + Term::Constant(_) => todo!(), + Term::Force(_) => todo!(), + Term::Error => todo!(), + Term::Builtin(_) => todo!(), + } +} + diff --git a/crates/uplc/src/lib.rs b/crates/uplc/src/lib.rs index 6d22da98..f6512702 100644 --- a/crates/uplc/src/lib.rs +++ b/crates/uplc/src/lib.rs @@ -2,6 +2,7 @@ pub mod ast; pub mod builtins; mod debruijn; mod flat; +pub mod interpreter; pub mod parser; mod pretty; pub mod program_builder;