1use bumpalo::collections::Vec as BumpVec;
2
3use crate::{
4 arena::Arena,
5 binder::Eval,
6 constant::{Constant, Integer},
7 ledger_value::LedgerValue,
8 term::Term,
9 typ::Type,
10};
11
12use super::{env::Env, runtime::Runtime, MachineError};
13
14#[derive(Debug)]
15pub enum Value<'a, V>
16where
17 V: Eval<'a>,
18{
19 Con(&'a Constant<'a>),
20 Lambda {
21 parameter: &'a V,
22 body: &'a Term<'a, V>,
23 env: &'a Env<'a, V>,
24 },
25 Builtin(&'a Runtime<'a, V>),
26 Delay(&'a Term<'a, V>, &'a Env<'a, V>),
27 Constr(usize, &'a [&'a Value<'a, V>]),
28}
29
30impl<'a, V> Value<'a, V>
31where
32 V: Eval<'a>,
33{
34 pub fn con(arena: &'a Arena, constant: &'a Constant<'a>) -> &'a Value<'a, V> {
35 arena.alloc(Value::Con(constant))
36 }
37
38 pub fn lambda(
39 arena: &'a Arena,
40 parameter: &'a V,
41 body: &'a Term<'a, V>,
42 env: &'a Env<'a, V>,
43 ) -> &'a Value<'a, V> {
44 arena.alloc(Value::Lambda {
45 parameter,
46 body,
47 env,
48 })
49 }
50
51 pub fn delay(arena: &'a Arena, body: &'a Term<'a, V>, env: &'a Env<'a, V>) -> &'a Value<'a, V> {
52 arena.alloc(Value::Delay(body, env))
53 }
54
55 pub fn constr_empty(arena: &'a Arena, tag: usize) -> &'a Value<'a, V> {
56 let empty = BumpVec::new_in(arena.as_bump());
57 let empty = arena.alloc(empty);
58
59 arena.alloc(Value::Constr(tag, empty))
60 }
61
62 pub fn constr(
63 arena: &'a Arena,
64 tag: usize,
65 values: &'a [&'a Value<'a, V>],
66 ) -> &'a Value<'a, V> {
67 arena.alloc(Value::Constr(tag, values))
68 }
69
70 pub fn builtin(arena: &'a Arena, runtime: &'a Runtime<'a, V>) -> &'a Value<'a, V> {
71 arena.alloc(Value::Builtin(runtime))
72 }
73
74 pub fn integer(arena: &'a Arena, i: &'a Integer) -> &'a Value<'a, V> {
75 let con = arena.alloc(Constant::Integer(i));
76
77 Value::con(arena, con)
78 }
79
80 pub fn byte_string(arena: &'a Arena, b: &'a [u8]) -> &'a Value<'a, V> {
81 let con = arena.alloc(Constant::ByteString(b));
82
83 Value::con(arena, con)
84 }
85
86 pub fn string(arena: &'a Arena, s: &'a str) -> &'a Value<'a, V> {
87 let con = arena.alloc(Constant::String(s));
88
89 Value::con(arena, con)
90 }
91
92 pub fn bool(arena: &'a Arena, b: bool) -> &'a Value<'a, V> {
93 let con = arena.alloc(Constant::Boolean(b));
94
95 Value::con(arena, con)
96 }
97
98 pub fn unwrap_integer(&'a self) -> Result<&'a Integer, MachineError<'a, V>> {
99 let inner = self.unwrap_constant()?;
100
101 let Constant::Integer(integer) = inner else {
102 return Err(MachineError::type_mismatch(Type::Integer, inner));
103 };
104
105 Ok(integer)
106 }
107
108 pub fn unwrap_byte_string(&'a self) -> Result<&'a [u8], MachineError<'a, V>> {
109 let inner = self.unwrap_constant()?;
110
111 let Constant::ByteString(byte_string) = inner else {
112 return Err(MachineError::type_mismatch(Type::ByteString, inner));
113 };
114
115 Ok(byte_string)
116 }
117
118 pub fn unwrap_string(&'a self) -> Result<&'a str, MachineError<'a, V>> {
119 let inner = self.unwrap_constant()?;
120
121 let Constant::String(string) = inner else {
122 return Err(MachineError::type_mismatch(Type::String, inner));
123 };
124
125 Ok(string)
126 }
127
128 pub fn unwrap_bool(&'a self) -> Result<bool, MachineError<'a, V>> {
129 let inner = self.unwrap_constant()?;
130
131 let Constant::Boolean(b) = inner else {
132 return Err(MachineError::type_mismatch(Type::Bool, inner));
133 };
134
135 Ok(*b)
136 }
137
138 pub fn unwrap_pair(
139 &'a self,
140 ) -> Result<
141 (
142 &'a Type<'a>,
143 &'a Type<'a>,
144 &'a Constant<'a>,
145 &'a Constant<'a>,
146 ),
147 MachineError<'a, V>,
148 > {
149 let inner = self.unwrap_constant()?;
150
151 let Constant::ProtoPair(t1, t2, first, second) = inner else {
152 return Err(MachineError::expected_pair(inner));
153 };
154
155 Ok((t1, t2, first, second))
156 }
157
158 pub fn unwrap_list(
159 &'a self,
160 ) -> Result<(&'a Type<'a>, &'a [&'a Constant<'a>]), MachineError<'a, V>> {
161 let inner = self.unwrap_constant()?;
162
163 let Constant::ProtoList(t1, list) = inner else {
164 return Err(MachineError::expected_list(inner));
165 };
166
167 Ok((t1, list))
168 }
169
170 pub fn unwrap_array(
171 &'a self,
172 ) -> Result<(&'a Type<'a>, &'a [&'a Constant<'a>]), MachineError<'a, V>> {
173 let inner = self.unwrap_constant()?;
174
175 let Constant::ProtoArray(t1, array) = inner else {
176 return Err(MachineError::expected_array(inner));
177 };
178
179 Ok((t1, array))
180 }
181
182 pub fn unwrap_map(
183 &'a self,
184 ) -> Result<(&'a Type<'a>, &'a [&'a Constant<'a>]), MachineError<'a, V>> {
185 let inner = self.unwrap_constant()?;
186
187 let Constant::ProtoList(t1, list) = inner else {
188 return Err(MachineError::expected_list(inner));
189 };
190
191 Ok((t1, list))
192 }
193
194 pub fn unwrap_constant(&'a self) -> Result<&'a Constant<'a>, MachineError<'a, V>> {
195 let Value::Con(item) = self else {
196 return Err(MachineError::NotAConstant(self));
197 };
198
199 Ok(item)
200 }
201
202 pub fn unwrap_unit(&'a self) -> Result<(), MachineError<'a, V>> {
203 let inner = self.unwrap_constant()?;
204
205 let Constant::Unit = inner else {
206 return Err(MachineError::type_mismatch(Type::Unit, inner));
207 };
208
209 Ok(())
210 }
211
212 pub(super) fn unwrap_int_list(&'a self) -> Result<&'a [&'a Constant<'a>], MachineError<'a, V>> {
213 let inner = self.unwrap_constant()?;
214
215 let Constant::ProtoList(Type::Integer, list) = inner else {
216 return Err(MachineError::type_mismatch(
217 Type::List(&Type::Integer),
218 inner,
219 ));
220 };
221
222 Ok(list)
223 }
224
225 pub fn unwrap_bls12_381_g1_element(&'a self) -> Result<&'a blst::blst_p1, MachineError<'a, V>> {
226 let inner = self.unwrap_constant()?;
227
228 let Constant::Bls12_381G1Element(g1) = inner else {
229 return Err(MachineError::type_mismatch(Type::Bls12_381G1Element, inner));
230 };
231
232 Ok(g1)
233 }
234
235 pub fn unwrap_bls12_381_g2_element(&'a self) -> Result<&'a blst::blst_p2, MachineError<'a, V>> {
236 let inner = self.unwrap_constant()?;
237
238 let Constant::Bls12_381G2Element(g2) = inner else {
239 return Err(MachineError::type_mismatch(Type::Bls12_381G2Element, inner));
240 };
241
242 Ok(g2)
243 }
244
245 pub fn unwrap_bls12_381_ml_result(
246 &'a self,
247 ) -> Result<&'a blst::blst_fp12, MachineError<'a, V>> {
248 let inner = self.unwrap_constant()?;
249
250 let Constant::Bls12_381MlResult(ml_res) = inner else {
251 return Err(MachineError::type_mismatch(Type::Bls12_381MlResult, inner));
252 };
253
254 Ok(ml_res)
255 }
256
257 pub fn unwrap_ledger_value(&'a self) -> Result<&'a LedgerValue<'a>, MachineError<'a, V>> {
258 let inner = self.unwrap_constant()?;
259
260 let Constant::Value(v) = inner else {
261 return Err(MachineError::type_mismatch(Type::Value, inner));
262 };
263
264 Ok(v)
265 }
266}
267
268impl<'a> Constant<'a> {
269 pub fn value<V>(&'a self, arena: &'a Arena) -> &'a Value<'a, V>
270 where
271 V: Eval<'a>,
272 {
273 Value::con(arena, self)
274 }
275}