| 294 | } |
| 295 | |
| 296 | pub fn eval( |
| 297 | &self, |
| 298 | argc: u8, |
| 299 | cur_frame: &mut Frame, |
| 300 | vm: &mut VirtualMachine, |
| 301 | other_args: &PartialFunctionApplication, |
| 302 | discard_result: bool, |
| 303 | ) -> ExecutionResult<CallResult> { |
| 304 | let mut new_frame = Frame::new_with_function(self.clone()); |
| 305 | |
| 306 | let other_argc = other_args.suffix_args.len() as u8; |
| 307 | let effective_argc = argc + other_argc; |
| 308 | let fixed_arity = self.arity().required + self.arity().optional; |
| 309 | |
| 310 | if self.attribute().is_vararg() { |
| 311 | if effective_argc < self.arity().required { |
| 312 | return Err( |
| 313 | crate::error::vm_error::VmErrorReason::MismatchedArgumentCount( |
| 314 | self.arity().required as usize, |
| 315 | effective_argc as usize, |
| 316 | ) |
| 317 | .into(), |
| 318 | ); |
| 319 | } |
| 320 | |
| 321 | let mut popped_args = cur_frame.stack.pop_count(argc as usize); |
| 322 | let split_at = (fixed_arity - other_argc) as usize; |
| 323 | let varargs = popped_args.split_off(split_at.min(popped_args.len())); |
| 324 | |
| 325 | let l = List::default(); |
| 326 | for arg in varargs { |
| 327 | l.append(arg); |
| 328 | } |
| 329 | |
| 330 | new_frame.stack.push(super::RuntimeValue::List(l)); |
| 331 | for arg in popped_args.into_iter().rev() { |
| 332 | new_frame.stack.push(arg); |
| 333 | } |
| 334 | } else { |
| 335 | if effective_argc < self.arity().required { |
| 336 | return Err( |
| 337 | crate::error::vm_error::VmErrorReason::MismatchedArgumentCount( |
| 338 | self.arity().required as usize, |
| 339 | effective_argc as usize, |
| 340 | ) |
| 341 | .into(), |
| 342 | ); |
| 343 | } |
| 344 | if effective_argc > fixed_arity { |
| 345 | return Err( |
| 346 | crate::error::vm_error::VmErrorReason::MismatchedArgumentCount( |
| 347 | fixed_arity as usize, |
| 348 | effective_argc as usize, |
| 349 | ) |
| 350 | .into(), |
| 351 | ); |
| 352 | } |
| 353 | |