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