Dispatch the next opcode, stop at the given frame count. When dispatch in step() function, the stop_at_frame_count is 0. When dispatch in eval_function(), the stop_at_frame_count is the frame count before to call eval_function(). This is used to exit the frame call after the chunks of that function is finished.
(
&mut self,
stop_at_frame_count: usize,
)
| 317 | // When dispatch in eval_function(), the stop_at_frame_count is the frame count before to call eval_function(). |
| 318 | // This is used to exit the frame call after the chunks of that function is finished. |
| 319 | pub fn dispatch_next( |
| 320 | &mut self, |
| 321 | stop_at_frame_count: usize, |
| 322 | ) -> Result<Option<Value<'gc>>, VmError> { |
| 323 | // Debug stack info |
| 324 | #[cfg(feature = "debug")] |
| 325 | self.print_stack(); |
| 326 | let frame = self.current_frame(); |
| 327 | // Disassemble instruction for debug |
| 328 | #[cfg(feature = "debug")] |
| 329 | frame.disassemble_instruction(frame.ip); |
| 330 | match frame.next_opcode() { |
| 331 | OpCode::Constant(byte) => { |
| 332 | let constant = frame.read_constant(byte); |
| 333 | self.push_stack(constant); |
| 334 | } |
| 335 | OpCode::Add => match (self.peek(0), self.peek(1)) { |
| 336 | (Value::Number(_), Value::Number(_)) => { |
| 337 | binary_op!(self, +); |
| 338 | } |
| 339 | (Value::String(_), Value::String(_)) |
| 340 | | (Value::IoString(_), Value::IoString(_)) |
| 341 | | (Value::String(_), Value::IoString(_)) |
| 342 | | (Value::IoString(_), Value::String(_)) => { |
| 343 | let b = self.pop_stack().as_string()?; |
| 344 | let a = self.pop_stack().as_string()?; |
| 345 | let s = self.intern(format!("{a}{b}").as_bytes()); |
| 346 | self.push_stack(s.into()); |
| 347 | } |
| 348 | _ => { |
| 349 | return Err( |
| 350 | self.runtime_error("Operands must be two numbers or two strings.".into()) |
| 351 | ); |
| 352 | } |
| 353 | }, |
| 354 | OpCode::Subtract => { |
| 355 | binary_op!(self, -); |
| 356 | } |
| 357 | OpCode::Multiply => { |
| 358 | binary_op!(self, *); |
| 359 | } |
| 360 | OpCode::Divide => { |
| 361 | binary_op!(self, /); |
| 362 | } |
| 363 | OpCode::Modulo => { |
| 364 | binary_op!(self, %); |
| 365 | } |
| 366 | OpCode::Power => { |
| 367 | let b = self |
| 368 | .pop_stack() |
| 369 | .as_number() |
| 370 | .map_err(|_| self.runtime_error(NUMBER_OPERATOR_ERROR.into()))?; |
| 371 | let a = self |
| 372 | .pop_stack() |
| 373 | .as_number() |
| 374 | .map_err(|_| self.runtime_error(NUMBER_OPERATOR_ERROR.into()))?; |
| 375 | |
| 376 | // Use f64's powf method for power operation |
no test coverage detected