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

@ -217,7 +217,12 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, va
ops.push(Operation { opcode: 28, arg1: Some(arg_reg), arg2: None, arg3: None }); 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 }); 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) => { 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); 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);

View file

@ -133,7 +133,7 @@ fn main() {
vm.run(); vm.run();
println!("\n"); println!("\n");
println!("Registers: {:?}", vm.registers); println!("Registers: {:?}", vm.registers);
println!("Program Counter: {}", vm.pc); println!("Stack: {:?}", vm.stack);
println!("Memory: {:?}", vm.memory); println!("Memory: {:?}", vm.memory);
/*let mut executor = Executor::new(ast, 100); /*let mut executor = Executor::new(ast, 100);
executor.resume(); executor.resume();

View file

@ -28,7 +28,7 @@ pub struct VMMemoryBoolean {
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct VMMemoryFunction { pub struct VMMemoryFunction {
function: DecompiledFunction, pub id: usize,
pub variable_id: u32, pub variable_id: u32,
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -65,12 +65,18 @@ struct Variable {
end: usize end: usize
} }
pub struct CallStack {
func: usize,
return_reg: usize,
pc: usize,
}
pub struct Machine { pub struct Machine {
pub memory: Vec<VMMemory>, pub memory: Vec<VMMemory>,
functions: Vec<DecompiledFunction>, functions: Vec<DecompiledFunction>,
pub stack: Vec<VMMemory>, pub stack: Vec<VMMemory>,
pub registers: Vec<Register>, pub registers: Vec<Register>,
pub pc: usize, pub call_stack: Vec<CallStack>,
} }
fn read_be_num(input: &[u8]) -> usize { 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 })); memory.push(VMMemory::Null(VMMemoryNull { variable_id: 0 }));
set_register(registers, Register { id: operation.arg3, pointer: reg3_pointer }); 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] { let var_id = match &memory[reg3_pointer] {
VMMemory::String(str) => str.variable_id, VMMemory::String(str) => str.variable_id,
VMMemory::Number(num) => num.variable_id, VMMemory::Number(num) => num.variable_id,
@ -394,7 +397,11 @@ impl Machine {
functions: Vec::new(), functions: Vec::new(),
stack: Vec::new(), stack: Vec::new(),
registers: registers, 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) { pub fn run(&mut self) {
let main_func = self.functions.get(0); if self.call_stack.len() == 0 {
if main_func.is_none() { return;
panic!("No main function found!");
} }
let main_func = main_func.unwrap(); let executed_func = self.functions.get(self.call_stack[self.call_stack.len()-1].func);
while self.pc < main_func.body.len() { if executed_func.is_none() {
let operation = &main_func.body[self.pc]; panic!("Current function not found!");
self.pc += 1; }
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 { match operation.opcode {
0 => { 0 => {
//HLT //HLT
@ -429,7 +441,7 @@ impl Machine {
}, },
1 => { 1 => {
//LDS //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() { if str.is_none() {
panic!("String with ID {} not found", operation.arg2); panic!("String with ID {} not found", operation.arg2);
} }
@ -458,7 +470,7 @@ impl Machine {
}, },
5 => { 5 => {
//LDF //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() { if func_pos.is_none() {
panic!("Function with ID {} not found", operation.arg2); panic!("Function with ID {} not found", operation.arg2);
} }
@ -468,7 +480,7 @@ impl Machine {
panic!("Function with position {} not found", func_pos); panic!("Function with position {} not found", func_pos);
} }
self.memory.push(VMMemory::Function(VMMemoryFunction { self.memory.push(VMMemory::Function(VMMemoryFunction {
function: func.unwrap().clone(), id: *func_pos as usize,
variable_id: 0, variable_id: 0,
})); }));
set_register(&mut self.registers, Register { id: operation.arg1, pointer: self.memory.len() - 1 }); 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 })); self.memory.push(VMMemory::Null(VMMemoryNull { variable_id: 0 }));
set_register(&mut self.registers, Register { id: operation.arg2 as u8, pointer: reg2_pointer }); 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] { let var_id = match &self.memory[reg2.unwrap().pointer] {
VMMemory::String(str) => str.variable_id, VMMemory::String(str) => str.variable_id,
VMMemory::Number(num) => num.variable_id, VMMemory::Number(num) => num.variable_id,
@ -601,7 +610,7 @@ impl Machine {
}, },
25 => { 25 => {
//JMP //JMP
self.pc = operation.arg2 as usize; executed_stack.pc = operation.arg2 as usize;
}, },
26 => { 26 => {
//CJP //CJP
@ -618,7 +627,7 @@ impl Machine {
match &mem { match &mem {
VMMemory::Boolean(bool) => { VMMemory::Boolean(bool) => {
if bool.value { if bool.value {
self.pc = operation.arg2 as usize; executed_stack.pc = operation.arg2 as usize;
} }
} }
_ => panic!("Invalid memory type for CJP operation"), _ => panic!("Invalid memory type for CJP operation"),
@ -626,7 +635,27 @@ impl Machine {
}, },
27 => { 27 => {
//CAL //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 => { 28 => {
//PSH //PSH
@ -644,7 +673,27 @@ impl Machine {
}, },
29 => { 29 => {
//RET //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 => { 30 => {
//not implemented yet //not implemented yet

View file

@ -1,4 +1,6 @@
gethelj a = 1 gethelj a = 1
gethelj b = lőcsve() { gethelj b = lőcsve() {
gethelj a = 2 gethelj a = 2
reti 6
} }
gethelj c = b()