added tables to the execution part
This commit is contained in:
parent
6caafe77d0
commit
4faabe0d9c
3 changed files with 182 additions and 9 deletions
|
@ -177,7 +177,7 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, va
|
||||||
if reg.unbind_before {
|
if reg.unbind_before {
|
||||||
ops.push(Operation { opcode: 8, arg1: Some(reg.register), arg2: None, arg3: None });
|
ops.push(Operation { opcode: 8, arg1: Some(reg.register), arg2: None, arg3: None });
|
||||||
}
|
}
|
||||||
ops.push(Operation { opcode: 6, arg1: Some(reg.register), arg2: None, arg3: None });
|
ops.push(Operation { opcode: 6, arg1: Some(reg.register), arg2: Some(0), arg3: None });
|
||||||
set_register(registers, RegisterState { id: reg.register, used: true, variable: 0, last_used: *op_count });
|
set_register(registers, RegisterState { id: reg.register, used: true, variable: 0, last_used: *op_count });
|
||||||
return reg.register;
|
return reg.register;
|
||||||
},
|
},
|
||||||
|
@ -516,6 +516,20 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, va
|
||||||
set_register(registers, RegisterState { id: reg, used: true, variable: get_variable_by_name(variables, &asign.variable, ops.len()).expect("Variable should exist").id, last_used: *op_count });
|
set_register(registers, RegisterState { id: reg, used: true, variable: get_variable_by_name(variables, &asign.variable, ops.len()).expect("Variable should exist").id, last_used: *op_count });
|
||||||
garbage_collect_registers(registers);
|
garbage_collect_registers(registers);
|
||||||
},
|
},
|
||||||
|
ASTPart::Table(tbl) => {
|
||||||
|
let reg = allocate_register(registers);
|
||||||
|
if reg.unbind_before {
|
||||||
|
ops.push(Operation { opcode: 8, arg1: Some(reg.register), arg2: None, arg3: None });
|
||||||
|
}
|
||||||
|
ops.push(Operation { opcode: 6, arg1: Some(reg.register), arg2: Some(1), arg3: None });
|
||||||
|
set_register(registers, RegisterState { id: reg.register, used: true, variable: 0, last_used: *op_count });
|
||||||
|
for val in tbl.values {
|
||||||
|
let key_reg = do_ast_op(val.key, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers);
|
||||||
|
let value_reg = do_ast_op(val.value, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers);
|
||||||
|
ops.push(Operation { opcode: 31, arg1: Some(reg.register), arg2: Some(key_reg as i64), arg3: Some(value_reg) });
|
||||||
|
}
|
||||||
|
return reg.register;
|
||||||
|
},
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -341,6 +341,15 @@ fn read_table(input: &Vec<Token>, pos: &mut usize) -> ASTPart {
|
||||||
if input[*pos].typ == TokenType::SEPARATOR && input[*pos].value == "[" {
|
if input[*pos].typ == TokenType::SEPARATOR && input[*pos].value == "[" {
|
||||||
*pos += 1;
|
*pos += 1;
|
||||||
let keyy = read_exp(pos, input, &key_ends, &key_ends);
|
let keyy = read_exp(pos, input, &key_ends, &key_ends);
|
||||||
|
match keyy {
|
||||||
|
ASTPart::Table(_) => {
|
||||||
|
panic!("Table keys cannot be tables at {}", input[*pos].pos);
|
||||||
|
},
|
||||||
|
ASTPart::Function(_) => {
|
||||||
|
panic!("Table keys cannot be functions at {}", input[*pos].pos);
|
||||||
|
},
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
if input[*pos].typ != TokenType::SEPARATOR || input[*pos].value != "]" {
|
if input[*pos].typ != TokenType::SEPARATOR || input[*pos].value != "]" {
|
||||||
panic!("Unexpected end of key at {}", input[*pos].pos);
|
panic!("Unexpected end of key at {}", input[*pos].pos);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ pub enum VMMemory {
|
||||||
Boolean(VMMemoryBoolean),
|
Boolean(VMMemoryBoolean),
|
||||||
Function(VMMemoryFunction),
|
Function(VMMemoryFunction),
|
||||||
Null(VMMemoryNull),
|
Null(VMMemoryNull),
|
||||||
|
Table(VMMemoryTable),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
@ -35,6 +36,17 @@ pub struct VMMemoryFunction {
|
||||||
pub struct VMMemoryNull {
|
pub struct VMMemoryNull {
|
||||||
pub variable_id: u32,
|
pub variable_id: u32,
|
||||||
}
|
}
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct VMMemoryTable {
|
||||||
|
pub values: Vec<TableValue>,
|
||||||
|
pub variable_id: u32,
|
||||||
|
}
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct TableValue {
|
||||||
|
pub key: VMMemory,
|
||||||
|
pub value: VMMemory,
|
||||||
|
pub pos: usize
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
struct DecompiledFunction {
|
struct DecompiledFunction {
|
||||||
|
@ -161,12 +173,50 @@ fn get_mem_pos_by_var_id(memory: &Vec<VMMemory>, var_id: u32) -> Option<usize> {
|
||||||
VMMemory::Boolean(bool) if bool.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::Null(null) if null.variable_id == var_id => return Some(i),
|
||||||
VMMemory::Function(func) if func.variable_id == var_id => return Some(i),
|
VMMemory::Function(func) if func.variable_id == var_id => return Some(i),
|
||||||
|
VMMemory::Table(tbl) if tbl.variable_id == var_id => return Some(i),
|
||||||
_ => continue
|
_ => continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_mem_tbl_val(tbl: &mut VMMemoryTable, key: VMMemory, value: VMMemory) {
|
||||||
|
for i in 0..tbl.values.len() {
|
||||||
|
let found = match (&tbl.values[i].key, &key) {
|
||||||
|
(VMMemory::Number(num1), VMMemory::Number(num2)) => num1.value == num2.value,
|
||||||
|
(VMMemory::String(str1), VMMemory::String(str2)) => str1.value == str2.value,
|
||||||
|
(VMMemory::Boolean(bool1), VMMemory::Boolean(bool2)) => bool1.value == bool2.value,
|
||||||
|
(VMMemory::Null(_), VMMemory::Null(_)) => true,
|
||||||
|
(VMMemory::Function(_), VMMemory::Function(_)) => false,
|
||||||
|
(VMMemory::Table(_), VMMemory::Table(_)) => false,
|
||||||
|
_ => false,
|
||||||
|
};
|
||||||
|
if found {
|
||||||
|
tbl.values[i].value = value;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tbl.values.push(TableValue { key, value, pos: tbl.values.len() });
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_mem_tbl_val(tbl: &VMMemoryTable, key: VMMemory) -> Option<&VMMemory> {
|
||||||
|
for i in 0..tbl.values.len() {
|
||||||
|
let found = match (&tbl.values[i].key, &key) {
|
||||||
|
(VMMemory::Number(num1), VMMemory::Number(num2)) => num1.value == num2.value,
|
||||||
|
(VMMemory::String(str1), VMMemory::String(str2)) => str1.value == str2.value,
|
||||||
|
(VMMemory::Boolean(bool1), VMMemory::Boolean(bool2)) => bool1.value == bool2.value,
|
||||||
|
(VMMemory::Null(_), VMMemory::Null(_)) => true,
|
||||||
|
(VMMemory::Function(_), VMMemory::Function(_)) => false,
|
||||||
|
(VMMemory::Table(_), VMMemory::Table(_)) => false,
|
||||||
|
_ => false,
|
||||||
|
};
|
||||||
|
if found {
|
||||||
|
return Some(&tbl.values[i].value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
fn do_operation_operation(registers: &mut Vec<Register>, memory: &mut Vec<VMMemory>, operation: &DecompiledOperation) {
|
fn do_operation_operation(registers: &mut Vec<Register>, memory: &mut Vec<VMMemory>, operation: &DecompiledOperation) {
|
||||||
let reg_clone = registers.clone();
|
let reg_clone = registers.clone();
|
||||||
let reg1 = get_register_by_id(®_clone, operation.arg1);
|
let reg1 = get_register_by_id(®_clone, operation.arg1);
|
||||||
|
@ -292,6 +342,7 @@ fn do_operation_operation(registers: &mut Vec<Register>, memory: &mut Vec<VMMemo
|
||||||
VMMemory::Boolean(bool) => bool.variable_id,
|
VMMemory::Boolean(bool) => bool.variable_id,
|
||||||
VMMemory::Null(null) => null.variable_id,
|
VMMemory::Null(null) => null.variable_id,
|
||||||
VMMemory::Function(func) => func.variable_id,
|
VMMemory::Function(func) => func.variable_id,
|
||||||
|
VMMemory::Table(tbl) => tbl.variable_id,
|
||||||
};
|
};
|
||||||
match &mut result {
|
match &mut result {
|
||||||
VMMemory::String(str) => {
|
VMMemory::String(str) => {
|
||||||
|
@ -309,6 +360,9 @@ fn do_operation_operation(registers: &mut Vec<Register>, memory: &mut Vec<VMMemo
|
||||||
VMMemory::Function(func) => {
|
VMMemory::Function(func) => {
|
||||||
func.variable_id = var_id;
|
func.variable_id = var_id;
|
||||||
},
|
},
|
||||||
|
VMMemory::Table(tbl) => {
|
||||||
|
tbl.variable_id = var_id;
|
||||||
|
},
|
||||||
}
|
}
|
||||||
memory[reg3_pointer] = result;
|
memory[reg3_pointer] = result;
|
||||||
}
|
}
|
||||||
|
@ -482,8 +536,13 @@ impl Machine {
|
||||||
},
|
},
|
||||||
6 => {
|
6 => {
|
||||||
//LDN
|
//LDN
|
||||||
self.memory.push(VMMemory::Null(VMMemoryNull { variable_id: 0 }));
|
if operation.arg2 > 0 {
|
||||||
set_register(&mut self.registers, Register { id: operation.arg1, pointer: self.memory.len() - 1 });
|
self.memory.push(VMMemory::Table(VMMemoryTable { values: vec![], variable_id: 0 }));
|
||||||
|
set_register(&mut self.registers, Register { id: operation.arg1, pointer: self.memory.len() - 1 });
|
||||||
|
} else {
|
||||||
|
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
|
||||||
|
@ -513,6 +572,9 @@ impl Machine {
|
||||||
VMMemory::Function(func) => {
|
VMMemory::Function(func) => {
|
||||||
func.variable_id = 0;
|
func.variable_id = 0;
|
||||||
},
|
},
|
||||||
|
VMMemory::Table(tbl) => {
|
||||||
|
tbl.variable_id = 0;
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
match &mut self.memory[reg.pointer] {
|
match &mut self.memory[reg.pointer] {
|
||||||
|
@ -531,6 +593,9 @@ impl Machine {
|
||||||
VMMemory::Function(func) => {
|
VMMemory::Function(func) => {
|
||||||
func.variable_id = operation.arg2 as u32;
|
func.variable_id = operation.arg2 as u32;
|
||||||
},
|
},
|
||||||
|
VMMemory::Table(tbl) => {
|
||||||
|
tbl.variable_id = operation.arg2 as u32;
|
||||||
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
8 => {
|
8 => {
|
||||||
|
@ -583,6 +648,7 @@ impl Machine {
|
||||||
VMMemory::Boolean(bool) => bool.variable_id,
|
VMMemory::Boolean(bool) => bool.variable_id,
|
||||||
VMMemory::Null(null) => null.variable_id,
|
VMMemory::Null(null) => null.variable_id,
|
||||||
VMMemory::Function(func) => func.variable_id,
|
VMMemory::Function(func) => func.variable_id,
|
||||||
|
VMMemory::Table(tbl) => tbl.variable_id,
|
||||||
};
|
};
|
||||||
match &mut result {
|
match &mut result {
|
||||||
VMMemory::String(str) => {
|
VMMemory::String(str) => {
|
||||||
|
@ -600,6 +666,9 @@ impl Machine {
|
||||||
VMMemory::Function(func) => {
|
VMMemory::Function(func) => {
|
||||||
func.variable_id = var_id;
|
func.variable_id = var_id;
|
||||||
},
|
},
|
||||||
|
VMMemory::Table(tbl) => {
|
||||||
|
tbl.variable_id = var_id;
|
||||||
|
},
|
||||||
}
|
}
|
||||||
self.memory[reg2.unwrap().pointer] = result;
|
self.memory[reg2.unwrap().pointer] = result;
|
||||||
},
|
},
|
||||||
|
@ -691,15 +760,96 @@ impl Machine {
|
||||||
executed_stack = &mut self.call_stack[last_stack];
|
executed_stack = &mut self.call_stack[last_stack];
|
||||||
},
|
},
|
||||||
30 => {
|
30 => {
|
||||||
//not implemented yet
|
//GET
|
||||||
|
let reg_clone = self.registers.clone();
|
||||||
|
let reg = get_register_by_id(®_clone, operation.arg1);
|
||||||
|
let reg2 = get_register_by_id(®_clone, operation.arg2 as u8);
|
||||||
|
let reg3 = get_register_by_id(®_clone, operation.arg3);
|
||||||
|
if reg.is_none() || reg2.is_none() || reg3.is_none() {
|
||||||
|
panic!("One or more registers not found for SET operation");
|
||||||
|
}
|
||||||
|
let mem1 = self.memory.get(reg.unwrap().pointer);
|
||||||
|
let mem2 = self.memory.get(reg2.unwrap().pointer);
|
||||||
|
if mem1.is_none() || mem2.is_none() {
|
||||||
|
panic!("Memory location not found for one or more registers");
|
||||||
|
}
|
||||||
|
let mem1 = mem1.unwrap().clone();
|
||||||
|
let mem2 = mem2.unwrap().clone();
|
||||||
|
let mut value: VMMemory;
|
||||||
|
match mem1 {
|
||||||
|
VMMemory::Table(tbl) => {
|
||||||
|
let tvalue = get_mem_tbl_val(&tbl, mem2);
|
||||||
|
if tvalue.is_none() {
|
||||||
|
value = VMMemory::Null(VMMemoryNull { variable_id: 0 });
|
||||||
|
} else {
|
||||||
|
value = tvalue.unwrap().clone();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
panic!("Invalid memory type for SET operation");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let mut reg3_pointer = reg3.unwrap().pointer;
|
||||||
|
if reg3_pointer >= self.memory.len() || reg3_pointer < 1 {
|
||||||
|
reg3_pointer = self.memory.len();
|
||||||
|
self.memory.push(VMMemory::Null(VMMemoryNull { variable_id: 0 }));
|
||||||
|
set_register(&mut self.registers, Register { id: operation.arg2 as u8, pointer: reg3_pointer });
|
||||||
|
}
|
||||||
|
let var_id = match &self.memory[reg3.unwrap().pointer] {
|
||||||
|
VMMemory::String(str) => str.variable_id,
|
||||||
|
VMMemory::Number(num) => num.variable_id,
|
||||||
|
VMMemory::Boolean(bool) => bool.variable_id,
|
||||||
|
VMMemory::Null(null) => null.variable_id,
|
||||||
|
VMMemory::Function(func) => func.variable_id,
|
||||||
|
VMMemory::Table(tbl) => tbl.variable_id,
|
||||||
|
};
|
||||||
|
match &mut value {
|
||||||
|
VMMemory::String(str) => {
|
||||||
|
str.variable_id = var_id;
|
||||||
|
},
|
||||||
|
VMMemory::Number(num) => {
|
||||||
|
num.variable_id = var_id;
|
||||||
|
},
|
||||||
|
VMMemory::Boolean(bool) => {
|
||||||
|
bool.variable_id = var_id;
|
||||||
|
},
|
||||||
|
VMMemory::Null(null) => {
|
||||||
|
null.variable_id = var_id;
|
||||||
|
},
|
||||||
|
VMMemory::Function(func) => {
|
||||||
|
func.variable_id = var_id;
|
||||||
|
},
|
||||||
|
VMMemory::Table(tbl) => {
|
||||||
|
tbl.variable_id = var_id;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
self.memory[reg3.unwrap().pointer] = value;
|
||||||
},
|
},
|
||||||
31 => {
|
31 => {
|
||||||
//GET
|
|
||||||
//not implemented yet
|
|
||||||
},
|
|
||||||
32 => {
|
|
||||||
//SET
|
//SET
|
||||||
//not implemented yet
|
let reg = get_register_by_id(&self.registers, operation.arg1);
|
||||||
|
let reg2 = get_register_by_id(&self.registers, operation.arg2 as u8);
|
||||||
|
let reg3 = get_register_by_id(&self.registers, operation.arg3);
|
||||||
|
if reg.is_none() || reg2.is_none() || reg3.is_none() {
|
||||||
|
panic!("One or more registers not found for SET operation");
|
||||||
|
}
|
||||||
|
let mem1 = self.memory.get(reg.unwrap().pointer);
|
||||||
|
let mem2 = self.memory.get(reg2.unwrap().pointer);
|
||||||
|
let mem3 = self.memory.get(reg3.unwrap().pointer);
|
||||||
|
if mem1.is_none() || mem2.is_none() || mem3.is_none() {
|
||||||
|
panic!("Memory location not found for one or more registers");
|
||||||
|
}
|
||||||
|
let mem2 = mem2.unwrap().clone();
|
||||||
|
let mem3 = mem3.unwrap().clone();
|
||||||
|
let mem1 = self.memory.get_mut(reg.unwrap().pointer).expect("Memory location should exist");
|
||||||
|
match mem1 {
|
||||||
|
VMMemory::Table(tbl) => {
|
||||||
|
set_mem_tbl_val(tbl, mem2, mem3);
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
panic!("Invalid memory type for SET operation");
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
panic!("Unknown operation code: {}", operation.opcode);
|
panic!("Unknown operation code: {}", operation.opcode);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue