added a few more operations to the VM
This commit is contained in:
parent
3695f409db
commit
7c2c29fb1a
1 changed files with 221 additions and 2 deletions
|
@ -7,6 +7,7 @@ pub enum VMMemory {
|
||||||
String(VMMemoryString),
|
String(VMMemoryString),
|
||||||
Number(VMMemoryNumber),
|
Number(VMMemoryNumber),
|
||||||
Boolean(VMMemoryBoolean),
|
Boolean(VMMemoryBoolean),
|
||||||
|
Function(VMMemoryFunction),
|
||||||
Null(VMMemoryNull),
|
Null(VMMemoryNull),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,6 +27,11 @@ struct VMMemoryBoolean {
|
||||||
variable_id: u32,
|
variable_id: u32,
|
||||||
}
|
}
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
struct VMMemoryFunction {
|
||||||
|
function: DecompiledFunction,
|
||||||
|
variable_id: u32,
|
||||||
|
}
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
struct VMMemoryNull {
|
struct VMMemoryNull {
|
||||||
variable_id: u32,
|
variable_id: u32,
|
||||||
}
|
}
|
||||||
|
@ -51,7 +57,7 @@ struct DecompiledOperation {
|
||||||
arg3: u8,
|
arg3: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Register {
|
pub struct Register {
|
||||||
id: u8,
|
id: u8,
|
||||||
pointer: usize
|
pointer: usize
|
||||||
|
@ -157,6 +163,152 @@ fn set_register(registers: &mut Vec<Register>, new_register: Register) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_mem_pos_by_var_id(memory: &Vec<VMMemory>, var_id: u32) -> Option<usize> {
|
||||||
|
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<Register>, memory: &mut Vec<VMMemory>, 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 {
|
impl Machine {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let mut registers = Vec::new();
|
let mut registers = Vec::new();
|
||||||
|
@ -257,7 +409,8 @@ impl Machine {
|
||||||
if main.is_none() {
|
if main.is_none() {
|
||||||
panic!("Main file not found");
|
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() {
|
if main_func.is_none() {
|
||||||
panic!("Main function not found");
|
panic!("Main function not found");
|
||||||
}
|
}
|
||||||
|
@ -270,11 +423,57 @@ impl Machine {
|
||||||
//HLT
|
//HLT
|
||||||
return;
|
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 => {
|
3 => {
|
||||||
//LDI
|
//LDI
|
||||||
self.memory.push(VMMemory::Number(VMMemoryNumber { value: operation.arg2, variable_id: 0 }));
|
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 });
|
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 => {
|
7 => {
|
||||||
//ASS
|
//ASS
|
||||||
let reg = get_register_by_id(&self.registers, operation.arg1);
|
let reg = get_register_by_id(&self.registers, operation.arg1);
|
||||||
|
@ -298,8 +497,28 @@ impl Machine {
|
||||||
VMMemory::Null(null) => {
|
VMMemory::Null(null) => {
|
||||||
null.variable_id = operation.arg2 as u32;
|
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 => {
|
29 => {
|
||||||
//RET
|
//RET
|
||||||
//not implemented yet
|
//not implemented yet
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue