1use bumpalo::Bump;
2
3use crate::{
4 binder::Eval,
5 machine::{BuiltinSemantics, CostModel, EvalResult, ExBudget, Machine},
6 term::Term,
7};
8
9#[derive(Debug)]
10pub struct Program<'a, V> {
11 pub version: &'a Version<'a>,
12 pub term: &'a Term<'a, V>,
13}
14
15impl<'a, V> Program<'a, V> {
16 pub fn new(arena: &'a Bump, version: &'a Version<'a>, term: &'a Term<'a, V>) -> &'a Self {
17 let program = Program { version, term };
18
19 arena.alloc(program)
20 }
21
22 pub fn apply(&'a self, arena: &'a Bump, term: &'a Term<'a, V>) -> &'a Self {
23 let term = self.term.apply(arena, term);
24
25 Self::new(arena, self.version, term)
26 }
27}
28
29impl<'a, V> Program<'a, V>
30where
31 V: Eval<'a>,
32{
33 pub fn eval(&'a self, arena: &'a Bump) -> EvalResult<'a, V> {
34 let mut machine = Machine::new(
35 arena,
36 ExBudget::default(),
37 CostModel::default(),
38 if self.version.is_v1_1_0() {
42 BuiltinSemantics::V2
43 } else {
44 BuiltinSemantics::V1
45 },
46 );
47
48 let term = machine.run(self.term);
49 let mut info = machine.info();
50
51 info.consumed_budget = ExBudget::default() - info.consumed_budget;
52
53 EvalResult { term, info }
54 }
55}
56
57#[derive(Debug, Copy, Clone)]
58pub struct Version<'a>(&'a (usize, usize, usize));
59
60impl<'a> Version<'a> {
61 pub fn new(arena: &'a Bump, major: usize, minor: usize, patch: usize) -> &'a mut Self {
62 let version = arena.alloc((major, minor, patch));
63
64 arena.alloc(Version(version))
65 }
66
67 pub fn plutus_v1(arena: &'a Bump) -> &'a mut Self {
68 Self::new(arena, 1, 0, 0)
69 }
70
71 pub fn plutus_v2(arena: &'a Bump) -> &'a mut Self {
72 Self::new(arena, 1, 0, 0)
73 }
74
75 pub fn plutus_v3(arena: &'a Bump) -> &'a mut Self {
76 Self::new(arena, 1, 1, 0)
77 }
78
79 pub fn is_v1_0_0(&'a self) -> bool {
80 self.0 .0 == 1 && self.0 .1 == 0 && self.0 .2 == 0
81 }
82
83 pub fn is_v1_1_0(&'a self) -> bool {
84 self.0 .0 == 1 && self.0 .1 == 1 && self.0 .2 == 0
85 }
86
87 pub fn is_valid_version(&'a self) -> bool {
88 self.is_v1_0_0() || self.is_v1_1_0()
89 }
90
91 pub fn is_less_than_1_1_0(&'a self) -> bool {
92 self.0 .0 == 0 || self.0 .1 == 0
93 }
94
95 pub fn major(&'a self) -> usize {
96 self.0 .0
97 }
98
99 pub fn minor(&'a self) -> usize {
100 self.0 .1
101 }
102
103 pub fn patch(&'a self) -> usize {
104 self.0 .2
105 }
106}