MCPcopy Create free account
hub / github.com/dylan-sutton-chavez/edge-python / mul_vals

Method mul_vals

compiler/src/modules/vm/ops.rs:498–556  ·  view source on GitHub ↗
(&mut self, a: Val, b: Val)

Source from the content-addressed store, hash-verified

496 }
497
498 pub fn mul_vals(&mut self, a: Val, b: Val) -> Result<Val, VmErr> {
499 if a.is_int() && b.is_int()
500 && let Some(r) = a.as_int().checked_mul(b.as_int())
501 && (Val::INT_MIN..=Val::INT_MAX).contains(&r) {
502 return Ok(Val::int(r));
503 }
504 if let Some((af, bf)) = coerce_floats(a, b, &self.heap) { return Ok(Val::float(af * bf)); }
505 // Numeric multiply wins over sequence repetition when both sides are int-like.
506 if let (Some(ai), Some(bi)) = (as_i128(a, &self.heap), as_i128(b, &self.heap)) {
507 return self.int_to_val(ai.checked_mul(bi));
508 }
509 // Sequence repetition: str/list/tuple * int (count clamped to i64).
510 let (seq_val, count) = if a.is_heap() && b.is_int() && !matches!(self.heap.get(a), HeapObj::LongInt(_)) {
511 (a, b.as_int())
512 } else if a.is_int() && b.is_heap() && !matches!(self.heap.get(b), HeapObj::LongInt(_)) {
513 (b, a.as_int())
514 } else {
515 return Err(VmErr::TypeMsg(s!("unsupported operand type(s) for *: '", str self.type_name(a), "' and '", str self.type_name(b), "'")));
516 };
517 let n = count.max(0) as usize;
518 // Charge the fill up front so repeated `[x]*n` is bounded by the op budget, not just heap.
519 let fill_cost = match self.heap.get(seq_val) {
520 HeapObj::Str(s) => s.len().checked_mul(n),
521 HeapObj::List(rc) => rc.borrow().len().checked_mul(n),
522 HeapObj::Tuple(v) => v.len().checked_mul(n),
523 _ => None,
524 };
525 if let Some(c) = fill_cost && c <= self.heap.limit() { self.charge_steps(c)?; }
526 match self.heap.get(seq_val) {
527 HeapObj::Str(s) => {
528 let bytes = s.len().checked_mul(n).ok_or(cold_overflow())?;
529 if bytes > self.heap.limit() { return Err(cold_heap()); }
530 let r = s.repeat(n);
531 return self.heap.alloc(HeapObj::Str(r));
532 }
533 HeapObj::List(rc) => {
534 let src = rc.borrow().clone();
535 // Empty source: result is empty for any n, so skip the n-iteration loop.
536 if src.is_empty() { return self.heap.alloc(HeapObj::List(Rc::new(RefCell::new(Vec::new())))); }
537 let cap = src.len().checked_mul(n).ok_or(cold_overflow())?;
538 if cap > self.heap.limit() { return Err(cold_heap()); }
539 let mut out = Vec::with_capacity(cap);
540 for _ in 0..n { out.extend_from_slice(&src); }
541 return self.heap.alloc(HeapObj::List(Rc::new(RefCell::new(out))));
542 }
543 HeapObj::Tuple(v) => {
544 let src = v.clone();
545 // Empty source: result is empty for any n, so skip the n-iteration loop.
546 if src.is_empty() { return self.heap.alloc(HeapObj::Tuple(Vec::new())); }
547 let cap = src.len().checked_mul(n).ok_or(cold_overflow())?;
548 if cap > self.heap.limit() { return Err(cold_heap()); }
549 let mut out = Vec::with_capacity(cap);
550 for _ in 0..n { out.extend_from_slice(&src); }
551 return self.heap.alloc(HeapObj::Tuple(out));
552 }
553 _ => {}
554 }
555 Err(VmErr::TypeMsg(s!("unsupported operand type(s) for *: '", str self.type_name(a), "' and '", str self.type_name(b), "'")))

Callers 1

handle_arithMethod · 0.80

Calls 15

coerce_floatsFunction · 0.85
as_i128Function · 0.85
cold_overflowFunction · 0.85
cold_heapFunction · 0.85
is_intMethod · 0.80
as_intMethod · 0.80
int_to_valMethod · 0.80
is_heapMethod · 0.80
borrowMethod · 0.80
limitMethod · 0.80
charge_stepsMethod · 0.80
containsMethod · 0.45

Tested by

no test coverage detected