diff --git a/src/virtualmachine.rs b/src/virtualmachine.rs index 8657f3a..c307036 100644 --- a/src/virtualmachine.rs +++ b/src/virtualmachine.rs @@ -7,6 +7,7 @@ pub enum VMMemory { String(VMMemoryString), Number(VMMemoryNumber), Boolean(VMMemoryBoolean), + Function(VMMemoryFunction), Null(VMMemoryNull), } @@ -26,6 +27,11 @@ struct VMMemoryBoolean { variable_id: u32, } #[derive(Debug, Clone)] +struct VMMemoryFunction { + function: DecompiledFunction, + variable_id: u32, +} +#[derive(Debug, Clone)] struct VMMemoryNull { variable_id: u32, } @@ -51,7 +57,7 @@ struct DecompiledOperation { arg3: u8, } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct Register { id: u8, pointer: usize @@ -157,6 +163,152 @@ fn set_register(registers: &mut Vec, new_register: Register) { } } +fn get_mem_pos_by_var_id(memory: &Vec, var_id: u32) -> Option { + for i in 0..memory.len() { + match &memory[i] { + VMMemory::String(str) if str.variable_id == var_id => return Some(i), + VMMemory::Number(num) if num.variable_id == var_id => return Some(i), + VMMemory::Boolean(bool) if bool.variable_id == var_id => return Some(i), + VMMemory::Null(null) if null.variable_id == var_id => return Some(i), + VMMemory::Function(func) if func.variable_id == var_id => return Some(i), + _ => continue + } + } + None +} + +fn do_operation_operation(registers: &mut Vec, memory: &mut Vec, operation: &DecompiledOperation) { + let reg1 = get_register_by_id(registers, operation.arg1); + let reg2 = get_register_by_id(registers, operation.arg2 as u8); + let reg3 = get_register_by_id(registers, operation.arg3); + let mem1 = get_mem_pos_by_var_id(memory, reg1.unwrap().pointer as u32); + let mem2 = get_mem_pos_by_var_id(memory, reg2.unwrap().pointer as u32); + let mut mem3 = get_mem_pos_by_var_id(memory, reg3.unwrap().pointer as u32); + if mem1.is_none() || mem2.is_none() { + panic!("Memory location not found for registers"); + } + let mem1 = mem1.unwrap(); + if mem3.is_none() { + match operation.opcode { + 10 => { + match memory[mem1] { + VMMemory::String(_) => { + memory.push(VMMemory::String(VMMemoryString { value: String::new(), variable_id: 0 })); + set_register(registers, Register { id: operation.arg3, pointer: memory.len() - 1 }); + mem3 = Some(memory.len() - 1); + } + VMMemory::Number(_) => { + memory.push(VMMemory::Number(VMMemoryNumber { value: 0, variable_id: 0 })); + set_register(registers, Register { id: operation.arg3, pointer: memory.len() - 1 }); + mem3 = Some(memory.len() - 1); + } + _ => { + panic!("Invalid memory type for operation"); + } + } + }, + 11 | 12 | 13 | 14 | 15 => { + memory.push(VMMemory::Number(VMMemoryNumber { value: 0, variable_id: 0 })); + set_register(registers, Register { id: operation.arg3, pointer: memory.len() - 1 }); + mem3 = Some(memory.len() - 1); + }, + 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 => { + memory.push(VMMemory::Boolean(VMMemoryBoolean { value: false, variable_id: 0 })); + set_register(registers, Register { id: operation.arg3, pointer: memory.len() - 1 }); + mem3 = Some(memory.len() - 1); + }, + _ => {} + } + } + let mem2 = mem2.unwrap(); + let mem3 = mem3.unwrap(); + let temp_mem = memory.clone(); + match (&temp_mem[mem1], &temp_mem[mem2], &mut memory[mem3]) { + (VMMemory::Number(num1), VMMemory::Number(num2), VMMemory::Number(num3)) => { + match operation.opcode { + 10 => { + num3.value = num1.value + num2.value; + }, + 11 => { + num3.value = num1.value - num2.value; + }, + 12 => { + num3.value = num1.value * num2.value; + }, + 13 => { + if num2.value == 0 { + panic!("Division by zero"); + } + num3.value = num1.value / num2.value; + }, + 14 => { + num3.value = num1.value.pow(num2.value as u32); + }, + 15 => { + num3.value = num1.value % num2.value; + }, + _ => { + panic!("Invalid operation for number operation") + } + } + }, + (VMMemory::Number(num1), VMMemory::Number(num2), VMMemory::Boolean(bool3)) => { + match operation.opcode { + 18 => { + bool3.value = num1.value == num2.value; + }, + 19 => { + bool3.value = num1.value != num2.value; + }, + 20 => { + bool3.value = num1.value > num2.value; + }, + 21 => { + bool3.value = num1.value >= num2.value; + }, + 22 => { + bool3.value = num1.value < num2.value; + }, + 23 => { + bool3.value = num1.value <= num2.value; + }, + _ => panic!("Invalid operation for boolean operation"), + } + }, + (VMMemory::String(str1), VMMemory::String(str2), VMMemory::Boolean(bool3)) => { + match operation.opcode { + 18 => { + bool3.value = str1.value == str2.value; + }, + 19 => { + bool3.value = str1.value != str2.value; + }, + _ => panic!("Invalid operation for string operation"), + } + }, + (VMMemory::String(str1), VMMemory::String(str2), VMMemory::String(str3)) => { + match operation.opcode { + 10 => { + str3.value = str1.value.clone() + &str2.value; + }, + _ => panic!("Invalid operation for string operation"), + } + }, + (VMMemory::Boolean(bool1), VMMemory::Boolean(bool2), VMMemory::Boolean(bool3)) => { + match operation.opcode { + 16 => { + bool3.value = bool1.value && bool2.value; + }, + 17 => { + bool3.value = bool1.value || bool2.value; + }, + _ => panic!("Invalid operation for boolean operation"), + } + }, + _ => panic!("Invalid memory types for operation"), + } +} + impl Machine { pub fn new() -> Self { let mut registers = Vec::new(); @@ -257,7 +409,8 @@ impl Machine { if main.is_none() { panic!("Main file not found"); } - let main_func = get_function_by_name(&main.unwrap(), "main"); + let main = main.unwrap(); + let main_func = get_function_by_name(&main, "main"); if main_func.is_none() { panic!("Main function not found"); } @@ -270,11 +423,57 @@ impl Machine { //HLT return; }, + 1 => { + //LDS + let str = main_func.strings.get(&(operation.arg2 as u32)); + if str.is_none() { + panic!("String with ID {} not found", operation.arg2); + } + let str = str.unwrap(); + self.memory.push(VMMemory::String(VMMemoryString { value: str.clone(), variable_id: 0 })); + set_register(&mut self.registers, Register { id: operation.arg1, pointer: self.memory.len() - 1 }); + }, + 2 => { + //LDM + let mem = get_mem_pos_by_var_id(&self.memory, operation.arg2 as u32); + if mem.is_none() { + panic!("Memory with variable ID {} not found", operation.arg2); + } + let mem = mem.unwrap(); + set_register(&mut self.registers, Register { id: operation.arg1, pointer: mem }); + }, 3 => { //LDI self.memory.push(VMMemory::Number(VMMemoryNumber { value: operation.arg2, variable_id: 0 })); set_register(&mut self.registers, Register { id: operation.arg1, pointer: self.memory.len() - 1 }); }, + 4 => { + //LDB + self.memory.push(VMMemory::Boolean(VMMemoryBoolean { value: operation.arg2 != 0, variable_id: 0 })); + set_register(&mut self.registers, Register { id: operation.arg1, pointer: self.memory.len() - 1 }); + }, + 5 => { + //LDF + let func_pos = main_func.functions.get(&(operation.arg2 as u32)); + if func_pos.is_none() { + panic!("Function with ID {} not found", operation.arg2); + } + let func_pos = func_pos.unwrap(); + let func = main.functions.get(*func_pos as usize); + if func.is_none() { + panic!("Function with position {} not found", func_pos); + } + self.memory.push(VMMemory::Function(VMMemoryFunction { + function: func.unwrap().clone(), + variable_id: 0, + })); + set_register(&mut self.registers, Register { id: operation.arg1, pointer: self.memory.len() - 1 }); + }, + 6 => { + //LDN + self.memory.push(VMMemory::Null(VMMemoryNull { variable_id: 0 })); + set_register(&mut self.registers, Register { id: operation.arg1, pointer: self.memory.len() - 1 }); + }, 7 => { //ASS let reg = get_register_by_id(&self.registers, operation.arg1); @@ -298,8 +497,28 @@ impl Machine { VMMemory::Null(null) => { null.variable_id = operation.arg2 as u32; }, + VMMemory::Function(func) => { + func.variable_id = operation.arg2 as u32; + }, } }, + 8 => { + //UNB + set_register(&mut self.registers, Register { id: operation.arg1, pointer: 0 }); + }, + 9 => { + //MOV + let temp_regs = self.registers.clone(); + let reg1 = get_register_by_id(&temp_regs, operation.arg1); + if reg1.is_none() { + panic!("Register {} not found", operation.arg1); + } + let reg1 = reg1.unwrap(); + set_register(&mut self.registers, Register { id: operation.arg2 as u8, pointer: reg1.pointer }); + }, + 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 => { + do_operation_operation(&mut self.registers, &mut self.memory, operation); + }, 29 => { //RET //not implemented yet