leo_interpreter/
value.rs

1// Copyright (C) 2019-2025 Provable Inc.
2// This file is part of the Leo library.
3
4// The Leo library is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// The Leo library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
16
17use super::*;
18
19use leo_ast::{IntegerType, Type};
20use leo_span::Symbol;
21
22use snarkvm::prelude::{
23    Address as SvmAddressParam,
24    Boolean as SvmBooleanParam,
25    Cast,
26    Field as SvmFieldParam,
27    FromBits as _,
28    Group as SvmGroupParam,
29    Identifier as SvmIdentifierParam,
30    Literal,
31    Plaintext,
32    Scalar as SvmScalarParam,
33    // Signature as SvmSignatureParam,
34    TestnetV0,
35    ToBits,
36    integers::Integer as SvmIntegerParam,
37};
38
39use indexmap::IndexMap;
40use std::{
41    fmt,
42    hash::{Hash, Hasher},
43    str::FromStr as _,
44};
45
46pub type SvmAddress = SvmAddressParam<TestnetV0>;
47type SvmBoolean = SvmBooleanParam<TestnetV0>;
48type SvmField = SvmFieldParam<TestnetV0>;
49type SvmGroup = SvmGroupParam<TestnetV0>;
50type SvmIdentifier = SvmIdentifierParam<TestnetV0>;
51type SvmInteger<I> = SvmIntegerParam<TestnetV0, I>;
52type SvmScalar = SvmScalarParam<TestnetV0>;
53// type SvmSignature = SvmSignatureParam<TestnetV0>;
54
55#[derive(Clone, Debug, Eq, PartialEq)]
56pub struct StructContents {
57    pub name: Symbol,
58    pub contents: IndexMap<Symbol, Value>,
59}
60
61impl Hash for StructContents {
62    fn hash<H: Hasher>(&self, state: &mut H) {
63        self.name.hash(state);
64        for (_symbol, value) in self.contents.iter() {
65            value.hash(state);
66        }
67    }
68}
69
70#[derive(Clone, Debug, Eq, PartialEq, Hash)]
71pub struct AsyncExecution {
72    pub function: GlobalId,
73    pub arguments: Vec<Value>,
74}
75
76#[derive(Clone, Debug, Default, Eq, PartialEq, Hash)]
77pub struct Future(pub Vec<AsyncExecution>);
78
79impl fmt::Display for Future {
80    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
81        write!(f, "Future")?;
82        if !self.0.is_empty() {
83            write!(f, " with calls to ")?;
84            let mut names = self.0.iter().map(|async_ex| async_ex.function).peekable();
85            while let Some(name) = names.next() {
86                write!(f, "{name}")?;
87                if names.peek().is_some() {
88                    write!(f, ", ")?;
89                }
90            }
91        }
92        Ok(())
93    }
94}
95
96/// A Leo value of any type.
97///
98/// Mappings and functions aren't considered values.
99#[derive(Clone, Debug, Default, Eq, PartialEq, Hash)]
100pub enum Value {
101    #[default]
102    Unit,
103    Bool(bool),
104    U8(u8),
105    U16(u16),
106    U32(u32),
107    U64(u64),
108    U128(u128),
109    I8(i8),
110    I16(i16),
111    I32(i32),
112    I64(i64),
113    I128(i128),
114    Group(SvmGroup),
115    Field(SvmField),
116    Scalar(SvmScalar),
117    Array(Vec<Value>),
118    // Signature(Box<SvmSignature>),
119    Tuple(Vec<Value>),
120    Address(SvmAddress),
121    Future(Future),
122    Struct(StructContents),
123    // String(()),
124}
125
126impl fmt::Display for Value {
127    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
128        use Value::*;
129        match self {
130            Unit => write!(f, "()"),
131
132            Bool(x) => write!(f, "{x}"),
133            U8(x) => write!(f, "{x}u8"),
134            U16(x) => write!(f, "{x}u16"),
135            U32(x) => write!(f, "{x}u32"),
136            U64(x) => write!(f, "{x}u64"),
137            U128(x) => write!(f, "{x}u128"),
138            I8(x) => write!(f, "{x}i8"),
139            I16(x) => write!(f, "{x}i16"),
140            I32(x) => write!(f, "{x}i32"),
141            I64(x) => write!(f, "{x}i64"),
142            I128(x) => write!(f, "{x}i128"),
143            Group(x) => write!(f, "{x}"),
144            Field(x) => write!(f, "{x}"),
145            Scalar(x) => write!(f, "{x}"),
146            Array(x) => {
147                write!(f, "[")?;
148                let mut iter = x.iter().peekable();
149                while let Some(value) = iter.next() {
150                    write!(f, "{value}")?;
151                    if iter.peek().is_some() {
152                        write!(f, ", ")?;
153                    }
154                }
155                write!(f, "]")
156            }
157            Struct(StructContents { name, contents }) => {
158                write!(f, "{name} {{")?;
159                let mut iter = contents.iter().peekable();
160                while let Some((member_name, value)) = iter.next() {
161                    write!(f, "{member_name}: {value}")?;
162                    if iter.peek().is_some() {
163                        write!(f, ", ")?;
164                    }
165                }
166                write!(f, "}}")
167            }
168            Tuple(x) => {
169                write!(f, "(")?;
170                let mut iter = x.iter().peekable();
171                while let Some(value) = iter.next() {
172                    write!(f, "{value}")?;
173                    if iter.peek().is_some() {
174                        write!(f, ", ")?;
175                    }
176                }
177                write!(f, ")")
178            }
179            Address(x) => write!(f, "{x}"),
180            Future(future) => write!(f, "{future}"),
181            // Signature(x) => write!(f, "{x}"),
182            // String(_) => todo!(),
183        }
184    }
185}
186
187impl ToBits for Value {
188    fn write_bits_le(&self, vec: &mut Vec<bool>) {
189        use Value::*;
190
191        let plaintext: Plaintext<TestnetV0> = match self {
192            Bool(x) => Literal::Boolean(SvmBoolean::new(*x)).into(),
193            U8(x) => Literal::U8(SvmInteger::new(*x)).into(),
194            U16(x) => Literal::U16(SvmInteger::new(*x)).into(),
195            U32(x) => Literal::U32(SvmInteger::new(*x)).into(),
196            U64(x) => Literal::U64(SvmInteger::new(*x)).into(),
197            U128(x) => Literal::U128(SvmInteger::new(*x)).into(),
198            I8(x) => Literal::I8(SvmInteger::new(*x)).into(),
199            I16(x) => Literal::I16(SvmInteger::new(*x)).into(),
200            I32(x) => Literal::I32(SvmInteger::new(*x)).into(),
201            I64(x) => Literal::I64(SvmInteger::new(*x)).into(),
202            I128(x) => Literal::I128(SvmInteger::new(*x)).into(),
203            Group(x) => Literal::Group(*x).into(),
204            Field(x) => Literal::Field(*x).into(),
205            Scalar(x) => Literal::Scalar(*x).into(),
206            Address(x) => Literal::Address(*x).into(),
207            Struct(StructContents { name: _, contents }) => {
208                (contents.len() as u8).write_bits_le(vec);
209                for (name, value) in contents.iter() {
210                    let name_s = name.to_string();
211                    let identifier = SvmIdentifier::from_str(&name_s).expect("identifier should parse");
212                    identifier.size_in_bits().write_bits_le(vec);
213                    identifier.write_bits_le(vec);
214                    let value_bits = value.to_bits_le();
215                    (value_bits.len() as u16).write_bits_le(vec);
216                    vec.extend_from_slice(&value_bits);
217                }
218                return;
219            }
220
221            Array(array) => {
222                for element in array.iter() {
223                    let bits = element.to_bits_le();
224                    (bits.len() as u16).write_bits_le(vec);
225                    vec.extend_from_slice(&bits);
226                }
227                return;
228            }
229            _ => tc_fail!(),
230        };
231
232        plaintext.write_bits_le(vec);
233    }
234
235    fn write_bits_be(&self, _vec: &mut Vec<bool>) {
236        todo!()
237    }
238}
239
240impl Value {
241    pub fn to_fields(&self) -> Vec<SvmField> {
242        let mut bits = self.to_bits_le();
243        bits.push(true);
244        bits.chunks(SvmField::SIZE_IN_DATA_BITS)
245            .map(|bits| SvmField::from_bits_le(bits).expect("conversion should work"))
246            .collect()
247    }
248
249    pub fn gte(&self, rhs: &Self) -> Result<bool> {
250        rhs.gt(self).map(|v| !v)
251    }
252
253    pub fn lte(&self, rhs: &Self) -> Result<bool> {
254        rhs.lt(self).map(|v| !v)
255    }
256
257    pub fn lt(&self, rhs: &Self) -> Result<bool> {
258        use Value::*;
259        Ok(match (self, rhs) {
260            (U8(x), U8(y)) => x < y,
261            (U16(x), U16(y)) => x < y,
262            (U32(x), U32(y)) => x < y,
263            (U64(x), U64(y)) => x < y,
264            (U128(x), U128(y)) => x < y,
265            (I8(x), I8(y)) => x < y,
266            (I16(x), I16(y)) => x < y,
267            (I32(x), I32(y)) => x < y,
268            (I64(x), I64(y)) => x < y,
269            (I128(x), I128(y)) => x < y,
270            (Field(x), Field(y)) => x < y,
271            (a, b) => halt_no_span!("Type failure: {a} < {b}"),
272        })
273    }
274
275    pub fn gt(&self, rhs: &Self) -> Result<bool> {
276        use Value::*;
277        Ok(match (self, rhs) {
278            (U8(x), U8(y)) => x > y,
279            (U16(x), U16(y)) => x > y,
280            (U32(x), U32(y)) => x > y,
281            (U64(x), U64(y)) => x > y,
282            (U128(x), U128(y)) => x > y,
283            (I8(x), I8(y)) => x > y,
284            (I16(x), I16(y)) => x > y,
285            (I32(x), I32(y)) => x > y,
286            (I64(x), I64(y)) => x > y,
287            (I128(x), I128(y)) => x > y,
288            (Field(x), Field(y)) => x > y,
289            (a, b) => halt_no_span!("Type failure: {a} > {b}"),
290        })
291    }
292
293    pub fn neq(&self, rhs: &Self) -> Result<bool> {
294        self.eq(rhs).map(|v| !v)
295    }
296
297    /// Are the values equal, according to SnarkVM?
298    ///
299    /// We use this rather than the Eq trait so we can
300    /// fail when comparing values of different types,
301    /// rather than just returning false.
302    pub fn eq(&self, rhs: &Self) -> Result<bool> {
303        use Value::*;
304        Ok(match (self, rhs) {
305            (Unit, Unit) => true,
306            (Bool(x), Bool(y)) => x == y,
307            (U8(x), U8(y)) => x == y,
308            (U16(x), U16(y)) => x == y,
309            (U32(x), U32(y)) => x == y,
310            (U64(x), U64(y)) => x == y,
311            (U128(x), U128(y)) => x == y,
312            (I8(x), I8(y)) => x == y,
313            (I16(x), I16(y)) => x == y,
314            (I32(x), I32(y)) => x == y,
315            (I64(x), I64(y)) => x == y,
316            (I128(x), I128(y)) => x == y,
317            (Field(x), Field(y)) => x == y,
318            (Group(x), Group(y)) => x == y,
319            (Array(x), Array(y)) => {
320                if x.len() != y.len() {
321                    return Ok(false);
322                }
323                for (lhs, rhs) in x.iter().zip(y.iter()) {
324                    match lhs.eq(rhs) {
325                        Ok(true) => {}
326                        Ok(false) => return Ok(false),
327                        Err(e) => return Err(e),
328                    }
329                }
330                true
331            }
332            (a, b) => halt_no_span!("Type failure: {a} == {b}"),
333        })
334    }
335
336    pub fn inc_wrapping(&self) -> Self {
337        match self {
338            Value::U8(x) => Value::U8(x.wrapping_add(1)),
339            Value::U16(x) => Value::U16(x.wrapping_add(1)),
340            Value::U32(x) => Value::U32(x.wrapping_add(1)),
341            Value::U64(x) => Value::U64(x.wrapping_add(1)),
342            Value::U128(x) => Value::U128(x.wrapping_add(1)),
343            Value::I8(x) => Value::I8(x.wrapping_add(1)),
344            Value::I16(x) => Value::I16(x.wrapping_add(1)),
345            Value::I32(x) => Value::I32(x.wrapping_add(1)),
346            Value::I64(x) => Value::I64(x.wrapping_add(1)),
347            Value::I128(x) => Value::I128(x.wrapping_add(1)),
348            _ => tc_fail!(),
349        }
350    }
351
352    /// Return the group generator.
353    pub fn generator() -> Self {
354        Value::Group(SvmGroup::generator())
355    }
356
357    /// Doesn't correspond to Aleo's shl, because it
358    /// does not fail when set bits are shifted out.
359    pub fn simple_shl(&self, shift: u32) -> Self {
360        match self {
361            Value::U8(x) => Value::U8(x << shift),
362            Value::U16(x) => Value::U16(x << shift),
363            Value::U32(x) => Value::U32(x << shift),
364            Value::U64(x) => Value::U64(x << shift),
365            Value::U128(x) => Value::U128(x << shift),
366            Value::I8(x) => Value::I8(x << shift),
367            Value::I16(x) => Value::I16(x << shift),
368            Value::I32(x) => Value::I32(x << shift),
369            Value::I64(x) => Value::I64(x << shift),
370            Value::I128(x) => Value::I128(x << shift),
371            _ => tc_fail!(),
372        }
373    }
374
375    pub fn simple_shr(&self, shift: u32) -> Self {
376        match self {
377            Value::U8(x) => Value::U8(x >> shift),
378            Value::U16(x) => Value::U16(x >> shift),
379            Value::U32(x) => Value::U32(x >> shift),
380            Value::U64(x) => Value::U64(x >> shift),
381            Value::U128(x) => Value::U128(x >> shift),
382            Value::I8(x) => Value::I8(x >> shift),
383            Value::I16(x) => Value::I16(x >> shift),
384            Value::I32(x) => Value::I32(x >> shift),
385            Value::I64(x) => Value::I64(x >> shift),
386            Value::I128(x) => Value::I128(x >> shift),
387            _ => tc_fail!(),
388        }
389    }
390
391    /// Convert to the given type if possible under Aleo casting rules.
392    pub fn cast(&self, cast_type: &Type) -> Option<Value> {
393        match self {
394            Value::Bool(b) => really_cast(SvmBoolean::new(*b), cast_type),
395            Value::U8(x) => really_cast(SvmInteger::new(*x), cast_type),
396            Value::U16(x) => really_cast(SvmInteger::new(*x), cast_type),
397            Value::U32(x) => really_cast(SvmInteger::new(*x), cast_type),
398            Value::U64(x) => really_cast(SvmInteger::new(*x), cast_type),
399            Value::U128(x) => really_cast(SvmInteger::new(*x), cast_type),
400            Value::I8(x) => really_cast(SvmInteger::new(*x), cast_type),
401            Value::I16(x) => really_cast(SvmInteger::new(*x), cast_type),
402            Value::I32(x) => really_cast(SvmInteger::new(*x), cast_type),
403            Value::I64(x) => really_cast(SvmInteger::new(*x), cast_type),
404            Value::I128(x) => really_cast(SvmInteger::new(*x), cast_type),
405            Value::Group(g) => really_cast(g.to_x_coordinate(), cast_type),
406            Value::Field(f) => really_cast(*f, cast_type),
407            Value::Scalar(s) => really_cast(*s, cast_type),
408            Value::Address(a) => really_cast(a.to_group().to_x_coordinate(), cast_type),
409            _ => None,
410        }
411    }
412}
413
414fn really_cast<C>(c: C, cast_type: &Type) -> Option<Value>
415where
416    C: Cast<SvmAddress>
417        + Cast<SvmField>
418        + Cast<SvmAddress>
419        + Cast<SvmGroup>
420        + Cast<SvmBoolean>
421        + Cast<SvmScalar>
422        + Cast<SvmInteger<u8>>
423        + Cast<SvmInteger<u16>>
424        + Cast<SvmInteger<u32>>
425        + Cast<SvmInteger<u64>>
426        + Cast<SvmInteger<u128>>
427        + Cast<SvmInteger<i8>>
428        + Cast<SvmInteger<i16>>
429        + Cast<SvmInteger<i32>>
430        + Cast<SvmInteger<i64>>
431        + Cast<SvmInteger<i128>>,
432{
433    use Type::*;
434
435    let value = match cast_type {
436        Address => Value::Address(c.cast().ok()?),
437        Boolean => Value::Bool({
438            let b: SvmBoolean = c.cast().ok()?;
439            *b
440        }),
441        Field => Value::Field(c.cast().ok()?),
442        Group => Value::Group(c.cast().ok()?),
443        Integer(IntegerType::U8) => Value::U8({
444            let i: SvmInteger<u8> = c.cast().ok()?;
445            *i
446        }),
447        Integer(IntegerType::U16) => Value::U16({
448            let i: SvmInteger<u16> = c.cast().ok()?;
449            *i
450        }),
451        Integer(IntegerType::U32) => Value::U32({
452            let i: SvmInteger<u32> = c.cast().ok()?;
453            *i
454        }),
455        Integer(IntegerType::U64) => Value::U64({
456            let i: SvmInteger<u64> = c.cast().ok()?;
457            *i
458        }),
459        Integer(IntegerType::U128) => Value::U128({
460            let i: SvmInteger<u128> = c.cast().ok()?;
461            *i
462        }),
463        Integer(IntegerType::I8) => Value::I8({
464            let i: SvmInteger<i8> = c.cast().ok()?;
465            *i
466        }),
467        Integer(IntegerType::I16) => Value::I16({
468            let i: SvmInteger<i16> = c.cast().ok()?;
469            *i
470        }),
471        Integer(IntegerType::I32) => Value::I32({
472            let i: SvmInteger<i32> = c.cast().ok()?;
473            *i
474        }),
475        Integer(IntegerType::I64) => Value::I64({
476            let i: SvmInteger<i64> = c.cast().ok()?;
477            *i
478        }),
479        Integer(IntegerType::I128) => Value::I128({
480            let i: SvmInteger<i128> = c.cast().ok()?;
481            *i
482        }),
483        Scalar => Value::Scalar(c.cast().ok()?),
484
485        _ => tc_fail!(),
486    };
487    Some(value)
488}