(
&mut self,
function: &Gc<'gc, Function<'gc>>,
args_count: u8,
keyword_args_count: u8,
)
| 1547 | } |
| 1548 | |
| 1549 | fn prepare_args( |
| 1550 | &mut self, |
| 1551 | function: &Gc<'gc, Function<'gc>>, |
| 1552 | args_count: u8, |
| 1553 | keyword_args_count: u8, |
| 1554 | ) -> Result<Vec<Value<'gc>>, VmError> { |
| 1555 | let total_args = args_count + keyword_args_count; // Count keyword args too |
| 1556 | |
| 1557 | // For functions without keyword args or default values |
| 1558 | if function.arity == function.max_arity && total_args != function.arity { |
| 1559 | return Err(self.runtime_error( |
| 1560 | format!( |
| 1561 | "Expected {} arguments but got {}.", |
| 1562 | function.arity, total_args, |
| 1563 | ) |
| 1564 | .into(), |
| 1565 | )); |
| 1566 | } |
| 1567 | |
| 1568 | if self.frame_count == FRAME_MAX_SIZE { |
| 1569 | return Err(self.runtime_error("Stack overflow.".into())); |
| 1570 | } |
| 1571 | |
| 1572 | let max_arity = function.max_arity as usize; |
| 1573 | let mut final_args = vec![Value::Nil; max_arity]; |
| 1574 | |
| 1575 | // Copy positional arguments |
| 1576 | let total_args = args_count as usize; |
| 1577 | let keyword_slots = keyword_args_count as usize * 2; |
| 1578 | |
| 1579 | if total_args > 0 { |
| 1580 | let arg_start = self.stack_top - total_args - keyword_slots; |
| 1581 | final_args[..total_args] |
| 1582 | .copy_from_slice(&self.stack[arg_start..(total_args + arg_start)]); |
| 1583 | } |
| 1584 | |
| 1585 | // Process keyword arguments |
| 1586 | if keyword_args_count > 0 { |
| 1587 | let kw_start = self.stack_top - keyword_slots; |
| 1588 | for i in 0..keyword_args_count as usize { |
| 1589 | let idx = kw_start + i * 2; |
| 1590 | let name = self.stack[idx].as_string().map_err(|_| { |
| 1591 | self.runtime_error("Keyword argument name must be a string.".into()) |
| 1592 | })?; |
| 1593 | let value = self.stack[idx + 1]; |
| 1594 | |
| 1595 | if let Some(param) = function.params.get(&name) { |
| 1596 | let pos = param.position as usize; |
| 1597 | if pos < total_args { |
| 1598 | return Err(self.runtime_error( |
| 1599 | format!("Keyword argument '{}' was already specified as positional argument.", name) |
| 1600 | .into() |
| 1601 | )); |
| 1602 | } |
| 1603 | final_args[pos] = value; |
| 1604 | } else { |
| 1605 | return Err( |
| 1606 | self.runtime_error(format!("Unknown keyword argument '{}'.", name).into()) |
no test coverage detected