From a5c2420d20f3b9b20c2083b9da53957811ebf356 Mon Sep 17 00:00:00 2001 From: afonya2 Date: Tue, 3 Jun 2025 18:32:52 +0200 Subject: [PATCH] add function execution to the VM --- src/compiler.rs | 7 +++- src/main.rs | 2 +- src/virtualmachine.rs | 95 ++++++++++++++++++++++++++++++++----------- test.as | 4 +- 4 files changed, 82 insertions(+), 26 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index 638e519..ca14417 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -217,7 +217,12 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec, va ops.push(Operation { opcode: 28, arg1: Some(arg_reg), arg2: None, arg3: None }); set_register(registers, RegisterState { id: arg_reg, used: false, variable: 0, last_used: 0 }); } - ops.push(Operation { opcode: 27, arg1: Some(func), arg2: None, arg3: None }); + let ret_reg = allocate_register(registers); + if ret_reg.unbind_before { + ops.push(Operation { opcode: 8, arg1: Some(ret_reg.register), arg2: None, arg3: None }); + } + ops.push(Operation { opcode: 27, arg1: Some(func), arg2: Some(ret_reg.register as i64), arg3: None }); + return ret_reg.register; }, ASTPart::If(if_part) => { let condition_reg = do_ast_op(*if_part.condition, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers); diff --git a/src/main.rs b/src/main.rs index 576ca01..d58fd40 100644 --- a/src/main.rs +++ b/src/main.rs @@ -133,7 +133,7 @@ fn main() { vm.run(); println!("\n"); println!("Registers: {:?}", vm.registers); - println!("Program Counter: {}", vm.pc); + println!("Stack: {:?}", vm.stack); println!("Memory: {:?}", vm.memory); /*let mut executor = Executor::new(ast, 100); executor.resume(); diff --git a/src/virtualmachine.rs b/src/virtualmachine.rs index f424259..96bcd2b 100644 --- a/src/virtualmachine.rs +++ b/src/virtualmachine.rs @@ -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, functions: Vec, pub stack: Vec, pub registers: Vec, - pub pc: usize, + pub call_stack: Vec, } fn read_be_num(input: &[u8]) -> usize { @@ -280,9 +286,6 @@ fn do_operation_operation(registers: &mut Vec, memory: &mut Vec= 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 diff --git a/test.as b/test.as index b6fe0a5..e64ebb0 100644 --- a/test.as +++ b/test.as @@ -1,4 +1,6 @@ gethelj a = 1 gethelj b = lőcsve() { gethelj a = 2 -} \ No newline at end of file + reti 6 +} +gethelj c = b() \ No newline at end of file