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::String(..) => tc_fail2!(),
206 })
207}
208
209fn resolve_unsuffixed_unary_op_operand(
213 val: &Value,
214 op: &UnaryOperation,
215 expected_ty: &Option<Type>,
216 span: &Span,
217) -> Result<Value> {
218 match op {
219 UnaryOperation::Inverse | UnaryOperation::Square | UnaryOperation::SquareRoot => {
220 val.resolve_if_unsuffixed(&Some(Type::Field), *span)
222 }
223 UnaryOperation::ToXCoordinate | UnaryOperation::ToYCoordinate => {
224 val.resolve_if_unsuffixed(&Some(Type::Group), *span)
226 }
227 _ => {
228 val.resolve_if_unsuffixed(expected_ty, *span)
230 }
231 }
232}
233
234pub fn evaluate_unary(span: Span, op: UnaryOperation, value: &Value, expected_ty: &Option<Type>) -> Result<Value> {
236 let value = resolve_unsuffixed_unary_op_operand(value, &op, expected_ty, &span)?;
237 let ValueVariants::Svm(SvmValueParam::Plaintext(Plaintext::Literal(literal, ..))) = &value.contents else {
238 halt2!(span, "Type error");
239 };
240 let value_result: Value = match op {
241 UnaryOperation::Abs => match literal {
242 SvmLiteralParam::I8(x) => {
243 x.checked_abs().ok_or_else::<InterpreterHalt, _>(|| fail2!(span, "abs overflow"))?.into()
244 }
245 SvmLiteralParam::I16(x) => {
246 x.checked_abs().ok_or_else::<InterpreterHalt, _>(|| fail2!(span, "abs overlfow"))?.into()
247 }
248 SvmLiteralParam::I32(x) => {
249 x.checked_abs().ok_or_else::<InterpreterHalt, _>(|| fail2!(span, "abs overlfow"))?.into()
250 }
251 SvmLiteralParam::I64(x) => {
252 x.checked_abs().ok_or_else::<InterpreterHalt, _>(|| fail2!(span, "abs overlfow"))?.into()
253 }
254 SvmLiteralParam::I128(x) => {
255 x.checked_abs().ok_or_else::<InterpreterHalt, _>(|| fail2!(span, "abs overlfow"))?.into()
256 }
257 _ => halt2!(span, "Type error"),
258 },
259 UnaryOperation::AbsWrapped => match literal {
260 SvmLiteralParam::I8(x) => (x.unsigned_abs() as i8).into(),
261 SvmLiteralParam::I16(x) => (x.unsigned_abs() as i16).into(),
262 SvmLiteralParam::I32(x) => (x.unsigned_abs() as i32).into(),
263 SvmLiteralParam::I64(x) => (x.unsigned_abs() as i64).into(),
264 SvmLiteralParam::I128(x) => (x.unsigned_abs() as i128).into(),
265 _ => halt2!(span, "Type error"),
266 },
267 UnaryOperation::Double => match literal {
268 SvmLiteralParam::Field(x) => <Field as Double>::double(x).into(),
269 SvmLiteralParam::Group(x) => <Group as Double>::double(x).into(),
270 _ => halt2!(span, "Type error"),
271 },
272 UnaryOperation::Inverse => match literal {
273 SvmLiteralParam::Field(x) => {
274 let Ok(y) = x.inverse() else {
275 halt2!(span, "attempt to invert 0field");
276 };
277 y.into()
278 }
279 _ => halt2!(span, "Can only invert fields"),
280 },
281 UnaryOperation::Negate => match literal {
282 SvmLiteralParam::I8(x) => {
283 x.checked_neg().ok_or_else::<InterpreterHalt, _>(|| fail2!(span, "negation overflow"))?.into()
284 }
285 SvmLiteralParam::I16(x) => {
286 x.checked_neg().ok_or_else::<InterpreterHalt, _>(|| fail2!(span, "negation overflow"))?.into()
287 }
288 SvmLiteralParam::I32(x) => {
289 x.checked_neg().ok_or_else::<InterpreterHalt, _>(|| fail2!(span, "negation overflow"))?.into()
290 }
291 SvmLiteralParam::I64(x) => {
292 x.checked_neg().ok_or_else::<InterpreterHalt, _>(|| fail2!(span, "negation overflow"))?.into()
293 }
294 SvmLiteralParam::I128(x) => {
295 x.checked_neg().ok_or_else::<InterpreterHalt, _>(|| fail2!(span, "negation overflow"))?.into()
296 }
297 SvmLiteralParam::Group(x) => (-*x).into(),
298 SvmLiteralParam::Field(x) => (-*x).into(),
299 _ => halt2!(span, "Type error"),
300 },
301 UnaryOperation::Not => match literal {
302 SvmLiteralParam::Boolean(x) => (!**x).into(),
303 SvmLiteralParam::U8(x) => (!**x).into(),
304 SvmLiteralParam::U16(x) => (!**x).into(),
305 SvmLiteralParam::U32(x) => (!**x).into(),
306 SvmLiteralParam::U64(x) => (!**x).into(),
307 SvmLiteralParam::U128(x) => (!**x).into(),
308 SvmLiteralParam::I8(x) => (!**x).into(),
309 SvmLiteralParam::I16(x) => (!**x).into(),
310 SvmLiteralParam::I32(x) => (!**x).into(),
311 SvmLiteralParam::I64(x) => (!**x).into(),
312 SvmLiteralParam::I128(x) => (!**x).into(),
313 _ => halt2!(span, "Type error"),
314 },
315 UnaryOperation::Square => match literal {
316 SvmLiteralParam::Field(x) => x.square().into(),
317 _ => halt2!(span, "Can only square fields"),
318 },
319 UnaryOperation::SquareRoot => match literal {
320 SvmLiteralParam::Field(x) => {
321 x.square_root().map_err::<InterpreterHalt, _>(|e| fail2!(span, "square root failure: {e}"))?.into()
322 }
323 _ => halt2!(span, "Can only apply square_root to fields"),
324 },
325 UnaryOperation::ToXCoordinate => match literal {
326 SvmLiteral::Group(x) => x.to_x_coordinate().into(),
327 _ => tc_fail2!(),
328 },
329 UnaryOperation::ToYCoordinate => match literal {
330 SvmLiteral::Group(x) => x.to_y_coordinate().into(),
331 _ => tc_fail2!(),
332 },
333 };
334
335 Ok(value_result)
336}
337
338fn resolve_unsuffixed_binary_op_operands(
343 lhs: &Value,
344 rhs: &Value,
345 op: &BinaryOperation,
346 expected_ty: &Option<Type>,
347 span: &Span,
348) -> Result<(Value, Value)> {
349 use Type::*;
350
351 let lhs_ty = lhs.get_numeric_type();
352 let rhs_ty = rhs.get_numeric_type();
353
354 Ok(match op {
355 BinaryOperation::Mul => {
356 let lhs = match rhs_ty {
359 Some(Group) => lhs.resolve_if_unsuffixed(&Some(Scalar), *span)?,
360 Some(Scalar) => lhs.resolve_if_unsuffixed(&Some(Group), *span)?,
361 _ => lhs.resolve_if_unsuffixed(&rhs_ty, *span)?.resolve_if_unsuffixed(expected_ty, *span)?,
362 };
363
364 let rhs = match lhs_ty {
365 Some(Group) => rhs.resolve_if_unsuffixed(&Some(Scalar), *span)?,
366 Some(Scalar) => rhs.resolve_if_unsuffixed(&Some(Group), *span)?,
367 _ => rhs.resolve_if_unsuffixed(&lhs_ty, *span)?.resolve_if_unsuffixed(expected_ty, *span)?,
368 };
369
370 (lhs, rhs)
371 }
372 BinaryOperation::Pow => {
373 let lhs_resolved = lhs
376 .resolve_if_unsuffixed(&rhs_ty.filter(|ty| matches!(ty, Type::Field)), *span)?
377 .resolve_if_unsuffixed(expected_ty, *span)?;
378
379 let rhs_resolved = rhs.resolve_if_unsuffixed(&lhs_ty.filter(|ty| matches!(ty, Type::Field)), *span)?;
380
381 (lhs_resolved, rhs_resolved)
382 }
383 _ => (
384 lhs.resolve_if_unsuffixed(&rhs_ty, *span)?.resolve_if_unsuffixed(expected_ty, *span)?,
385 rhs.resolve_if_unsuffixed(&lhs_ty, *span)?.resolve_if_unsuffixed(expected_ty, *span)?,
386 ),
387 })
388}
389
390pub fn evaluate_binary(
392 span: Span,
393 op: BinaryOperation,
394 lhs: &Value,
395 rhs: &Value,
396 expected_ty: &Option<Type>,
397) -> Result<Value> {
398 let (lhs, rhs) = resolve_unsuffixed_binary_op_operands(lhs, rhs, &op, expected_ty, &span)?;
399
400 match op {
401 BinaryOperation::Eq => return lhs.eq(&rhs).map(|x| x.into()),
402 BinaryOperation::Neq => return lhs.eq(&rhs).map(|x| (!x).into()),
403 _ => {}
404 }
405
406 let ValueVariants::Svm(SvmValueParam::Plaintext(Plaintext::Literal(lhs, ..))) = &lhs.contents else {
407 halt2!(span, "Type error");
408 };
409 let ValueVariants::Svm(SvmValueParam::Plaintext(Plaintext::Literal(rhs, ..))) = &rhs.contents else {
410 halt2!(span, "Type error");
411 };
412 let value = match op {
413 BinaryOperation::Add => {
414 let Some(value): Option<Value> = (match (lhs, rhs) {
415 (SvmLiteralParam::U8(x), SvmLiteralParam::U8(y)) => (*x).checked_add(**y).map(|z| z.into()),
416 (SvmLiteralParam::U16(x), SvmLiteralParam::U16(y)) => (*x).checked_add(**y).map(|z| z.into()),
417 (SvmLiteralParam::U32(x), SvmLiteralParam::U32(y)) => (*x).checked_add(**y).map(|z| z.into()),
418 (SvmLiteralParam::U64(x), SvmLiteralParam::U64(y)) => (*x).checked_add(**y).map(|z| z.into()),
419 (SvmLiteralParam::U128(x), SvmLiteralParam::U128(y)) => (*x).checked_add(**y).map(|z| z.into()),
420 (SvmLiteralParam::I8(x), SvmLiteralParam::I8(y)) => (*x).checked_add(**y).map(|z| z.into()),
421 (SvmLiteralParam::I16(x), SvmLiteralParam::I16(y)) => (*x).checked_add(**y).map(|z| z.into()),
422 (SvmLiteralParam::I32(x), SvmLiteralParam::I32(y)) => (*x).checked_add(**y).map(|z| z.into()),
423 (SvmLiteralParam::I64(x), SvmLiteralParam::I64(y)) => (*x).checked_add(**y).map(|z| z.into()),
424 (SvmLiteralParam::I128(x), SvmLiteralParam::I128(y)) => (*x).checked_add(**y).map(|z| z.into()),
425 (SvmLiteralParam::Group(x), SvmLiteralParam::Group(y)) => Some((*x + y).into()),
426 (SvmLiteralParam::Field(x), SvmLiteralParam::Field(y)) => Some((*x + y).into()),
427 (SvmLiteralParam::Scalar(x), SvmLiteralParam::Scalar(y)) => Some((*x + y).into()),
428 _ => halt2!(span, "Type error"),
429 }) else {
430 halt2!(span, "add overflow");
431 };
432 value
433 }
434 BinaryOperation::AddWrapped => match (lhs, rhs) {
435 (SvmLiteralParam::U8(x), SvmLiteralParam::U8(y)) => (*x).wrapping_add(**y).into(),
436 (SvmLiteralParam::U16(x), SvmLiteralParam::U16(y)) => (*x).wrapping_add(**y).into(),
437 (SvmLiteralParam::U32(x), SvmLiteralParam::U32(y)) => (*x).wrapping_add(**y).into(),
438 (SvmLiteralParam::U64(x), SvmLiteralParam::U64(y)) => (*x).wrapping_add(**y).into(),
439 (SvmLiteralParam::U128(x), SvmLiteralParam::U128(y)) => (*x).wrapping_add(**y).into(),
440 (SvmLiteralParam::I8(x), SvmLiteralParam::I8(y)) => (*x).wrapping_add(**y).into(),
441 (SvmLiteralParam::I16(x), SvmLiteralParam::I16(y)) => (*x).wrapping_add(**y).into(),
442 (SvmLiteralParam::I32(x), SvmLiteralParam::I32(y)) => (*x).wrapping_add(**y).into(),
443 (SvmLiteralParam::I64(x), SvmLiteralParam::I64(y)) => (*x).wrapping_add(**y).into(),
444 (SvmLiteralParam::I128(x), SvmLiteralParam::I128(y)) => (*x).wrapping_add(**y).into(),
445 _ => halt2!(span, "Type error"),
446 },
447 BinaryOperation::And => match (lhs, rhs) {
448 (SvmLiteralParam::Boolean(x), SvmLiteralParam::Boolean(y)) => (**x && **y).into(),
449 _ => halt2!(span, "Type error"),
450 },
451 BinaryOperation::BitwiseAnd => match (lhs, rhs) {
452 (SvmLiteralParam::Boolean(x), SvmLiteralParam::Boolean(y)) => (**x & **y).into(),
453 (SvmLiteralParam::U8(x), SvmLiteralParam::U8(y)) => (**x & **y).into(),
454 (SvmLiteralParam::U16(x), SvmLiteralParam::U16(y)) => (**x & **y).into(),
455 (SvmLiteralParam::U32(x), SvmLiteralParam::U32(y)) => (**x & **y).into(),
456 (SvmLiteralParam::U64(x), SvmLiteralParam::U64(y)) => (**x & **y).into(),
457 (SvmLiteralParam::U128(x), SvmLiteralParam::U128(y)) => (**x & **y).into(),
458 (SvmLiteralParam::I8(x), SvmLiteralParam::I8(y)) => (**x & **y).into(),
459 (SvmLiteralParam::I16(x), SvmLiteralParam::I16(y)) => (**x & **y).into(),
460 (SvmLiteralParam::I32(x), SvmLiteralParam::I32(y)) => (**x & **y).into(),
461 (SvmLiteralParam::I64(x), SvmLiteralParam::I64(y)) => (**x & **y).into(),
462 (SvmLiteralParam::I128(x), SvmLiteralParam::I128(y)) => (**x & **y).into(),
463 _ => halt2!(span, "Type error"),
464 },
465 BinaryOperation::Div => {
466 let Some(value) = (match (lhs, rhs) {
467 (SvmLiteralParam::U8(x), SvmLiteralParam::U8(y)) => (*x).checked_div(**y).map(|z| z.into()),
468 (SvmLiteralParam::U16(x), SvmLiteralParam::U16(y)) => (*x).checked_div(**y).map(|z| z.into()),
469 (SvmLiteralParam::U32(x), SvmLiteralParam::U32(y)) => (*x).checked_div(**y).map(|z| z.into()),
470 (SvmLiteralParam::U64(x), SvmLiteralParam::U64(y)) => (*x).checked_div(**y).map(|z| z.into()),
471 (SvmLiteralParam::U128(x), SvmLiteralParam::U128(y)) => (*x).checked_div(**y).map(|z| z.into()),
472 (SvmLiteralParam::I8(x), SvmLiteralParam::I8(y)) => (*x).checked_div(**y).map(|z| z.into()),
473 (SvmLiteralParam::I16(x), SvmLiteralParam::I16(y)) => (*x).checked_div(**y).map(|z| z.into()),
474 (SvmLiteralParam::I32(x), SvmLiteralParam::I32(y)) => (*x).checked_div(**y).map(|z| z.into()),
475 (SvmLiteralParam::I64(x), SvmLiteralParam::I64(y)) => (*x).checked_div(**y).map(|z| z.into()),
476 (SvmLiteralParam::I128(x), SvmLiteralParam::I128(y)) => (*x).checked_div(**y).map(|z| z.into()),
477 (SvmLiteralParam::Field(x), SvmLiteralParam::Field(y)) => y.inverse().map(|y| (*x * y).into()).ok(),
478 _ => halt2!(span, "Type error"),
479 }) else {
480 halt2!(span, "div overflow");
481 };
482 value
483 }
484 BinaryOperation::DivWrapped => match (lhs, rhs) {
485 (SvmLiteralParam::U8(x), SvmLiteralParam::U8(y)) if **y != 0 => (*x).wrapping_div(**y).into(),
486 (SvmLiteralParam::U16(x), SvmLiteralParam::U16(y)) if **y != 0 => (*x).wrapping_div(**y).into(),
487 (SvmLiteralParam::U32(x), SvmLiteralParam::U32(y)) if **y != 0 => (*x).wrapping_div(**y).into(),
488 (SvmLiteralParam::U64(x), SvmLiteralParam::U64(y)) if **y != 0 => (*x).wrapping_div(**y).into(),
489 (SvmLiteralParam::U128(x), SvmLiteralParam::U128(y)) if **y != 0 => (*x).wrapping_div(**y).into(),
490 (SvmLiteralParam::I8(x), SvmLiteralParam::I8(y)) if **y != 0 => (*x).wrapping_div(**y).into(),
491 (SvmLiteralParam::I16(x), SvmLiteralParam::I16(y)) if **y != 0 => (*x).wrapping_div(**y).into(),
492 (SvmLiteralParam::I32(x), SvmLiteralParam::I32(y)) if **y != 0 => (*x).wrapping_div(**y).into(),
493 (SvmLiteralParam::I64(x), SvmLiteralParam::I64(y)) if **y != 0 => (*x).wrapping_div(**y).into(),
494 (SvmLiteralParam::I128(x), SvmLiteralParam::I128(y)) if **y != 0 => (*x).wrapping_div(**y).into(),
495 _ => halt2!(span, "Type error"),
496 },
497 BinaryOperation::Eq => unreachable!("This case was handled above"),
498 BinaryOperation::Gte => match (lhs, rhs) {
499 (SvmLiteralParam::U8(x), SvmLiteralParam::U8(y)) => (*x >= *y).into(),
500 (SvmLiteralParam::U16(x), SvmLiteralParam::U16(y)) => (*x >= *y).into(),
501 (SvmLiteralParam::U32(x), SvmLiteralParam::U32(y)) => (*x >= *y).into(),
502 (SvmLiteralParam::U64(x), SvmLiteralParam::U64(y)) => (*x >= *y).into(),
503 (SvmLiteralParam::U128(x), SvmLiteralParam::U128(y)) => (*x >= *y).into(),
504 (SvmLiteralParam::I8(x), SvmLiteralParam::I8(y)) => (*x >= *y).into(),
505 (SvmLiteralParam::I16(x), SvmLiteralParam::I16(y)) => (*x >= *y).into(),
506 (SvmLiteralParam::I32(x), SvmLiteralParam::I32(y)) => (*x >= *y).into(),
507 (SvmLiteralParam::I64(x), SvmLiteralParam::I64(y)) => (*x >= *y).into(),
508 (SvmLiteralParam::I128(x), SvmLiteralParam::I128(y)) => (*x >= *y).into(),
509 (SvmLiteralParam::Field(x), SvmLiteralParam::Field(y)) => (*x >= *y).into(),
510 (SvmLiteralParam::Scalar(x), SvmLiteralParam::Scalar(y)) => (*x >= *y).into(),
511 _ => halt2!(span, "Type error"),
512 },
513 BinaryOperation::Gt => match (lhs, rhs) {
514 (SvmLiteralParam::U8(x), SvmLiteralParam::U8(y)) => (*x > *y).into(),
515 (SvmLiteralParam::U16(x), SvmLiteralParam::U16(y)) => (*x > *y).into(),
516 (SvmLiteralParam::U32(x), SvmLiteralParam::U32(y)) => (*x > *y).into(),
517 (SvmLiteralParam::U64(x), SvmLiteralParam::U64(y)) => (*x > *y).into(),
518 (SvmLiteralParam::U128(x), SvmLiteralParam::U128(y)) => (*x > *y).into(),
519 (SvmLiteralParam::I8(x), SvmLiteralParam::I8(y)) => (*x > *y).into(),
520 (SvmLiteralParam::I16(x), SvmLiteralParam::I16(y)) => (*x > *y).into(),
521 (SvmLiteralParam::I32(x), SvmLiteralParam::I32(y)) => (*x > *y).into(),
522 (SvmLiteralParam::I64(x), SvmLiteralParam::I64(y)) => (*x > *y).into(),
523 (SvmLiteralParam::I128(x), SvmLiteralParam::I128(y)) => (*x > *y).into(),
524 (SvmLiteralParam::Field(x), SvmLiteralParam::Field(y)) => (*x > *y).into(),
525 (SvmLiteralParam::Scalar(x), SvmLiteralParam::Scalar(y)) => (*x > *y).into(),
526 _ => halt2!(span, "Type error"),
527 },
528 BinaryOperation::Lte => match (lhs, rhs) {
529 (SvmLiteralParam::U8(x), SvmLiteralParam::U8(y)) => (*x <= *y).into(),
530 (SvmLiteralParam::U16(x), SvmLiteralParam::U16(y)) => (*x <= *y).into(),
531 (SvmLiteralParam::U32(x), SvmLiteralParam::U32(y)) => (*x <= *y).into(),
532 (SvmLiteralParam::U64(x), SvmLiteralParam::U64(y)) => (*x <= *y).into(),
533 (SvmLiteralParam::U128(x), SvmLiteralParam::U128(y)) => (*x <= *y).into(),
534 (SvmLiteralParam::I8(x), SvmLiteralParam::I8(y)) => (*x <= *y).into(),
535 (SvmLiteralParam::I16(x), SvmLiteralParam::I16(y)) => (*x <= *y).into(),
536 (SvmLiteralParam::I32(x), SvmLiteralParam::I32(y)) => (*x <= *y).into(),
537 (SvmLiteralParam::I64(x), SvmLiteralParam::I64(y)) => (*x <= *y).into(),
538 (SvmLiteralParam::I128(x), SvmLiteralParam::I128(y)) => (*x <= *y).into(),
539 (SvmLiteralParam::Field(x), SvmLiteralParam::Field(y)) => (*x <= *y).into(),
540 (SvmLiteralParam::Scalar(x), SvmLiteralParam::Scalar(y)) => (*x <= *y).into(),
541 _ => halt2!(span, "Type error"),
542 },
543 BinaryOperation::Lt => match (lhs, rhs) {
544 (SvmLiteralParam::U8(x), SvmLiteralParam::U8(y)) => (*x < *y).into(),
545 (SvmLiteralParam::U16(x), SvmLiteralParam::U16(y)) => (*x < *y).into(),
546 (SvmLiteralParam::U32(x), SvmLiteralParam::U32(y)) => (*x < *y).into(),
547 (SvmLiteralParam::U64(x), SvmLiteralParam::U64(y)) => (*x < *y).into(),
548 (SvmLiteralParam::U128(x), SvmLiteralParam::U128(y)) => (*x < *y).into(),
549 (SvmLiteralParam::I8(x), SvmLiteralParam::I8(y)) => (*x < *y).into(),
550 (SvmLiteralParam::I16(x), SvmLiteralParam::I16(y)) => (*x < *y).into(),
551 (SvmLiteralParam::I32(x), SvmLiteralParam::I32(y)) => (*x < *y).into(),
552 (SvmLiteralParam::I64(x), SvmLiteralParam::I64(y)) => (*x < *y).into(),
553 (SvmLiteralParam::I128(x), SvmLiteralParam::I128(y)) => (*x < *y).into(),
554 (SvmLiteralParam::Field(x), SvmLiteralParam::Field(y)) => (*x < *y).into(),
555 (SvmLiteralParam::Scalar(x), SvmLiteralParam::Scalar(y)) => (*x < *y).into(),
556 _ => halt2!(span, "Type error"),
557 },
558 BinaryOperation::Mod => {
559 let Some(value) = (match (lhs, rhs) {
560 (SvmLiteralParam::U8(x), SvmLiteralParam::U8(y)) => x.checked_rem(**y).map(|z| z.into()),
561 (SvmLiteralParam::U16(x), SvmLiteralParam::U16(y)) => x.checked_rem(**y).map(|z| z.into()),
562 (SvmLiteralParam::U32(x), SvmLiteralParam::U32(y)) => x.checked_rem(**y).map(|z| z.into()),
563 (SvmLiteralParam::U64(x), SvmLiteralParam::U64(y)) => x.checked_rem(**y).map(|z| z.into()),
564 (SvmLiteralParam::U128(x), SvmLiteralParam::U128(y)) => x.checked_rem(**y).map(|z| z.into()),
565 _ => halt2!(span, "Type error"),
566 }) else {
567 halt2!(span, "mod overflow");
568 };
569 value
570 }
571 BinaryOperation::Mul => {
572 let Some(value) = (match (lhs, rhs) {
573 (SvmLiteralParam::U8(x), SvmLiteralParam::U8(y)) => x.checked_mul(**y).map(|z| z.into()),
574 (SvmLiteralParam::U16(x), SvmLiteralParam::U16(y)) => x.checked_mul(**y).map(|z| z.into()),
575 (SvmLiteralParam::U32(x), SvmLiteralParam::U32(y)) => x.checked_mul(**y).map(|z| z.into()),
576 (SvmLiteralParam::U64(x), SvmLiteralParam::U64(y)) => x.checked_mul(**y).map(|z| z.into()),
577 (SvmLiteralParam::U128(x), SvmLiteralParam::U128(y)) => x.checked_mul(**y).map(|z| z.into()),
578 (SvmLiteralParam::I8(x), SvmLiteralParam::I8(y)) => x.checked_mul(**y).map(|z| z.into()),
579 (SvmLiteralParam::I16(x), SvmLiteralParam::I16(y)) => x.checked_mul(**y).map(|z| z.into()),
580 (SvmLiteralParam::I32(x), SvmLiteralParam::I32(y)) => x.checked_mul(**y).map(|z| z.into()),
581 (SvmLiteralParam::I64(x), SvmLiteralParam::I64(y)) => x.checked_mul(**y).map(|z| z.into()),
582 (SvmLiteralParam::I128(x), SvmLiteralParam::I128(y)) => x.checked_mul(**y).map(|z| z.into()),
583 (SvmLiteralParam::Field(x), SvmLiteralParam::Field(y)) => Some((*x * y).into()),
584 (SvmLiteralParam::Group(x), SvmLiteralParam::Scalar(y)) => Some((*x * y).into()),
585 (SvmLiteralParam::Scalar(x), SvmLiteralParam::Group(y)) => Some((*x * y).into()),
586 _ => halt2!(span, "Type error"),
587 }) else {
588 halt2!(span, "mul overflow");
589 };
590 value
591 }
592 BinaryOperation::MulWrapped => match (lhs, rhs) {
593 (SvmLiteralParam::U8(x), SvmLiteralParam::U8(y)) => x.wrapping_mul(**y).into(),
594 (SvmLiteralParam::U16(x), SvmLiteralParam::U16(y)) => x.wrapping_mul(**y).into(),
595 (SvmLiteralParam::U32(x), SvmLiteralParam::U32(y)) => x.wrapping_mul(**y).into(),
596 (SvmLiteralParam::U64(x), SvmLiteralParam::U64(y)) => x.wrapping_mul(**y).into(),
597 (SvmLiteralParam::U128(x), SvmLiteralParam::U128(y)) => x.wrapping_mul(**y).into(),
598 (SvmLiteralParam::I8(x), SvmLiteralParam::I8(y)) => x.wrapping_mul(**y).into(),
599 (SvmLiteralParam::I16(x), SvmLiteralParam::I16(y)) => x.wrapping_mul(**y).into(),
600 (SvmLiteralParam::I32(x), SvmLiteralParam::I32(y)) => x.wrapping_mul(**y).into(),
601 (SvmLiteralParam::I64(x), SvmLiteralParam::I64(y)) => x.wrapping_mul(**y).into(),
602 (SvmLiteralParam::I128(x), SvmLiteralParam::I128(y)) => x.wrapping_mul(**y).into(),
603 _ => halt2!(span, "Type error"),
604 },
605
606 BinaryOperation::Nand => match (lhs, rhs) {
607 (SvmLiteralParam::Boolean(x), SvmLiteralParam::Boolean(y)) => (!(**x & **y)).into(),
608 _ => halt2!(span, "Type error"),
609 },
610
611 BinaryOperation::Neq => unreachable!("This case was handled above"),
612
613 BinaryOperation::Nor => match (lhs, rhs) {
614 (SvmLiteralParam::Boolean(x), SvmLiteralParam::Boolean(y)) => (!(**x | **y)).into(),
615 _ => halt2!(span, "Type error"),
616 },
617
618 BinaryOperation::Or => match (lhs, rhs) {
619 (SvmLiteralParam::Boolean(x), SvmLiteralParam::Boolean(y)) => (**x | **y).into(),
620 _ => halt2!(span, "Type error"),
621 },
622
623 BinaryOperation::BitwiseOr => match (lhs, rhs) {
624 (SvmLiteralParam::Boolean(x), SvmLiteralParam::Boolean(y)) => (**x | **y).into(),
625 (SvmLiteralParam::U8(x), SvmLiteralParam::U8(y)) => (**x | **y).into(),
626 (SvmLiteralParam::U16(x), SvmLiteralParam::U16(y)) => (**x | **y).into(),
627 (SvmLiteralParam::U32(x), SvmLiteralParam::U32(y)) => (**x | **y).into(),
628 (SvmLiteralParam::U64(x), SvmLiteralParam::U64(y)) => (**x | **y).into(),
629 (SvmLiteralParam::U128(x), SvmLiteralParam::U128(y)) => (**x | **y).into(),
630 (SvmLiteralParam::I8(x), SvmLiteralParam::I8(y)) => (**x | **y).into(),
631 (SvmLiteralParam::I16(x), SvmLiteralParam::I16(y)) => (**x | **y).into(),
632 (SvmLiteralParam::I32(x), SvmLiteralParam::I32(y)) => (**x | **y).into(),
633 (SvmLiteralParam::I64(x), SvmLiteralParam::I64(y)) => (**x | **y).into(),
634 (SvmLiteralParam::I128(x), SvmLiteralParam::I128(y)) => (**x | **y).into(),
635 _ => halt2!(span, "Type error"),
636 },
637
638 BinaryOperation::Pow => {
639 if let (SvmLiteralParam::Field(x), SvmLiteralParam::Field(y)) = (&lhs, &rhs) {
640 x.pow(y).into()
641 } else {
642 let rhs: u32 = match rhs {
643 SvmLiteralParam::U8(y) => (**y).into(),
644 SvmLiteralParam::U16(y) => (**y).into(),
645 SvmLiteralParam::U32(y) => **y,
646 _ => tc_fail2!(),
647 };
648
649 let Some(value) = (match lhs {
650 SvmLiteralParam::U8(x) => x.checked_pow(rhs).map(|z| z.into()),
651 SvmLiteralParam::U16(x) => x.checked_pow(rhs).map(|z| z.into()),
652 SvmLiteralParam::U32(x) => x.checked_pow(rhs).map(|z| z.into()),
653 SvmLiteralParam::U64(x) => x.checked_pow(rhs).map(|z| z.into()),
654 SvmLiteralParam::U128(x) => x.checked_pow(rhs).map(|z| z.into()),
655 SvmLiteralParam::I8(x) => x.checked_pow(rhs).map(|z| z.into()),
656 SvmLiteralParam::I16(x) => x.checked_pow(rhs).map(|z| z.into()),
657 SvmLiteralParam::I32(x) => x.checked_pow(rhs).map(|z| z.into()),
658 SvmLiteralParam::I64(x) => x.checked_pow(rhs).map(|z| z.into()),
659 SvmLiteralParam::I128(x) => x.checked_pow(rhs).map(|z| z.into()),
660 _ => halt2!(span, "Type error"),
661 }) else {
662 halt2!(span, "pow overflow");
663 };
664 value
665 }
666 }
667 BinaryOperation::PowWrapped => {
668 let rhs: u32 = match rhs {
669 SvmLiteralParam::U8(y) => (**y).into(),
670 SvmLiteralParam::U16(y) => (**y).into(),
671 SvmLiteralParam::U32(y) => **y,
672 _ => halt2!(span, "Type error"),
673 };
674
675 match lhs {
676 SvmLiteralParam::U8(x) => x.wrapping_pow(rhs).into(),
677 SvmLiteralParam::U16(x) => x.wrapping_pow(rhs).into(),
678 SvmLiteralParam::U32(x) => x.wrapping_pow(rhs).into(),
679 SvmLiteralParam::U64(x) => x.wrapping_pow(rhs).into(),
680 SvmLiteralParam::U128(x) => x.wrapping_pow(rhs).into(),
681 SvmLiteralParam::I8(x) => x.wrapping_pow(rhs).into(),
682 SvmLiteralParam::I16(x) => x.wrapping_pow(rhs).into(),
683 SvmLiteralParam::I32(x) => x.wrapping_pow(rhs).into(),
684 SvmLiteralParam::I64(x) => x.wrapping_pow(rhs).into(),
685 SvmLiteralParam::I128(x) => x.wrapping_pow(rhs).into(),
686 _ => halt2!(span, "Type error"),
687 }
688 }
689
690 BinaryOperation::Rem => {
691 let Some(value) = (match (lhs, rhs) {
692 (SvmLiteralParam::U8(x), SvmLiteralParam::U8(y)) => (**x).checked_rem(**y).map(|z| z.into()),
693 (SvmLiteralParam::U16(x), SvmLiteralParam::U16(y)) => (**x).checked_rem(**y).map(|z| z.into()),
694 (SvmLiteralParam::U32(x), SvmLiteralParam::U32(y)) => (**x).checked_rem(**y).map(|z| z.into()),
695 (SvmLiteralParam::U64(x), SvmLiteralParam::U64(y)) => (**x).checked_rem(**y).map(|z| z.into()),
696 (SvmLiteralParam::U128(x), SvmLiteralParam::U128(y)) => (**x).checked_rem(**y).map(|z| z.into()),
697 (SvmLiteralParam::I8(x), SvmLiteralParam::I8(y)) => (**x).checked_rem(**y).map(|z| z.into()),
698 (SvmLiteralParam::I16(x), SvmLiteralParam::I16(y)) => (**x).checked_rem(**y).map(|z| z.into()),
699 (SvmLiteralParam::I32(x), SvmLiteralParam::I32(y)) => (**x).checked_rem(**y).map(|z| z.into()),
700 (SvmLiteralParam::I64(x), SvmLiteralParam::I64(y)) => (**x).checked_rem(**y).map(|z| z.into()),
701 (SvmLiteralParam::I128(x), SvmLiteralParam::I128(y)) => (**x).checked_rem(**y).map(|z| z.into()),
702 _ => halt2!(span, "Type error"),
703 }) else {
704 halt2!(span, "rem error");
705 };
706 value
707 }
708
709 BinaryOperation::RemWrapped => match (lhs, rhs) {
710 (SvmLiteralParam::U8(x), SvmLiteralParam::U8(y)) if **y != 0 => (*x).wrapping_rem(**y).into(),
711 (SvmLiteralParam::U16(x), SvmLiteralParam::U16(y)) if **y != 0 => (*x).wrapping_rem(**y).into(),
712 (SvmLiteralParam::U32(x), SvmLiteralParam::U32(y)) if **y != 0 => (*x).wrapping_rem(**y).into(),
713 (SvmLiteralParam::U64(x), SvmLiteralParam::U64(y)) if **y != 0 => (*x).wrapping_rem(**y).into(),
714 (SvmLiteralParam::U128(x), SvmLiteralParam::U128(y)) if **y != 0 => (*x).wrapping_rem(**y).into(),
715 (SvmLiteralParam::I8(x), SvmLiteralParam::I8(y)) if **y != 0 => (*x).wrapping_rem(**y).into(),
716 (SvmLiteralParam::I16(x), SvmLiteralParam::I16(y)) if **y != 0 => (*x).wrapping_rem(**y).into(),
717 (SvmLiteralParam::I32(x), SvmLiteralParam::I32(y)) if **y != 0 => (*x).wrapping_rem(**y).into(),
718 (SvmLiteralParam::I64(x), SvmLiteralParam::I64(y)) if **y != 0 => (*x).wrapping_rem(**y).into(),
719 (SvmLiteralParam::I128(x), SvmLiteralParam::I128(y)) if **y != 0 => (*x).wrapping_rem(**y).into(),
720 _ => halt2!(span, "Type error"),
721 },
722
723 BinaryOperation::Shl => {
724 let rhs: u32 = match rhs {
725 SvmLiteralParam::U8(y) => (**y).into(),
726 SvmLiteralParam::U16(y) => (**y).into(),
727 SvmLiteralParam::U32(y) => **y,
728 _ => halt2!(span, "Type error"),
729 };
730 match lhs {
731 SvmLiteralParam::U8(_) | SvmLiteralParam::I8(_) if rhs >= 8 => halt2!(span, "shl overflow"),
732 SvmLiteralParam::U16(_) | SvmLiteralParam::I16(_) if rhs >= 16 => halt2!(span, "shl overflow"),
733 SvmLiteralParam::U32(_) | SvmLiteralParam::I32(_) if rhs >= 32 => halt2!(span, "shl overflow"),
734 SvmLiteralParam::U64(_) | SvmLiteralParam::I64(_) if rhs >= 64 => halt2!(span, "shl overflow"),
735 SvmLiteralParam::U128(_) | SvmLiteralParam::I128(_) if rhs >= 128 => halt2!(span, "shl overflow"),
736 SvmLiteralParam::U8(x) => {
737 let before_ones = x.count_ones();
738 let shifted = (**x) << rhs;
739 let after_ones = x.count_ones();
740 if before_ones != after_ones {
741 halt2!(span, "shl");
742 }
743 shifted.into()
744 }
745 SvmLiteralParam::U16(x) => {
746 let before_ones = x.count_ones();
747 let shifted = (**x) << rhs;
748 let after_ones = x.count_ones();
749 if before_ones != after_ones {
750 halt2!(span, "shl");
751 }
752 shifted.into()
753 }
754 SvmLiteralParam::U32(x) => {
755 let before_ones = x.count_ones();
756 let shifted = (**x) << rhs;
757 let after_ones = x.count_ones();
758 if before_ones != after_ones {
759 halt2!(span, "shl");
760 }
761 shifted.into()
762 }
763 SvmLiteralParam::U64(x) => {
764 let before_ones = x.count_ones();
765 let shifted = (**x) << rhs;
766 let after_ones = x.count_ones();
767 if before_ones != after_ones {
768 halt2!(span, "shl");
769 }
770 shifted.into()
771 }
772 SvmLiteralParam::U128(x) => {
773 let before_ones = x.count_ones();
774 let shifted = (**x) << rhs;
775 let after_ones = x.count_ones();
776 if before_ones != after_ones {
777 halt2!(span, "shl");
778 }
779 shifted.into()
780 }
781 SvmLiteralParam::I8(x) => {
782 let before_ones = x.count_ones();
783 let shifted = (**x) << rhs;
784 let after_ones = x.count_ones();
785 if before_ones != after_ones {
786 halt2!(span, "shl");
787 }
788 shifted.into()
789 }
790 SvmLiteralParam::I16(x) => {
791 let before_ones = x.count_ones();
792 let shifted = (**x) << rhs;
793 let after_ones = x.count_ones();
794 if before_ones != after_ones {
795 halt2!(span, "shl");
796 }
797 shifted.into()
798 }
799 SvmLiteralParam::I32(x) => {
800 let before_ones = x.count_ones();
801 let shifted = (**x) << rhs;
802 let after_ones = x.count_ones();
803 if before_ones != after_ones {
804 halt2!(span, "shl");
805 }
806 shifted.into()
807 }
808 SvmLiteralParam::I64(x) => {
809 let before_ones = x.count_ones();
810 let shifted = (**x) << rhs;
811 let after_ones = x.count_ones();
812 if before_ones != after_ones {
813 halt2!(span, "shl");
814 }
815 shifted.into()
816 }
817 SvmLiteralParam::I128(x) => {
818 let before_ones = x.count_ones();
819 let shifted = (**x) << rhs;
820 let after_ones = x.count_ones();
821 if before_ones != after_ones {
822 halt2!(span, "shl");
823 }
824 shifted.into()
825 }
826 _ => halt2!(span, "Type error"),
827 }
828 }
829
830 BinaryOperation::ShlWrapped => {
831 let rhs: u32 = match rhs {
832 SvmLiteralParam::U8(y) => (**y).into(),
833 SvmLiteralParam::U16(y) => (**y).into(),
834 SvmLiteralParam::U32(y) => **y,
835 _ => halt2!(span, "Type error"),
836 };
837 match lhs {
838 SvmLiteralParam::U8(x) => x.wrapping_shl(rhs).into(),
839 SvmLiteralParam::U16(x) => x.wrapping_shl(rhs).into(),
840 SvmLiteralParam::U32(x) => x.wrapping_shl(rhs).into(),
841 SvmLiteralParam::U64(x) => x.wrapping_shl(rhs).into(),
842 SvmLiteralParam::U128(x) => x.wrapping_shl(rhs).into(),
843 SvmLiteralParam::I8(x) => x.wrapping_shl(rhs).into(),
844 SvmLiteralParam::I16(x) => x.wrapping_shl(rhs).into(),
845 SvmLiteralParam::I32(x) => x.wrapping_shl(rhs).into(),
846 SvmLiteralParam::I64(x) => x.wrapping_shl(rhs).into(),
847 SvmLiteralParam::I128(x) => x.wrapping_shl(rhs).into(),
848 _ => halt2!(span, "Type error"),
849 }
850 }
851
852 BinaryOperation::Shr => {
853 let rhs: u32 = match rhs {
854 SvmLiteralParam::U8(y) => (**y).into(),
855 SvmLiteralParam::U16(y) => (**y).into(),
856 SvmLiteralParam::U32(y) => **y,
857 _ => halt2!(span, "Type error"),
858 };
859
860 match lhs {
861 SvmLiteralParam::U8(_) | SvmLiteralParam::I8(_) if rhs >= 8 => halt2!(span, "shr overflow"),
862 SvmLiteralParam::U16(_) | SvmLiteralParam::I16(_) if rhs >= 16 => halt2!(span, "shr overflow"),
863 SvmLiteralParam::U32(_) | SvmLiteralParam::I32(_) if rhs >= 32 => halt2!(span, "shr overflow"),
864 SvmLiteralParam::U64(_) | SvmLiteralParam::I64(_) if rhs >= 64 => halt2!(span, "shr overflow"),
865 SvmLiteralParam::U128(_) | SvmLiteralParam::I128(_) if rhs >= 128 => halt2!(span, "shr overflow"),
866 SvmLiteralParam::U8(x) => (**x >> rhs).into(),
867 SvmLiteralParam::U16(x) => (**x >> rhs).into(),
868 SvmLiteralParam::U32(x) => (**x >> rhs).into(),
869 SvmLiteralParam::U64(x) => (**x >> rhs).into(),
870 SvmLiteralParam::U128(x) => (**x >> rhs).into(),
871 SvmLiteralParam::I8(x) => (**x >> rhs).into(),
872 SvmLiteralParam::I16(x) => (**x >> rhs).into(),
873 SvmLiteralParam::I32(x) => (**x >> rhs).into(),
874 SvmLiteralParam::I64(x) => (**x >> rhs).into(),
875 SvmLiteralParam::I128(x) => (**x >> rhs).into(),
876 _ => tc_fail2!(),
877 }
878 }
879
880 BinaryOperation::ShrWrapped => {
881 let rhs: u32 = match rhs {
882 SvmLiteralParam::U8(y) => (**y).into(),
883 SvmLiteralParam::U16(y) => (**y).into(),
884 SvmLiteralParam::U32(y) => **y,
885 _ => halt2!(span, "Type error"),
886 };
887
888 match lhs {
889 SvmLiteralParam::U8(x) => (x.wrapping_shr(rhs)).into(),
890 SvmLiteralParam::U16(x) => (x.wrapping_shr(rhs)).into(),
891 SvmLiteralParam::U32(x) => (x.wrapping_shr(rhs)).into(),
892 SvmLiteralParam::U64(x) => (x.wrapping_shr(rhs)).into(),
893 SvmLiteralParam::U128(x) => (x.wrapping_shr(rhs)).into(),
894 SvmLiteralParam::I8(x) => (x.wrapping_shr(rhs)).into(),
895 SvmLiteralParam::I16(x) => (x.wrapping_shr(rhs)).into(),
896 SvmLiteralParam::I32(x) => (x.wrapping_shr(rhs)).into(),
897 SvmLiteralParam::I64(x) => (x.wrapping_shr(rhs)).into(),
898 SvmLiteralParam::I128(x) => (x.wrapping_shr(rhs)).into(),
899 _ => halt2!(span, "Type error"),
900 }
901 }
902
903 BinaryOperation::Sub => {
904 let Some(value) = (match (lhs, rhs) {
905 (SvmLiteralParam::U8(x), SvmLiteralParam::U8(y)) => (**x).checked_sub(**y).map(|z| z.into()),
906 (SvmLiteralParam::U16(x), SvmLiteralParam::U16(y)) => (**x).checked_sub(**y).map(|z| z.into()),
907 (SvmLiteralParam::U32(x), SvmLiteralParam::U32(y)) => (**x).checked_sub(**y).map(|z| z.into()),
908 (SvmLiteralParam::U64(x), SvmLiteralParam::U64(y)) => (**x).checked_sub(**y).map(|z| z.into()),
909 (SvmLiteralParam::U128(x), SvmLiteralParam::U128(y)) => (**x).checked_sub(**y).map(|z| z.into()),
910 (SvmLiteralParam::I8(x), SvmLiteralParam::I8(y)) => (**x).checked_sub(**y).map(|z| z.into()),
911 (SvmLiteralParam::I16(x), SvmLiteralParam::I16(y)) => (**x).checked_sub(**y).map(|z| z.into()),
912 (SvmLiteralParam::I32(x), SvmLiteralParam::I32(y)) => (**x).checked_sub(**y).map(|z| z.into()),
913 (SvmLiteralParam::I64(x), SvmLiteralParam::I64(y)) => (**x).checked_sub(**y).map(|z| z.into()),
914 (SvmLiteralParam::I128(x), SvmLiteralParam::I128(y)) => (**x).checked_sub(**y).map(|z| z.into()),
915 (SvmLiteralParam::Group(x), SvmLiteralParam::Group(y)) => Some((*x - *y).into()),
916 (SvmLiteralParam::Field(x), SvmLiteralParam::Field(y)) => Some((*x - *y).into()),
917 _ => halt2!(span, "Type error"),
918 }) else {
919 halt2!(span, "sub overflow");
920 };
921 value
922 }
923
924 BinaryOperation::SubWrapped => match (lhs, rhs) {
925 (SvmLiteralParam::U8(x), SvmLiteralParam::U8(y)) => (**x).wrapping_sub(**y).into(),
926 (SvmLiteralParam::U16(x), SvmLiteralParam::U16(y)) => (**x).wrapping_sub(**y).into(),
927 (SvmLiteralParam::U32(x), SvmLiteralParam::U32(y)) => (**x).wrapping_sub(**y).into(),
928 (SvmLiteralParam::U64(x), SvmLiteralParam::U64(y)) => (**x).wrapping_sub(**y).into(),
929 (SvmLiteralParam::U128(x), SvmLiteralParam::U128(y)) => (**x).wrapping_sub(**y).into(),
930 (SvmLiteralParam::I8(x), SvmLiteralParam::I8(y)) => (**x).wrapping_sub(**y).into(),
931 (SvmLiteralParam::I16(x), SvmLiteralParam::I16(y)) => (**x).wrapping_sub(**y).into(),
932 (SvmLiteralParam::I32(x), SvmLiteralParam::I32(y)) => (**x).wrapping_sub(**y).into(),
933 (SvmLiteralParam::I64(x), SvmLiteralParam::I64(y)) => (**x).wrapping_sub(**y).into(),
934 (SvmLiteralParam::I128(x), SvmLiteralParam::I128(y)) => (**x).wrapping_sub(**y).into(),
935 _ => halt2!(span, "Type error"),
936 },
937 BinaryOperation::Xor => match (lhs, rhs) {
938 (SvmLiteralParam::Boolean(x), SvmLiteralParam::Boolean(y)) => (**x ^ **y).into(),
939 (SvmLiteralParam::U8(x), SvmLiteralParam::U8(y)) => (**x ^ **y).into(),
940 (SvmLiteralParam::U16(x), SvmLiteralParam::U16(y)) => (**x ^ **y).into(),
941 (SvmLiteralParam::U32(x), SvmLiteralParam::U32(y)) => (**x ^ **y).into(),
942 (SvmLiteralParam::U64(x), SvmLiteralParam::U64(y)) => (**x ^ **y).into(),
943 (SvmLiteralParam::U128(x), SvmLiteralParam::U128(y)) => (**x ^ **y).into(),
944 (SvmLiteralParam::I8(x), SvmLiteralParam::I8(y)) => (**x ^ **y).into(),
945 (SvmLiteralParam::I16(x), SvmLiteralParam::I16(y)) => (**x ^ **y).into(),
946 (SvmLiteralParam::I32(x), SvmLiteralParam::I32(y)) => (**x ^ **y).into(),
947 (SvmLiteralParam::I64(x), SvmLiteralParam::I64(y)) => (**x ^ **y).into(),
948 (SvmLiteralParam::I128(x), SvmLiteralParam::I128(y)) => (**x ^ **y).into(),
949 _ => halt2!(span, "Type error"),
950 },
951 };
952
953 Ok(value)
954}
955
956fn prepare_snarkvm_string(s: &str, suffix: &str) -> String {
958 let (neg, rest) = s.strip_prefix("-").map(|rest| ("-", rest)).unwrap_or(("", s));
960 let mut rest = rest.trim_start_matches('0');
962 if rest.is_empty() {
963 rest = "0";
964 }
965 format!("{neg}{rest}{suffix}")
966}