leo_ast/interpreter_value/
evaluate.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 crate::{
18    BinaryOperation,
19    FromStrRadix as _,
20    IntegerType,
21    Literal,
22    LiteralVariant,
23    Node as _,
24    Type,
25    UnaryOperation,
26    halt,
27    halt_no_span,
28    interpreter_value::{
29        StructContents,
30        SvmAddress,
31        SvmBoolean,
32        SvmField,
33        SvmGroup,
34        SvmIdentifier,
35        SvmInteger,
36        SvmScalar,
37        Value,
38        util::ExpectTc,
39    },
40    tc_fail,
41};
42use leo_errors::{InterpreterHalt, Result};
43use leo_span::Span;
44
45use snarkvm::prelude::{
46    Cast,
47    Double as _,
48    FromBits as _,
49    Inverse as _,
50    Literal as SvmLiteral,
51    Plaintext,
52    Pow as _,
53    ProgramID,
54    Square as _,
55    SquareRoot as _,
56    // Signature as SvmSignatureParam,
57    TestnetV0,
58    ToBits,
59};
60use std::str::FromStr as _;
61
62impl Value {
63    pub fn to_fields(&self) -> Vec<SvmField> {
64        let mut bits = self.to_bits_le();
65        bits.push(true);
66        bits.chunks(SvmField::SIZE_IN_DATA_BITS)
67            .map(|bits| SvmField::from_bits_le(bits).expect("conversion should work"))
68            .collect()
69    }
70
71    pub fn gte(&self, rhs: &Self) -> Result<bool> {
72        rhs.gt(self).map(|v| !v)
73    }
74
75    pub fn lte(&self, rhs: &Self) -> Result<bool> {
76        rhs.lt(self).map(|v| !v)
77    }
78
79    pub fn lt(&self, rhs: &Self) -> Result<bool> {
80        use Value::*;
81        Ok(match (self, rhs) {
82            (U8(x), U8(y)) => x < y,
83            (U16(x), U16(y)) => x < y,
84            (U32(x), U32(y)) => x < y,
85            (U64(x), U64(y)) => x < y,
86            (U128(x), U128(y)) => x < y,
87            (I8(x), I8(y)) => x < y,
88            (I16(x), I16(y)) => x < y,
89            (I32(x), I32(y)) => x < y,
90            (I64(x), I64(y)) => x < y,
91            (I128(x), I128(y)) => x < y,
92            (Field(x), Field(y)) => x < y,
93            (a, b) => halt_no_span!("Type failure: {a} < {b}"),
94        })
95    }
96
97    pub fn gt(&self, rhs: &Self) -> Result<bool> {
98        use Value::*;
99        Ok(match (self, rhs) {
100            (U8(x), U8(y)) => x > y,
101            (U16(x), U16(y)) => x > y,
102            (U32(x), U32(y)) => x > y,
103            (U64(x), U64(y)) => x > y,
104            (U128(x), U128(y)) => x > y,
105            (I8(x), I8(y)) => x > y,
106            (I16(x), I16(y)) => x > y,
107            (I32(x), I32(y)) => x > y,
108            (I64(x), I64(y)) => x > y,
109            (I128(x), I128(y)) => x > y,
110            (Field(x), Field(y)) => x > y,
111            (a, b) => halt_no_span!("Type failure: {a} > {b}"),
112        })
113    }
114
115    pub fn neq(&self, rhs: &Self) -> Result<bool> {
116        self.eq(rhs).map(|v| !v)
117    }
118
119    /// Are the values equal, according to SnarkVM?
120    ///
121    /// We use this rather than the Eq trait so we can
122    /// fail when comparing values of different types,
123    /// rather than just returning false.
124    pub fn eq(&self, rhs: &Self) -> Result<bool> {
125        use Value::*;
126        Ok(match (self, rhs) {
127            (Unit, Unit) => true,
128            (Bool(x), Bool(y)) => x == y,
129            (U8(x), U8(y)) => x == y,
130            (U16(x), U16(y)) => x == y,
131            (U32(x), U32(y)) => x == y,
132            (U64(x), U64(y)) => x == y,
133            (U128(x), U128(y)) => x == y,
134            (I8(x), I8(y)) => x == y,
135            (I16(x), I16(y)) => x == y,
136            (I32(x), I32(y)) => x == y,
137            (I64(x), I64(y)) => x == y,
138            (I128(x), I128(y)) => x == y,
139            (Field(x), Field(y)) => x == y,
140            (Group(x), Group(y)) => x == y,
141            (Array(x), Array(y)) => {
142                if x.len() != y.len() {
143                    return Ok(false);
144                }
145                for (lhs, rhs) in x.iter().zip(y.iter()) {
146                    match lhs.eq(rhs) {
147                        Ok(true) => {}
148                        Ok(false) => return Ok(false),
149                        Err(e) => return Err(e),
150                    }
151                }
152                true
153            }
154            (a, b) => halt_no_span!("Type failure: {a} == {b}"),
155        })
156    }
157
158    pub fn inc_wrapping(&self) -> Self {
159        match self {
160            Value::U8(x) => Value::U8(x.wrapping_add(1)),
161            Value::U16(x) => Value::U16(x.wrapping_add(1)),
162            Value::U32(x) => Value::U32(x.wrapping_add(1)),
163            Value::U64(x) => Value::U64(x.wrapping_add(1)),
164            Value::U128(x) => Value::U128(x.wrapping_add(1)),
165            Value::I8(x) => Value::I8(x.wrapping_add(1)),
166            Value::I16(x) => Value::I16(x.wrapping_add(1)),
167            Value::I32(x) => Value::I32(x.wrapping_add(1)),
168            Value::I64(x) => Value::I64(x.wrapping_add(1)),
169            Value::I128(x) => Value::I128(x.wrapping_add(1)),
170            _ => tc_fail!(),
171        }
172    }
173
174    /// Return the group generator.
175    pub fn generator() -> Self {
176        Value::Group(SvmGroup::generator())
177    }
178
179    /// Doesn't correspond to Aleo's shl, because it
180    /// does not fail when set bits are shifted out.
181    pub fn simple_shl(&self, shift: u32) -> Self {
182        match self {
183            Value::U8(x) => Value::U8(x << shift),
184            Value::U16(x) => Value::U16(x << shift),
185            Value::U32(x) => Value::U32(x << shift),
186            Value::U64(x) => Value::U64(x << shift),
187            Value::U128(x) => Value::U128(x << shift),
188            Value::I8(x) => Value::I8(x << shift),
189            Value::I16(x) => Value::I16(x << shift),
190            Value::I32(x) => Value::I32(x << shift),
191            Value::I64(x) => Value::I64(x << shift),
192            Value::I128(x) => Value::I128(x << shift),
193            _ => tc_fail!(),
194        }
195    }
196
197    pub fn simple_shr(&self, shift: u32) -> Self {
198        match self {
199            Value::U8(x) => Value::U8(x >> shift),
200            Value::U16(x) => Value::U16(x >> shift),
201            Value::U32(x) => Value::U32(x >> shift),
202            Value::U64(x) => Value::U64(x >> shift),
203            Value::U128(x) => Value::U128(x >> shift),
204            Value::I8(x) => Value::I8(x >> shift),
205            Value::I16(x) => Value::I16(x >> shift),
206            Value::I32(x) => Value::I32(x >> shift),
207            Value::I64(x) => Value::I64(x >> shift),
208            Value::I128(x) => Value::I128(x >> shift),
209            _ => tc_fail!(),
210        }
211    }
212
213    /// Convert to the given type if possible under Aleo casting rules.
214    pub fn cast(&self, cast_type: &Type) -> Option<Value> {
215        match self {
216            Value::Bool(b) => really_cast(SvmBoolean::new(*b), cast_type),
217            Value::U8(x) => really_cast(SvmInteger::new(*x), cast_type),
218            Value::U16(x) => really_cast(SvmInteger::new(*x), cast_type),
219            Value::U32(x) => really_cast(SvmInteger::new(*x), cast_type),
220            Value::U64(x) => really_cast(SvmInteger::new(*x), cast_type),
221            Value::U128(x) => really_cast(SvmInteger::new(*x), cast_type),
222            Value::I8(x) => really_cast(SvmInteger::new(*x), cast_type),
223            Value::I16(x) => really_cast(SvmInteger::new(*x), cast_type),
224            Value::I32(x) => really_cast(SvmInteger::new(*x), cast_type),
225            Value::I64(x) => really_cast(SvmInteger::new(*x), cast_type),
226            Value::I128(x) => really_cast(SvmInteger::new(*x), cast_type),
227            Value::Group(g) => really_cast(g.to_x_coordinate(), cast_type),
228            Value::Field(f) => really_cast(*f, cast_type),
229            Value::Scalar(s) => really_cast(*s, cast_type),
230            Value::Address(a) => really_cast(a.to_group().to_x_coordinate(), cast_type),
231            _ => None,
232        }
233    }
234}
235
236impl ToBits for Value {
237    fn write_bits_le(&self, vec: &mut Vec<bool>) {
238        use Value::*;
239
240        let plaintext: Plaintext<TestnetV0> = match self {
241            Bool(x) => SvmLiteral::Boolean(SvmBoolean::new(*x)).into(),
242            U8(x) => SvmLiteral::U8(SvmInteger::new(*x)).into(),
243            U16(x) => SvmLiteral::U16(SvmInteger::new(*x)).into(),
244            U32(x) => SvmLiteral::U32(SvmInteger::new(*x)).into(),
245            U64(x) => SvmLiteral::U64(SvmInteger::new(*x)).into(),
246            U128(x) => SvmLiteral::U128(SvmInteger::new(*x)).into(),
247            I8(x) => SvmLiteral::I8(SvmInteger::new(*x)).into(),
248            I16(x) => SvmLiteral::I16(SvmInteger::new(*x)).into(),
249            I32(x) => SvmLiteral::I32(SvmInteger::new(*x)).into(),
250            I64(x) => SvmLiteral::I64(SvmInteger::new(*x)).into(),
251            I128(x) => SvmLiteral::I128(SvmInteger::new(*x)).into(),
252            Group(x) => SvmLiteral::Group(*x).into(),
253            Field(x) => SvmLiteral::Field(*x).into(),
254            Scalar(x) => SvmLiteral::Scalar(*x).into(),
255            Address(x) => SvmLiteral::Address(*x).into(),
256            Struct(StructContents { name: _, contents }) => {
257                (contents.len() as u8).write_bits_le(vec);
258                for (name, value) in contents.iter() {
259                    let name_s = name.to_string();
260                    let identifier = SvmIdentifier::from_str(&name_s).expect("identifier should parse");
261                    identifier.size_in_bits().write_bits_le(vec);
262                    identifier.write_bits_le(vec);
263                    let value_bits = value.to_bits_le();
264                    (value_bits.len() as u16).write_bits_le(vec);
265                    vec.extend_from_slice(&value_bits);
266                }
267                return;
268            }
269
270            Array(array) => {
271                for element in array.iter() {
272                    let bits = element.to_bits_le();
273                    (bits.len() as u16).write_bits_le(vec);
274                    vec.extend_from_slice(&bits);
275                }
276                return;
277            }
278            _ => tc_fail!(),
279        };
280
281        plaintext.write_bits_le(vec);
282    }
283
284    fn write_bits_be(&self, _vec: &mut Vec<bool>) {
285        todo!()
286    }
287}
288
289pub fn literal_to_value(literal: &Literal, ty: &Option<Type>) -> Result<Value> {
290    // SnarkVM will not parse fields, groups, or scalars with
291    // leading zeros, so we strip them out.
292    fn prepare_snarkvm_string(s: &str, suffix: &str) -> String {
293        // If there's a `-`, separate it from the rest of the string.
294        let (neg, rest) = s.strip_prefix("-").map(|rest| ("-", rest)).unwrap_or(("", s));
295        // Remove leading zeros.
296        let mut rest = rest.trim_start_matches('0');
297        if rest.is_empty() {
298            rest = "0";
299        }
300        format!("{neg}{rest}{suffix}")
301    }
302
303    let value = match &literal.variant {
304        LiteralVariant::Boolean(b) => Value::Bool(*b),
305        LiteralVariant::Integer(IntegerType::U8, s, ..) => {
306            let s = s.replace("_", "");
307            Value::U8(u8::from_str_by_radix(&s).expect("Parsing guarantees this works."))
308        }
309        LiteralVariant::Integer(IntegerType::U16, s, ..) => {
310            let s = s.replace("_", "");
311            Value::U16(u16::from_str_by_radix(&s).expect("Parsing guarantees this works."))
312        }
313        LiteralVariant::Integer(IntegerType::U32, s, ..) => {
314            let s = s.replace("_", "");
315            Value::U32(u32::from_str_by_radix(&s).expect("Parsing guarantees this works."))
316        }
317        LiteralVariant::Integer(IntegerType::U64, s, ..) => {
318            let s = s.replace("_", "");
319            Value::U64(u64::from_str_by_radix(&s).expect("Parsing guarantees this works."))
320        }
321        LiteralVariant::Integer(IntegerType::U128, s, ..) => {
322            let s = s.replace("_", "");
323            Value::U128(u128::from_str_by_radix(&s).expect("Parsing guarantees this works."))
324        }
325        LiteralVariant::Integer(IntegerType::I8, s, ..) => {
326            let s = s.replace("_", "");
327            Value::I8(i8::from_str_by_radix(&s).expect("Parsing guarantees this works."))
328        }
329        LiteralVariant::Integer(IntegerType::I16, s, ..) => {
330            let s = s.replace("_", "");
331            Value::I16(i16::from_str_by_radix(&s).expect("Parsing guarantees this works."))
332        }
333        LiteralVariant::Integer(IntegerType::I32, s, ..) => {
334            let s = s.replace("_", "");
335            Value::I32(i32::from_str_by_radix(&s).expect("Parsing guarantees this works."))
336        }
337        LiteralVariant::Integer(IntegerType::I64, s, ..) => {
338            let s = s.replace("_", "");
339            Value::I64(i64::from_str_by_radix(&s).expect("Parsing guarantees this works."))
340        }
341        LiteralVariant::Integer(IntegerType::I128, s, ..) => {
342            let s = s.replace("_", "");
343            Value::I128(i128::from_str_by_radix(&s).expect("Parsing guarantees this works."))
344        }
345        LiteralVariant::Field(s) => Value::Field(prepare_snarkvm_string(s, "field").parse().expect_tc(literal.span())?),
346        LiteralVariant::Group(s) => Value::Group(prepare_snarkvm_string(s, "group").parse().expect_tc(literal.span())?),
347        LiteralVariant::Address(s) => {
348            if s.ends_with(".aleo") {
349                let program_id = ProgramID::from_str(s)?;
350                Value::Address(program_id.to_address()?)
351            } else {
352                Value::Address(s.parse().expect_tc(literal.span())?)
353            }
354        }
355        LiteralVariant::Scalar(s) => {
356            Value::Scalar(prepare_snarkvm_string(s, "scalar").parse().expect_tc(literal.span())?)
357        }
358        LiteralVariant::Unsuffixed(s) => match ty {
359            Some(Type::Integer(IntegerType::U8)) => {
360                let s = s.replace("_", "");
361                Value::U8(u8::from_str_by_radix(&s).expect("Parsing guarantees this works."))
362            }
363            Some(Type::Integer(IntegerType::U16)) => {
364                let s = s.replace("_", "");
365                Value::U16(u16::from_str_by_radix(&s).expect("Parsing guarantees this works."))
366            }
367            Some(Type::Integer(IntegerType::U32)) => {
368                let s = s.replace("_", "");
369                Value::U32(u32::from_str_by_radix(&s).expect("Parsing guarantees this works."))
370            }
371            Some(Type::Integer(IntegerType::U64)) => {
372                let s = s.replace("_", "");
373                Value::U64(u64::from_str_by_radix(&s).expect("Parsing guarantees this works."))
374            }
375            Some(Type::Integer(IntegerType::U128)) => {
376                let s = s.replace("_", "");
377                Value::U128(u128::from_str_by_radix(&s).expect("Parsing guarantees this works."))
378            }
379            Some(Type::Integer(IntegerType::I8)) => {
380                let s = s.replace("_", "");
381                Value::I8(i8::from_str_by_radix(&s).expect("Parsing guarantees this works."))
382            }
383            Some(Type::Integer(IntegerType::I16)) => {
384                let s = s.replace("_", "");
385                Value::I16(i16::from_str_by_radix(&s).expect("Parsing guarantees this works."))
386            }
387            Some(Type::Integer(IntegerType::I32)) => {
388                let s = s.replace("_", "");
389                Value::I32(i32::from_str_by_radix(&s).expect("Parsing guarantees this works."))
390            }
391            Some(Type::Integer(IntegerType::I64)) => {
392                let s = s.replace("_", "");
393                Value::I64(i64::from_str_by_radix(&s).expect("Parsing guarantees this works."))
394            }
395            Some(Type::Integer(IntegerType::I128)) => {
396                let s = s.replace("_", "");
397                Value::I128(i128::from_str_by_radix(&s).expect("Parsing guarantees this works."))
398            }
399            Some(Type::Field) => Value::Field(prepare_snarkvm_string(s, "field").parse().expect_tc(literal.span())?),
400            Some(Type::Group) => Value::Group(prepare_snarkvm_string(s, "group").parse().expect_tc(literal.span())?),
401            Some(Type::Scalar) => Value::Scalar(prepare_snarkvm_string(s, "scalar").parse().expect_tc(literal.span())?),
402            _ => {
403                halt!(literal.span(), "cannot infer type of unsuffixed literal")
404            }
405        },
406        LiteralVariant::String(..) => tc_fail!(),
407    };
408
409    Ok(value)
410}
411
412/// Evaluate a unary operation.
413pub fn evaluate_unary(span: Span, op: UnaryOperation, value: &Value) -> Result<Value> {
414    let value_result = match op {
415        UnaryOperation::Abs => match value {
416            Value::I8(x) => {
417                if *x == i8::MIN {
418                    halt!(span, "abs overflow");
419                } else {
420                    Value::I8(x.abs())
421                }
422            }
423            Value::I16(x) => {
424                if *x == i16::MIN {
425                    halt!(span, "abs overflow");
426                } else {
427                    Value::I16(x.abs())
428                }
429            }
430            Value::I32(x) => {
431                if *x == i32::MIN {
432                    halt!(span, "abs overflow");
433                } else {
434                    Value::I32(x.abs())
435                }
436            }
437            Value::I64(x) => {
438                if *x == i64::MIN {
439                    halt!(span, "abs overflow");
440                } else {
441                    Value::I64(x.abs())
442                }
443            }
444            Value::I128(x) => {
445                if *x == i128::MIN {
446                    halt!(span, "abs overflow");
447                } else {
448                    Value::I128(x.abs())
449                }
450            }
451            _ => halt!(span, "Type error"),
452        },
453        UnaryOperation::AbsWrapped => match value {
454            Value::I8(x) => Value::I8(x.unsigned_abs() as i8),
455            Value::I16(x) => Value::I16(x.unsigned_abs() as i16),
456            Value::I32(x) => Value::I32(x.unsigned_abs() as i32),
457            Value::I64(x) => Value::I64(x.unsigned_abs() as i64),
458            Value::I128(x) => Value::I128(x.unsigned_abs() as i128),
459            _ => halt!(span, "Type error"),
460        },
461        UnaryOperation::Double => match value {
462            Value::Field(x) => Value::Field(x.double()),
463            Value::Group(x) => Value::Group(x.double()),
464            _ => halt!(span, "Type error"),
465        },
466        UnaryOperation::Inverse => match value {
467            Value::Field(x) => {
468                let Ok(y) = x.inverse() else {
469                    halt!(span, "attempt to invert 0field");
470                };
471                Value::Field(y)
472            }
473            _ => halt!(span, "Can only invert fields"),
474        },
475        UnaryOperation::Negate => match value {
476            Value::I8(x) => match x.checked_neg() {
477                None => halt!(span, "negation overflow"),
478                Some(y) => Value::I8(y),
479            },
480            Value::I16(x) => match x.checked_neg() {
481                None => halt!(span, "negation overflow"),
482                Some(y) => Value::I16(y),
483            },
484            Value::I32(x) => match x.checked_neg() {
485                None => halt!(span, "negation overflow"),
486                Some(y) => Value::I32(y),
487            },
488            Value::I64(x) => match x.checked_neg() {
489                None => halt!(span, "negation overflow"),
490                Some(y) => Value::I64(y),
491            },
492            Value::I128(x) => match x.checked_neg() {
493                None => halt!(span, "negation overflow"),
494                Some(y) => Value::I128(y),
495            },
496            Value::Group(x) => Value::Group(-*x),
497            Value::Field(x) => Value::Field(-*x),
498            _ => halt!(span, "Type error"),
499        },
500        UnaryOperation::Not => match value {
501            Value::Bool(x) => Value::Bool(!x),
502            Value::U8(x) => Value::U8(!x),
503            Value::U16(x) => Value::U16(!x),
504            Value::U32(x) => Value::U32(!x),
505            Value::U64(x) => Value::U64(!x),
506            Value::U128(x) => Value::U128(!x),
507            Value::I8(x) => Value::I8(!x),
508            Value::I16(x) => Value::I16(!x),
509            Value::I32(x) => Value::I32(!x),
510            Value::I64(x) => Value::I64(!x),
511            Value::I128(x) => Value::I128(!x),
512            _ => halt!(span, "Type error"),
513        },
514        UnaryOperation::Square => match value {
515            Value::Field(x) => Value::Field(x.square()),
516            _ => halt!(span, "Can only square fields"),
517        },
518        UnaryOperation::SquareRoot => match value {
519            Value::Field(x) => {
520                let Ok(y) = x.square_root() else {
521                    halt!(span, "square root failure");
522                };
523                Value::Field(y)
524            }
525            _ => halt!(span, "Can only apply square_root to fields"),
526        },
527        UnaryOperation::ToXCoordinate => match value {
528            Value::Group(x) => Value::Field(x.to_x_coordinate()),
529            _ => tc_fail!(),
530        },
531        UnaryOperation::ToYCoordinate => match value {
532            Value::Group(x) => Value::Field(x.to_y_coordinate()),
533            _ => tc_fail!(),
534        },
535    };
536
537    Ok(value_result)
538}
539
540/// Evaluate a binary operation.
541pub fn evaluate_binary(span: Span, op: BinaryOperation, lhs: &Value, rhs: &Value) -> Result<Value> {
542    let value = match op {
543        BinaryOperation::Add => {
544            let Some(value) = (match (lhs, rhs) {
545                (Value::U8(x), Value::U8(y)) => x.checked_add(*y).map(Value::U8),
546                (Value::U16(x), Value::U16(y)) => x.checked_add(*y).map(Value::U16),
547                (Value::U32(x), Value::U32(y)) => x.checked_add(*y).map(Value::U32),
548                (Value::U64(x), Value::U64(y)) => x.checked_add(*y).map(Value::U64),
549                (Value::U128(x), Value::U128(y)) => x.checked_add(*y).map(Value::U128),
550                (Value::I8(x), Value::I8(y)) => x.checked_add(*y).map(Value::I8),
551                (Value::I16(x), Value::I16(y)) => x.checked_add(*y).map(Value::I16),
552                (Value::I32(x), Value::I32(y)) => x.checked_add(*y).map(Value::I32),
553                (Value::I64(x), Value::I64(y)) => x.checked_add(*y).map(Value::I64),
554                (Value::I128(x), Value::I128(y)) => x.checked_add(*y).map(Value::I128),
555                (Value::Group(x), Value::Group(y)) => Some(Value::Group(*x + *y)),
556                (Value::Field(x), Value::Field(y)) => Some(Value::Field(*x + *y)),
557                (Value::Scalar(x), Value::Scalar(y)) => Some(Value::Scalar(*x + *y)),
558                _ => halt!(span, "Type error"),
559            }) else {
560                halt!(span, "add overflow");
561            };
562            value
563        }
564        BinaryOperation::AddWrapped => match (lhs, rhs) {
565            (Value::U8(x), Value::U8(y)) => Value::U8(x.wrapping_add(*y)),
566            (Value::U16(x), Value::U16(y)) => Value::U16(x.wrapping_add(*y)),
567            (Value::U32(x), Value::U32(y)) => Value::U32(x.wrapping_add(*y)),
568            (Value::U64(x), Value::U64(y)) => Value::U64(x.wrapping_add(*y)),
569            (Value::U128(x), Value::U128(y)) => Value::U128(x.wrapping_add(*y)),
570            (Value::I8(x), Value::I8(y)) => Value::I8(x.wrapping_add(*y)),
571            (Value::I16(x), Value::I16(y)) => Value::I16(x.wrapping_add(*y)),
572            (Value::I32(x), Value::I32(y)) => Value::I32(x.wrapping_add(*y)),
573            (Value::I64(x), Value::I64(y)) => Value::I64(x.wrapping_add(*y)),
574            (Value::I128(x), Value::I128(y)) => Value::I128(x.wrapping_add(*y)),
575            _ => halt!(span, "Type error"),
576        },
577        BinaryOperation::And => match (lhs, rhs) {
578            (Value::Bool(x), Value::Bool(y)) => Value::Bool(*x && *y),
579            _ => halt!(span, "Type error"),
580        },
581        BinaryOperation::BitwiseAnd => match (lhs, rhs) {
582            (Value::Bool(x), Value::Bool(y)) => Value::Bool(x & y),
583            (Value::U8(x), Value::U8(y)) => Value::U8(x & y),
584            (Value::U16(x), Value::U16(y)) => Value::U16(x & y),
585            (Value::U32(x), Value::U32(y)) => Value::U32(x & y),
586            (Value::U64(x), Value::U64(y)) => Value::U64(x & y),
587            (Value::U128(x), Value::U128(y)) => Value::U128(x & y),
588            (Value::I8(x), Value::I8(y)) => Value::I8(x & y),
589            (Value::I16(x), Value::I16(y)) => Value::I16(x & y),
590            (Value::I32(x), Value::I32(y)) => Value::I32(x & y),
591            (Value::I64(x), Value::I64(y)) => Value::I64(x & y),
592            (Value::I128(x), Value::I128(y)) => Value::I128(x & y),
593            _ => halt!(span, "Type error"),
594        },
595        BinaryOperation::Div => {
596            let Some(value) = (match (lhs, rhs) {
597                (Value::U8(x), Value::U8(y)) => x.checked_div(*y).map(Value::U8),
598                (Value::U16(x), Value::U16(y)) => x.checked_div(*y).map(Value::U16),
599                (Value::U32(x), Value::U32(y)) => x.checked_div(*y).map(Value::U32),
600                (Value::U64(x), Value::U64(y)) => x.checked_div(*y).map(Value::U64),
601                (Value::U128(x), Value::U128(y)) => x.checked_div(*y).map(Value::U128),
602                (Value::I8(x), Value::I8(y)) => x.checked_div(*y).map(Value::I8),
603                (Value::I16(x), Value::I16(y)) => x.checked_div(*y).map(Value::I16),
604                (Value::I32(x), Value::I32(y)) => x.checked_div(*y).map(Value::I32),
605                (Value::I64(x), Value::I64(y)) => x.checked_div(*y).map(Value::I64),
606                (Value::I128(x), Value::I128(y)) => x.checked_div(*y).map(Value::I128),
607                (Value::Field(x), Value::Field(y)) => y.inverse().map(|y| Value::Field(*x * y)).ok(),
608                _ => halt!(span, "Type error"),
609            }) else {
610                halt!(span, "div overflow");
611            };
612            value
613        }
614        BinaryOperation::DivWrapped => match (lhs, rhs) {
615            (Value::U8(_), Value::U8(0))
616            | (Value::U16(_), Value::U16(0))
617            | (Value::U32(_), Value::U32(0))
618            | (Value::U64(_), Value::U64(0))
619            | (Value::U128(_), Value::U128(0))
620            | (Value::I8(_), Value::I8(0))
621            | (Value::I16(_), Value::I16(0))
622            | (Value::I32(_), Value::I32(0))
623            | (Value::I64(_), Value::I64(0))
624            | (Value::I128(_), Value::I128(0)) => halt!(span, "divide by 0"),
625            (Value::U8(x), Value::U8(y)) => Value::U8(x.wrapping_div(*y)),
626            (Value::U16(x), Value::U16(y)) => Value::U16(x.wrapping_div(*y)),
627            (Value::U32(x), Value::U32(y)) => Value::U32(x.wrapping_div(*y)),
628            (Value::U64(x), Value::U64(y)) => Value::U64(x.wrapping_div(*y)),
629            (Value::U128(x), Value::U128(y)) => Value::U128(x.wrapping_div(*y)),
630            (Value::I8(x), Value::I8(y)) => Value::I8(x.wrapping_div(*y)),
631            (Value::I16(x), Value::I16(y)) => Value::I16(x.wrapping_div(*y)),
632            (Value::I32(x), Value::I32(y)) => Value::I32(x.wrapping_div(*y)),
633            (Value::I64(x), Value::I64(y)) => Value::I64(x.wrapping_div(*y)),
634            (Value::I128(x), Value::I128(y)) => Value::I128(x.wrapping_div(*y)),
635            _ => halt!(span, "Type error"),
636        },
637        BinaryOperation::Eq => Value::Bool(lhs.eq(rhs)?),
638        BinaryOperation::Gte => Value::Bool(lhs.gte(rhs)?),
639        BinaryOperation::Gt => Value::Bool(lhs.gt(rhs)?),
640        BinaryOperation::Lte => Value::Bool(lhs.lte(rhs)?),
641        BinaryOperation::Lt => Value::Bool(lhs.lt(rhs)?),
642        BinaryOperation::Mod => {
643            let Some(value) = (match (lhs, rhs) {
644                (Value::U8(x), Value::U8(y)) => x.checked_rem(*y).map(Value::U8),
645                (Value::U16(x), Value::U16(y)) => x.checked_rem(*y).map(Value::U16),
646                (Value::U32(x), Value::U32(y)) => x.checked_rem(*y).map(Value::U32),
647                (Value::U64(x), Value::U64(y)) => x.checked_rem(*y).map(Value::U64),
648                (Value::U128(x), Value::U128(y)) => x.checked_rem(*y).map(Value::U128),
649                (Value::I8(x), Value::I8(y)) => x.checked_rem(*y).map(Value::I8),
650                (Value::I16(x), Value::I16(y)) => x.checked_rem(*y).map(Value::I16),
651                (Value::I32(x), Value::I32(y)) => x.checked_rem(*y).map(Value::I32),
652                (Value::I64(x), Value::I64(y)) => x.checked_rem(*y).map(Value::I64),
653                (Value::I128(x), Value::I128(y)) => x.checked_rem(*y).map(Value::I128),
654                _ => halt!(span, "Type error"),
655            }) else {
656                halt!(span, "mod overflow");
657            };
658            value
659        }
660        BinaryOperation::Mul => {
661            let Some(value) = (match (lhs, rhs) {
662                (Value::U8(x), Value::U8(y)) => x.checked_mul(*y).map(Value::U8),
663                (Value::U16(x), Value::U16(y)) => x.checked_mul(*y).map(Value::U16),
664                (Value::U32(x), Value::U32(y)) => x.checked_mul(*y).map(Value::U32),
665                (Value::U64(x), Value::U64(y)) => x.checked_mul(*y).map(Value::U64),
666                (Value::U128(x), Value::U128(y)) => x.checked_mul(*y).map(Value::U128),
667                (Value::I8(x), Value::I8(y)) => x.checked_mul(*y).map(Value::I8),
668                (Value::I16(x), Value::I16(y)) => x.checked_mul(*y).map(Value::I16),
669                (Value::I32(x), Value::I32(y)) => x.checked_mul(*y).map(Value::I32),
670                (Value::I64(x), Value::I64(y)) => x.checked_mul(*y).map(Value::I64),
671                (Value::I128(x), Value::I128(y)) => x.checked_mul(*y).map(Value::I128),
672                (Value::Field(x), Value::Field(y)) => Some(Value::Field(*x * *y)),
673                (Value::Group(x), Value::Scalar(y)) => Some(Value::Group(*x * *y)),
674                (Value::Scalar(x), Value::Group(y)) => Some(Value::Group(*x * *y)),
675                _ => halt!(span, "Type error"),
676            }) else {
677                halt!(span, "mul overflow");
678            };
679            value
680        }
681        BinaryOperation::MulWrapped => match (lhs, rhs) {
682            (Value::U8(x), Value::U8(y)) => Value::U8(x.wrapping_mul(*y)),
683            (Value::U16(x), Value::U16(y)) => Value::U16(x.wrapping_mul(*y)),
684            (Value::U32(x), Value::U32(y)) => Value::U32(x.wrapping_mul(*y)),
685            (Value::U64(x), Value::U64(y)) => Value::U64(x.wrapping_mul(*y)),
686            (Value::U128(x), Value::U128(y)) => Value::U128(x.wrapping_mul(*y)),
687            (Value::I8(x), Value::I8(y)) => Value::I8(x.wrapping_mul(*y)),
688            (Value::I16(x), Value::I16(y)) => Value::I16(x.wrapping_mul(*y)),
689            (Value::I32(x), Value::I32(y)) => Value::I32(x.wrapping_mul(*y)),
690            (Value::I64(x), Value::I64(y)) => Value::I64(x.wrapping_mul(*y)),
691            (Value::I128(x), Value::I128(y)) => Value::I128(x.wrapping_mul(*y)),
692            _ => halt!(span, "Type error"),
693        },
694
695        BinaryOperation::Nand => match (lhs, rhs) {
696            (Value::Bool(x), Value::Bool(y)) => Value::Bool(!(x & y)),
697            _ => halt!(span, "Type error"),
698        },
699        BinaryOperation::Neq => Value::Bool(lhs.neq(rhs)?),
700        BinaryOperation::Nor => match (lhs, rhs) {
701            (Value::Bool(x), Value::Bool(y)) => Value::Bool(!(x | y)),
702            _ => halt!(span, "Type error"),
703        },
704        BinaryOperation::Or => match (lhs, rhs) {
705            (Value::Bool(x), Value::Bool(y)) => Value::Bool(x | y),
706            _ => halt!(span, "Type error"),
707        },
708        BinaryOperation::BitwiseOr => match (lhs, rhs) {
709            (Value::Bool(x), Value::Bool(y)) => Value::Bool(x | y),
710            (Value::U8(x), Value::U8(y)) => Value::U8(x | y),
711            (Value::U16(x), Value::U16(y)) => Value::U16(x | y),
712            (Value::U32(x), Value::U32(y)) => Value::U32(x | y),
713            (Value::U64(x), Value::U64(y)) => Value::U64(x | y),
714            (Value::U128(x), Value::U128(y)) => Value::U128(x | y),
715            (Value::I8(x), Value::I8(y)) => Value::I8(x | y),
716            (Value::I16(x), Value::I16(y)) => Value::I16(x | y),
717            (Value::I32(x), Value::I32(y)) => Value::I32(x | y),
718            (Value::I64(x), Value::I64(y)) => Value::I64(x | y),
719            (Value::I128(x), Value::I128(y)) => Value::I128(x | y),
720            _ => halt!(span, "Type error"),
721        },
722        BinaryOperation::Pow => {
723            if let (Value::Field(x), Value::Field(y)) = (&lhs, &rhs) {
724                Value::Field(x.pow(y))
725            } else {
726                let rhs: u32 = match rhs {
727                    Value::U8(y) => (*y).into(),
728                    Value::U16(y) => (*y).into(),
729                    Value::U32(y) => *y,
730                    _ => tc_fail!(),
731                };
732
733                let Some(value) = (match lhs {
734                    Value::U8(x) => x.checked_pow(rhs).map(Value::U8),
735                    Value::U16(x) => x.checked_pow(rhs).map(Value::U16),
736                    Value::U32(x) => x.checked_pow(rhs).map(Value::U32),
737                    Value::U64(x) => x.checked_pow(rhs).map(Value::U64),
738                    Value::U128(x) => x.checked_pow(rhs).map(Value::U128),
739                    Value::I8(x) => x.checked_pow(rhs).map(Value::I8),
740                    Value::I16(x) => x.checked_pow(rhs).map(Value::I16),
741                    Value::I32(x) => x.checked_pow(rhs).map(Value::I32),
742                    Value::I64(x) => x.checked_pow(rhs).map(Value::I64),
743                    Value::I128(x) => x.checked_pow(rhs).map(Value::I128),
744                    _ => halt!(span, "Type error"),
745                }) else {
746                    halt!(span, "pow overflow");
747                };
748                value
749            }
750        }
751        BinaryOperation::PowWrapped => {
752            let rhs: u32 = match rhs {
753                Value::U8(y) => (*y).into(),
754                Value::U16(y) => (*y).into(),
755                Value::U32(y) => *y,
756                _ => halt!(span, "Type error"),
757            };
758
759            match lhs {
760                Value::U8(x) => Value::U8(x.wrapping_pow(rhs)),
761                Value::U16(x) => Value::U16(x.wrapping_pow(rhs)),
762                Value::U32(x) => Value::U32(x.wrapping_pow(rhs)),
763                Value::U64(x) => Value::U64(x.wrapping_pow(rhs)),
764                Value::U128(x) => Value::U128(x.wrapping_pow(rhs)),
765                Value::I8(x) => Value::I8(x.wrapping_pow(rhs)),
766                Value::I16(x) => Value::I16(x.wrapping_pow(rhs)),
767                Value::I32(x) => Value::I32(x.wrapping_pow(rhs)),
768                Value::I64(x) => Value::I64(x.wrapping_pow(rhs)),
769                Value::I128(x) => Value::I128(x.wrapping_pow(rhs)),
770                _ => halt!(span, "Type error"),
771            }
772        }
773        BinaryOperation::Rem => {
774            let Some(value) = (match (lhs, rhs) {
775                (Value::U8(x), Value::U8(y)) => x.checked_rem(*y).map(Value::U8),
776                (Value::U16(x), Value::U16(y)) => x.checked_rem(*y).map(Value::U16),
777                (Value::U32(x), Value::U32(y)) => x.checked_rem(*y).map(Value::U32),
778                (Value::U64(x), Value::U64(y)) => x.checked_rem(*y).map(Value::U64),
779                (Value::U128(x), Value::U128(y)) => x.checked_rem(*y).map(Value::U128),
780                (Value::I8(x), Value::I8(y)) => x.checked_rem(*y).map(Value::I8),
781                (Value::I16(x), Value::I16(y)) => x.checked_rem(*y).map(Value::I16),
782                (Value::I32(x), Value::I32(y)) => x.checked_rem(*y).map(Value::I32),
783                (Value::I64(x), Value::I64(y)) => x.checked_rem(*y).map(Value::I64),
784                (Value::I128(x), Value::I128(y)) => x.checked_rem(*y).map(Value::I128),
785                _ => halt!(span, "Type error"),
786            }) else {
787                halt!(span, "rem error");
788            };
789            value
790        }
791        BinaryOperation::RemWrapped => match (lhs, rhs) {
792            (Value::U8(_), Value::U8(0))
793            | (Value::U16(_), Value::U16(0))
794            | (Value::U32(_), Value::U32(0))
795            | (Value::U64(_), Value::U64(0))
796            | (Value::U128(_), Value::U128(0))
797            | (Value::I8(_), Value::I8(0))
798            | (Value::I16(_), Value::I16(0))
799            | (Value::I32(_), Value::I32(0))
800            | (Value::I64(_), Value::I64(0))
801            | (Value::I128(_), Value::I128(0)) => halt!(span, "rem by 0"),
802            (Value::U8(x), Value::U8(y)) => Value::U8(x.wrapping_rem(*y)),
803            (Value::U16(x), Value::U16(y)) => Value::U16(x.wrapping_rem(*y)),
804            (Value::U32(x), Value::U32(y)) => Value::U32(x.wrapping_rem(*y)),
805            (Value::U64(x), Value::U64(y)) => Value::U64(x.wrapping_rem(*y)),
806            (Value::U128(x), Value::U128(y)) => Value::U128(x.wrapping_rem(*y)),
807            (Value::I8(x), Value::I8(y)) => Value::I8(x.wrapping_rem(*y)),
808            (Value::I16(x), Value::I16(y)) => Value::I16(x.wrapping_rem(*y)),
809            (Value::I32(x), Value::I32(y)) => Value::I32(x.wrapping_rem(*y)),
810            (Value::I64(x), Value::I64(y)) => Value::I64(x.wrapping_rem(*y)),
811            (Value::I128(x), Value::I128(y)) => Value::I128(x.wrapping_rem(*y)),
812            _ => halt!(span, "Type error"),
813        },
814        BinaryOperation::Shl => {
815            let rhs: u32 = match rhs {
816                Value::U8(y) => (*y).into(),
817                Value::U16(y) => (*y).into(),
818                Value::U32(y) => *y,
819                _ => halt!(span, "Type error"),
820            };
821            match lhs {
822                Value::U8(_) | Value::I8(_) if rhs >= 8 => halt!(span, "shl overflow"),
823                Value::U16(_) | Value::I16(_) if rhs >= 16 => halt!(span, "shl overflow"),
824                Value::U32(_) | Value::I32(_) if rhs >= 32 => halt!(span, "shl overflow"),
825                Value::U64(_) | Value::I64(_) if rhs >= 64 => halt!(span, "shl overflow"),
826                Value::U128(_) | Value::I128(_) if rhs >= 128 => halt!(span, "shl overflow"),
827                _ => {}
828            }
829
830            // Aleo's shl halts if set bits are shifted out.
831            let shifted = lhs.simple_shl(rhs);
832            let reshifted = shifted.simple_shr(rhs);
833            if lhs.eq(&reshifted)? {
834                shifted
835            } else {
836                halt!(span, "shl overflow");
837            }
838        }
839
840        BinaryOperation::ShlWrapped => {
841            let rhs: u32 = match rhs {
842                Value::U8(y) => (*y).into(),
843                Value::U16(y) => (*y).into(),
844                Value::U32(y) => *y,
845                _ => halt!(span, "Type error"),
846            };
847            match lhs {
848                Value::U8(x) => Value::U8(x.wrapping_shl(rhs)),
849                Value::U16(x) => Value::U16(x.wrapping_shl(rhs)),
850                Value::U32(x) => Value::U32(x.wrapping_shl(rhs)),
851                Value::U64(x) => Value::U64(x.wrapping_shl(rhs)),
852                Value::U128(x) => Value::U128(x.wrapping_shl(rhs)),
853                Value::I8(x) => Value::I8(x.wrapping_shl(rhs)),
854                Value::I16(x) => Value::I16(x.wrapping_shl(rhs)),
855                Value::I32(x) => Value::I32(x.wrapping_shl(rhs)),
856                Value::I64(x) => Value::I64(x.wrapping_shl(rhs)),
857                Value::I128(x) => Value::I128(x.wrapping_shl(rhs)),
858                _ => halt!(span, "Type error"),
859            }
860        }
861
862        BinaryOperation::Shr => {
863            let rhs: u32 = match rhs {
864                Value::U8(y) => (*y).into(),
865                Value::U16(y) => (*y).into(),
866                Value::U32(y) => *y,
867                _ => halt!(span, "Type error"),
868            };
869
870            match lhs {
871                Value::U8(_) | Value::I8(_) if rhs >= 8 => halt!(span, "shr overflow"),
872                Value::U16(_) | Value::I16(_) if rhs >= 16 => halt!(span, "shr overflow"),
873                Value::U32(_) | Value::I32(_) if rhs >= 32 => halt!(span, "shr overflow"),
874                Value::U64(_) | Value::I64(_) if rhs >= 64 => halt!(span, "shr overflow"),
875                Value::U128(_) | Value::I128(_) if rhs >= 128 => halt!(span, "shr overflow"),
876                _ => {}
877            }
878
879            lhs.simple_shr(rhs)
880        }
881
882        BinaryOperation::ShrWrapped => {
883            let rhs: u32 = match rhs {
884                Value::U8(y) => (*y).into(),
885                Value::U16(y) => (*y).into(),
886                Value::U32(y) => *y,
887                _ => halt!(span, "Type error"),
888            };
889
890            match lhs {
891                Value::U8(x) => Value::U8(x.wrapping_shr(rhs)),
892                Value::U16(x) => Value::U16(x.wrapping_shr(rhs)),
893                Value::U32(x) => Value::U32(x.wrapping_shr(rhs)),
894                Value::U64(x) => Value::U64(x.wrapping_shr(rhs)),
895                Value::U128(x) => Value::U128(x.wrapping_shr(rhs)),
896                Value::I8(x) => Value::I8(x.wrapping_shr(rhs)),
897                Value::I16(x) => Value::I16(x.wrapping_shr(rhs)),
898                Value::I32(x) => Value::I32(x.wrapping_shr(rhs)),
899                Value::I64(x) => Value::I64(x.wrapping_shr(rhs)),
900                Value::I128(x) => Value::I128(x.wrapping_shr(rhs)),
901                _ => halt!(span, "Type error"),
902            }
903        }
904
905        BinaryOperation::Sub => {
906            let Some(value) = (match (lhs, rhs) {
907                (Value::U8(x), Value::U8(y)) => x.checked_sub(*y).map(Value::U8),
908                (Value::U16(x), Value::U16(y)) => x.checked_sub(*y).map(Value::U16),
909                (Value::U32(x), Value::U32(y)) => x.checked_sub(*y).map(Value::U32),
910                (Value::U64(x), Value::U64(y)) => x.checked_sub(*y).map(Value::U64),
911                (Value::U128(x), Value::U128(y)) => x.checked_sub(*y).map(Value::U128),
912                (Value::I8(x), Value::I8(y)) => x.checked_sub(*y).map(Value::I8),
913                (Value::I16(x), Value::I16(y)) => x.checked_sub(*y).map(Value::I16),
914                (Value::I32(x), Value::I32(y)) => x.checked_sub(*y).map(Value::I32),
915                (Value::I64(x), Value::I64(y)) => x.checked_sub(*y).map(Value::I64),
916                (Value::I128(x), Value::I128(y)) => x.checked_sub(*y).map(Value::I128),
917                (Value::Group(x), Value::Group(y)) => Some(Value::Group(*x - *y)),
918                (Value::Field(x), Value::Field(y)) => Some(Value::Field(*x - *y)),
919                _ => halt!(span, "Type error"),
920            }) else {
921                halt!(span, "sub overflow");
922            };
923            value
924        }
925
926        BinaryOperation::SubWrapped => match (lhs, rhs) {
927            (Value::U8(x), Value::U8(y)) => Value::U8(x.wrapping_sub(*y)),
928            (Value::U16(x), Value::U16(y)) => Value::U16(x.wrapping_sub(*y)),
929            (Value::U32(x), Value::U32(y)) => Value::U32(x.wrapping_sub(*y)),
930            (Value::U64(x), Value::U64(y)) => Value::U64(x.wrapping_sub(*y)),
931            (Value::U128(x), Value::U128(y)) => Value::U128(x.wrapping_sub(*y)),
932            (Value::I8(x), Value::I8(y)) => Value::I8(x.wrapping_sub(*y)),
933            (Value::I16(x), Value::I16(y)) => Value::I16(x.wrapping_sub(*y)),
934            (Value::I32(x), Value::I32(y)) => Value::I32(x.wrapping_sub(*y)),
935            (Value::I64(x), Value::I64(y)) => Value::I64(x.wrapping_sub(*y)),
936            (Value::I128(x), Value::I128(y)) => Value::I128(x.wrapping_sub(*y)),
937            _ => halt!(span, "Type error"),
938        },
939
940        BinaryOperation::Xor => match (lhs, rhs) {
941            (Value::Bool(x), Value::Bool(y)) => Value::Bool(*x ^ *y),
942            (Value::U8(x), Value::U8(y)) => Value::U8(*x ^ *y),
943            (Value::U16(x), Value::U16(y)) => Value::U16(*x ^ *y),
944            (Value::U32(x), Value::U32(y)) => Value::U32(*x ^ *y),
945            (Value::U64(x), Value::U64(y)) => Value::U64(*x ^ *y),
946            (Value::U128(x), Value::U128(y)) => Value::U128(*x ^ *y),
947            (Value::I8(x), Value::I8(y)) => Value::I8(*x ^ *y),
948            (Value::I16(x), Value::I16(y)) => Value::I16(*x ^ *y),
949            (Value::I32(x), Value::I32(y)) => Value::I32(*x ^ *y),
950            (Value::I64(x), Value::I64(y)) => Value::I64(*x ^ *y),
951            (Value::I128(x), Value::I128(y)) => Value::I128(*x ^ *y),
952            _ => halt!(span, "Type error"),
953        },
954    };
955    Ok(value)
956}
957
958fn really_cast<C>(c: C, cast_type: &Type) -> Option<Value>
959where
960    C: Cast<SvmAddress>
961        + Cast<SvmField>
962        + Cast<SvmAddress>
963        + Cast<SvmGroup>
964        + Cast<SvmBoolean>
965        + Cast<SvmScalar>
966        + Cast<SvmInteger<u8>>
967        + Cast<SvmInteger<u16>>
968        + Cast<SvmInteger<u32>>
969        + Cast<SvmInteger<u64>>
970        + Cast<SvmInteger<u128>>
971        + Cast<SvmInteger<i8>>
972        + Cast<SvmInteger<i16>>
973        + Cast<SvmInteger<i32>>
974        + Cast<SvmInteger<i64>>
975        + Cast<SvmInteger<i128>>,
976{
977    use Type::*;
978
979    let value = match cast_type {
980        Address => Value::Address(c.cast().ok()?),
981        Boolean => Value::Bool({
982            let b: SvmBoolean = c.cast().ok()?;
983            *b
984        }),
985        Field => Value::Field(c.cast().ok()?),
986        Group => Value::Group(c.cast().ok()?),
987        Integer(IntegerType::U8) => Value::U8({
988            let i: SvmInteger<u8> = c.cast().ok()?;
989            *i
990        }),
991        Integer(IntegerType::U16) => Value::U16({
992            let i: SvmInteger<u16> = c.cast().ok()?;
993            *i
994        }),
995        Integer(IntegerType::U32) => Value::U32({
996            let i: SvmInteger<u32> = c.cast().ok()?;
997            *i
998        }),
999        Integer(IntegerType::U64) => Value::U64({
1000            let i: SvmInteger<u64> = c.cast().ok()?;
1001            *i
1002        }),
1003        Integer(IntegerType::U128) => Value::U128({
1004            let i: SvmInteger<u128> = c.cast().ok()?;
1005            *i
1006        }),
1007        Integer(IntegerType::I8) => Value::I8({
1008            let i: SvmInteger<i8> = c.cast().ok()?;
1009            *i
1010        }),
1011        Integer(IntegerType::I16) => Value::I16({
1012            let i: SvmInteger<i16> = c.cast().ok()?;
1013            *i
1014        }),
1015        Integer(IntegerType::I32) => Value::I32({
1016            let i: SvmInteger<i32> = c.cast().ok()?;
1017            *i
1018        }),
1019        Integer(IntegerType::I64) => Value::I64({
1020            let i: SvmInteger<i64> = c.cast().ok()?;
1021            *i
1022        }),
1023        Integer(IntegerType::I128) => Value::I128({
1024            let i: SvmInteger<i128> = c.cast().ok()?;
1025            *i
1026        }),
1027        Scalar => Value::Scalar(c.cast().ok()?),
1028
1029        _ => tc_fail!(),
1030    };
1031    Some(value)
1032}