use crate::classfile::{ JavaClassFile, AttributeData }; #[derive(Copy, Clone, Debug)] pub enum Value { Boolean(bool), Byte(u8), Char(u16), Short(u16), Int(u32), Float(u32), Reference(u32), ReturnAddress(u32), Double0(u32), Double1(u32), Long0(u32), Long1(u32), Empty(), } #[derive(Debug)] pub struct OperandStack { stack: Box<[Value]>, depth: u16, } impl OperandStack { fn new(size: u16) -> Self { return OperandStack { stack: vec![Value::Empty(); size.into()].into_boxed_slice(), depth: 0, } } } #[derive(Debug)] pub struct StackFrame { pub locals: Box<[Value]>, pub operand_stack: OperandStack, pub class_index: usize, pub method_index: u16, pub instruction_pointer: u32, } impl StackFrame { pub fn new(classfile: &JavaClassFile, class_index: usize, method_index: u16, arguments: &[Value]) -> Self { let method_info = &classfile.methods[method_index as usize]; let code_data = match &method_info.attributes[method_info.code_attribute_index].data { AttributeData::Code(data) => data, _ => unreachable!(), }; let mut locals = vec![Value::Empty(); code_data.max_locals.into()].into_boxed_slice(); assert!(locals.len() >= arguments.len()); for (index, v) in arguments.iter().enumerate() { locals[index] = *v; } StackFrame { locals, operand_stack: OperandStack::new(code_data.max_stack), class_index, method_index, instruction_pointer: 0, } } }