feat: clean up the machine a bit
This commit is contained in:
		
							parent
							
								
									de476c801b
								
							
						
					
					
						commit
						795d9ee028
					
				|  | @ -14,6 +14,32 @@ pub struct Program<T> { | ||||||
|     pub term: Term<T>, |     pub term: Term<T>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | impl<T> Program<T> | ||||||
|  | where | ||||||
|  |     T: Clone, | ||||||
|  | { | ||||||
|  |     /// We use this to apply the validator to Datum,
 | ||||||
|  |     /// then redeemer, then ScriptContext. If datum is
 | ||||||
|  |     /// even necessary (i.e. minting policy).
 | ||||||
|  |     ///
 | ||||||
|  |     /// ```rust
 | ||||||
|  |     /// program.apply(&datum)
 | ||||||
|  |     ///    .apply(&redeemer)
 | ||||||
|  |     ///    .apply(&script_context);
 | ||||||
|  |     /// ```
 | ||||||
|  |     pub fn apply(&self, program: &Self) -> Self { | ||||||
|  |         let applied_term = Term::Apply { | ||||||
|  |             function: Box::new(self.term.clone()), | ||||||
|  |             argument: Box::new(program.term.clone()), | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         Program { | ||||||
|  |             version: self.version, | ||||||
|  |             term: applied_term, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /// This represents a term in Untyped Plutus Core.
 | /// This represents a term in Untyped Plutus Core.
 | ||||||
| /// We need a generic type for the different forms that a program may be in.
 | /// We need a generic type for the different forms that a program may be in.
 | ||||||
| /// Specifically, `Var` and `parameter_name` in `Lambda` can be a `Name`,
 | /// Specifically, `Var` and `parameter_name` in `Lambda` can be a `Name`,
 | ||||||
|  | @ -374,14 +400,3 @@ impl From<Term<FakeNamedDeBruijn>> for Term<NamedDeBruijn> { | ||||||
|         converter.fake_named_debruijn_to_named_debruijn(value) |         converter.fake_named_debruijn_to_named_debruijn(value) | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 |  | ||||||
| pub fn apply_program<T>(p1: Program<T>, p2: Program<T>) -> Program<T> { |  | ||||||
|     let applied_term = Term::Apply { |  | ||||||
|         function: Box::new(p1.term), |  | ||||||
|         argument: Box::new(p2.term), |  | ||||||
|     }; |  | ||||||
|     Program { |  | ||||||
|         version: p1.version, |  | ||||||
|         term: applied_term, |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  | @ -16,6 +16,7 @@ enum StepKind { | ||||||
|     BForce = 5, |     BForce = 5, | ||||||
|     BBuiltin = 6, |     BBuiltin = 6, | ||||||
| } | } | ||||||
|  | 
 | ||||||
| impl TryFrom<u8> for StepKind { | impl TryFrom<u8> for StepKind { | ||||||
|     type Error = de::Error; |     type Error = de::Error; | ||||||
| 
 | 
 | ||||||
|  | @ -41,6 +42,7 @@ enum ExBudgetCategory { | ||||||
|     BBuiltinApp(DefaultFunction), |     BBuiltinApp(DefaultFunction), | ||||||
|     BStartup, |     BStartup, | ||||||
| } | } | ||||||
|  | 
 | ||||||
| /// Can be negative
 | /// Can be negative
 | ||||||
| #[derive(Debug, Clone, PartialEq)] | #[derive(Debug, Clone, PartialEq)] | ||||||
| struct ExBudget { | struct ExBudget { | ||||||
|  | @ -146,27 +148,3 @@ fn spend_accumulated_budget_cek(unbudgeted_steps: &mut Vec<u32>, current_budget: | ||||||
|         ); |         ); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 |  | ||||||
| fn spend_budget_cek( |  | ||||||
|     current_budget: &mut ExBudget, |  | ||||||
|     category: ExBudgetCategory, |  | ||||||
|     spend_budget: ExBudget, |  | ||||||
| ) { |  | ||||||
|     current_budget.mem -= spend_budget.mem; |  | ||||||
|     current_budget.cpu -= spend_budget.cpu; |  | ||||||
|     if current_budget.mem < 0 || current_budget.cpu < 0 { |  | ||||||
|         panic!("Budget exhausted {:?}", current_budget); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| fn get_cost_by_step(step: StepKind) -> ExBudget { |  | ||||||
|     match (step) { |  | ||||||
|         StepKind::BConst => ExBudget { mem: 100, cpu: 100 }, |  | ||||||
|         StepKind::BVar => ExBudget { mem: 100, cpu: 100 }, |  | ||||||
|         StepKind::BLamAbs => ExBudget { mem: 100, cpu: 100 }, |  | ||||||
|         StepKind::BApply => ExBudget { mem: 100, cpu: 100 }, |  | ||||||
|         StepKind::BDelay => ExBudget { mem: 100, cpu: 100 }, |  | ||||||
|         StepKind::BForce => ExBudget { mem: 100, cpu: 100 }, |  | ||||||
|         StepKind::BBuiltin => ExBudget { mem: 100, cpu: 100 }, |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  | @ -3,6 +3,7 @@ pub mod builtins; | ||||||
| mod debruijn; | mod debruijn; | ||||||
| mod flat; | mod flat; | ||||||
| pub mod interpreter; | pub mod interpreter; | ||||||
|  | pub mod machine; | ||||||
| pub mod parser; | pub mod parser; | ||||||
| mod pretty; | mod pretty; | ||||||
| pub mod program_builder; | pub mod program_builder; | ||||||
|  |  | ||||||
|  | @ -0,0 +1,132 @@ | ||||||
|  | use crate::{ | ||||||
|  |     ast::{Constant, DeBruijn, Term}, | ||||||
|  |     builtins::DefaultFunction, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | mod error; | ||||||
|  | 
 | ||||||
|  | pub use error::Error; | ||||||
|  | 
 | ||||||
|  | pub struct Machine { | ||||||
|  |     costs: Costs, | ||||||
|  |     ex_budget: ExBudget, | ||||||
|  |     frames: Vec<Context>, | ||||||
|  |     slippage: u32, | ||||||
|  |     env: Vec<Value>, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl Machine { | ||||||
|  |     pub fn new(costs: Costs, initial_budget: ExBudget, slippage: u32) -> Machine { | ||||||
|  |         Machine { | ||||||
|  |             costs, | ||||||
|  |             ex_budget: initial_budget, | ||||||
|  |             slippage, | ||||||
|  |             frames: vec![], | ||||||
|  |             env: vec![], | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn run( | ||||||
|  |         &mut self, | ||||||
|  |         term: &Term<DeBruijn>, | ||||||
|  |     ) -> Result<(Term<DeBruijn>, usize, Vec<String>), Error> { | ||||||
|  |         let startup_budget = self.costs.get(StepKind::StartUp); | ||||||
|  | 
 | ||||||
|  |         self.spend_budget(startup_budget)?; | ||||||
|  | 
 | ||||||
|  |         self.push_frame(Context::NoFrame); | ||||||
|  | 
 | ||||||
|  |         self.enter_compute(term) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn enter_compute(&mut self, term: &Term<DeBruijn>) {} | ||||||
|  | 
 | ||||||
|  |     fn spend_budget(&mut self, spend_budget: ExBudget) -> Result<(), Error> { | ||||||
|  |         self.ex_budget.mem -= spend_budget.mem; | ||||||
|  |         self.ex_budget.cpu -= spend_budget.cpu; | ||||||
|  | 
 | ||||||
|  |         if self.ex_budget.mem < 0 || self.ex_budget.cpu < 0 { | ||||||
|  |             Err(Error::OutOfExError(self.ex_budget)) | ||||||
|  |         } else { | ||||||
|  |             Ok(()) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn push_frame(&mut self, frame: Context) { | ||||||
|  |         self.frames.push(frame); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | enum Context { | ||||||
|  |     FrameApplyFun(Term<DeBruijn>, Term<DeBruijn>), | ||||||
|  |     FrameApplyArg(Vec<Value>, Term<DeBruijn>, Box<Context>), | ||||||
|  |     FrameForce(Box<Context>), | ||||||
|  |     NoFrame, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | enum Value { | ||||||
|  |     Con(Constant), | ||||||
|  |     Delay(Term<DeBruijn>, Vec<Value>), | ||||||
|  |     Lambda(DeBruijn, Term<DeBruijn>, Vec<Value>), | ||||||
|  |     Builtin( | ||||||
|  |         DefaultFunction, | ||||||
|  |         Term<DeBruijn>, | ||||||
|  |         // Need to figure out run time stuff
 | ||||||
|  |         // BuiltinRuntime (CekValue uni fun)
 | ||||||
|  |     ), | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /// Can be negative
 | ||||||
|  | #[derive(Debug, Clone, PartialEq)] | ||||||
|  | struct ExBudget { | ||||||
|  |     mem: i32, | ||||||
|  |     cpu: i32, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl ExBudget { | ||||||
|  |     pub fn occurence(&mut self, n: i32) { | ||||||
|  |         self.mem *= n; | ||||||
|  |         self.cpu *= n; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | enum StepKind { | ||||||
|  |     Constant, | ||||||
|  |     Var, | ||||||
|  |     Lambda, | ||||||
|  |     Apply, | ||||||
|  |     Delay, | ||||||
|  |     Force, | ||||||
|  |     Builtin, | ||||||
|  |     StartUp, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /// There's no entry for Error since we'll be exiting anyway; also, what would
 | ||||||
|  | /// happen if calling 'Error' caused the budget to be exceeded?
 | ||||||
|  | struct Costs { | ||||||
|  |     startup: ExBudget, | ||||||
|  |     var: ExBudget, | ||||||
|  |     constant: ExBudget, | ||||||
|  |     lambda: ExBudget, | ||||||
|  |     delay: ExBudget, | ||||||
|  |     force: ExBudget, | ||||||
|  |     apply: ExBudget, | ||||||
|  |     /// Just the cost of evaluating a Builtin node, not the builtin itself.
 | ||||||
|  |     builtin: ExBudget, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl Costs { | ||||||
|  |     /// Get the cost of a step
 | ||||||
|  |     pub fn get(&self, step: StepKind) -> ExBudget { | ||||||
|  |         match step { | ||||||
|  |             StepKind::Constant => self.constant, | ||||||
|  |             StepKind::Var => self.var, | ||||||
|  |             StepKind::Lambda => self.lambda, | ||||||
|  |             StepKind::Apply => self.apply, | ||||||
|  |             StepKind::Delay => self.delay, | ||||||
|  |             StepKind::Force => self.force, | ||||||
|  |             StepKind::Builtin => self.builtin, | ||||||
|  |             StepKind::StartUp => self.startup, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,9 @@ | ||||||
|  | use thiserror::Error; | ||||||
|  | 
 | ||||||
|  | use super::ExBudget; | ||||||
|  | 
 | ||||||
|  | #[derive(Error, Debug)] | ||||||
|  | pub enum Error { | ||||||
|  |     #[error("Over budget mem: {} & cpu: {}", .0.mem, .0.cpu)] | ||||||
|  |     OutOfExError(ExBudget), | ||||||
|  | } | ||||||
		Loading…
	
		Reference in New Issue
	
	 rvcas
						rvcas