add function execution to the VM
This commit is contained in:
parent
598f4a0cdb
commit
a5c2420d20
4 changed files with 82 additions and 26 deletions
|
@ -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 });
|
||||
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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue