Skip to main content

amaru_uplc/machine/
value.rs

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}