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