add function execution to the VM

This commit is contained in:
afonya2 2025-06-03 18:32:52 +02:00
parent 598f4a0cdb
commit a5c2420d20
Signed by: afonya
GPG key ID: EBB9C4CAFAAFB2DC
4 changed files with 82 additions and 26 deletions

View file

@ -28,7 +28,7 @@ pub struct VMMemoryBoolean {
}
#[derive(Debug, Clone)]
pub struct VMMemoryFunction {
function: DecompiledFunction,
pub id: usize,
pub variable_id: u32,
}
#[derive(Debug, Clone)]
@ -65,12 +65,18 @@ struct Variable {
end: usize
}
pub struct CallStack {
func: usize,
return_reg: usize,
pc: usize,
}
pub struct Machine {
pub memory: Vec<VMMemory>,
functions: Vec<DecompiledFunction>,
pub stack: Vec<VMMemory>,
pub registers: Vec<Register>,
pub pc: usize,
pub call_stack: Vec<CallStack>,
}
fn read_be_num(input: &[u8]) -> usize {
@ -280,9 +286,6 @@ fn do_operation_operation(registers: &mut Vec<Register>, memory: &mut Vec<VMMemo
memory.push(VMMemory::Null(VMMemoryNull { variable_id: 0 }));
set_register(registers, Register { id: operation.arg3, pointer: reg3_pointer });
}
if reg3_pointer >= memory.len() || reg3_pointer < 1 {
panic!("Register {} points to an invalid memory location", reg3.unwrap().id);
}
let var_id = match &memory[reg3_pointer] {
VMMemory::String(str) => str.variable_id,
VMMemory::Number(num) => num.variable_id,
@ -394,7 +397,11 @@ impl Machine {
functions: Vec::new(),
stack: Vec::new(),
registers: registers,
pc: 0,
call_stack: vec![CallStack {
func: 0,
return_reg: 0,
pc: 0,
}]
};
}
@ -414,14 +421,19 @@ impl Machine {
}
pub fn run(&mut self) {
let main_func = self.functions.get(0);
if main_func.is_none() {
panic!("No main function found!");
if self.call_stack.len() == 0 {
return;
}
let main_func = main_func.unwrap();
while self.pc < main_func.body.len() {
let operation = &main_func.body[self.pc];
self.pc += 1;
let executed_func = self.functions.get(self.call_stack[self.call_stack.len()-1].func);
if executed_func.is_none() {
panic!("Current function not found!");
}
let mut executed_func = executed_func.unwrap();
let last_stack = self.call_stack.len()-1;
let mut executed_stack = &mut self.call_stack[last_stack];
while executed_stack.pc < executed_func.body.len() {
let operation = &executed_func.body[executed_stack.pc];
executed_stack.pc += 1;
match operation.opcode {
0 => {
//HLT
@ -429,7 +441,7 @@ impl Machine {
},
1 => {
//LDS
let str = main_func.strings.get(&(operation.arg2 as u32));
let str = executed_func.strings.get(&(operation.arg2 as u32));
if str.is_none() {
panic!("String with ID {} not found", operation.arg2);
}
@ -458,7 +470,7 @@ impl Machine {
},
5 => {
//LDF
let func_pos = main_func.functions.get(&(operation.arg2 as u32));
let func_pos = executed_func.functions.get(&(operation.arg2 as u32));
if func_pos.is_none() {
panic!("Function with ID {} not found", operation.arg2);
}
@ -468,7 +480,7 @@ impl Machine {
panic!("Function with position {} not found", func_pos);
}
self.memory.push(VMMemory::Function(VMMemoryFunction {
function: func.unwrap().clone(),
id: *func_pos as usize,
variable_id: 0,
}));
set_register(&mut self.registers, Register { id: operation.arg1, pointer: self.memory.len() - 1 });
@ -570,9 +582,6 @@ impl Machine {
self.memory.push(VMMemory::Null(VMMemoryNull { variable_id: 0 }));
set_register(&mut self.registers, Register { id: operation.arg2 as u8, pointer: reg2_pointer });
}
if reg2_pointer >= self.memory.len() || reg2_pointer < 1 {
panic!("Register {} points to an invalid memory location", reg2.unwrap().id);
}
let var_id = match &self.memory[reg2.unwrap().pointer] {
VMMemory::String(str) => str.variable_id,
VMMemory::Number(num) => num.variable_id,
@ -601,7 +610,7 @@ impl Machine {
},
25 => {
//JMP
self.pc = operation.arg2 as usize;
executed_stack.pc = operation.arg2 as usize;
},
26 => {
//CJP
@ -618,7 +627,7 @@ impl Machine {
match &mem {
VMMemory::Boolean(bool) => {
if bool.value {
self.pc = operation.arg2 as usize;
executed_stack.pc = operation.arg2 as usize;
}
}
_ => panic!("Invalid memory type for CJP operation"),
@ -626,7 +635,27 @@ impl Machine {
},
27 => {
//CAL
//not implemented yet
let reg = get_register_by_id(&self.registers, operation.arg1);
if reg.is_none() {
panic!("Register {} doesn't exist", operation.arg1);
}
let reg = reg.unwrap();
let mem = self.memory.get(reg.pointer);
if mem.is_none() {
panic!("Memory location not found for register");
}
let mem = mem.unwrap();
match mem {
VMMemory::Function(func) => {
self.call_stack.push(CallStack { func: func.id, return_reg: operation.arg2 as usize, pc: 0 });
executed_func = &self.functions[func.id];
let last_stack = self.call_stack.len() - 1;
executed_stack = &mut self.call_stack[last_stack];
},
_ => {
panic!("Unable to call non-function memory type");
}
}
},
28 => {
//PSH
@ -644,7 +673,27 @@ impl Machine {
},
29 => {
//RET
//not implemented yet
let target_reg = get_register_by_id(&self.registers, executed_stack.return_reg as u8);
let ret_reg = get_register_by_id(&self.registers, operation.arg1);
if target_reg.is_none() || ret_reg.is_none() {
panic!("Return register or target register not found");
}
let ret_mem = self.memory.get(ret_reg.unwrap().pointer);
if ret_mem.is_none() {
panic!("Memory location not found for return register");
}
let return_value = ret_mem.unwrap().clone();
let target_reg_pointer = self.memory.len();
self.memory.push(VMMemory::Null(VMMemoryNull { variable_id: 0 }));
set_register(&mut self.registers, Register { id: executed_stack.return_reg as u8, pointer: target_reg_pointer });
self.memory[target_reg_pointer] = return_value;
self.call_stack.pop();
if self.call_stack.len() < 1 {
return;
}
let last_stack = self.call_stack.len() - 1;
executed_func = &self.functions[self.call_stack[last_stack].func];
executed_stack = &mut self.call_stack[last_stack];
},
30 => {
//not implemented yet