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 });
|
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);
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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
|
||||||
|
|
2
test.as
2
test.as
|
@ -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()
|
Loading…
Add table
Add a link
Reference in a new issue