added functions and calls

This commit is contained in:
afonya2 2025-05-30 21:22:16 +02:00
parent 1561abcc31
commit 4c69228848
Signed by: afonya
GPG key ID: EBB9C4CAFAAFB2DC
2 changed files with 123 additions and 17 deletions

View file

@ -24,13 +24,26 @@ struct AllocateResult {
unbind_before: bool,
}
#[derive(Debug, Clone)]
struct Compiled {
operations: Vec<Operation>,
var_ids: HashMap<String, u32>,
strings: HashMap<u32, String>,
functions: HashMap<u32, Compiled>
}
fn get_register_by_id(registers: &Vec<RegisterState>, id: u8) -> RegisterState {
for register in registers {
if register.id == id {
return register.clone();
}
}
panic!("Register with id {} not found", id);
return RegisterState {
id: 0,
used: false,
variable: 0,
last_used: 0,
};
}
fn get_register_by_variable(registers: &Vec<RegisterState>, variable: u32) -> RegisterState {
@ -39,7 +52,12 @@ fn get_register_by_variable(registers: &Vec<RegisterState>, variable: u32) -> Re
return register.clone();
}
}
panic!("Register with variable {} not found", variable);
return RegisterState {
id: 0,
used: false,
variable: 0,
last_used: 0,
};
}
fn set_register(registers: &mut Vec<RegisterState>, new_state: RegisterState) {
@ -87,7 +105,7 @@ fn garbage_collect_registers(registers: &mut Vec<RegisterState>) {
}
}
fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, var_ids: &mut HashMap<String, u32>, next_var_id: &mut u32, strings: &mut HashMap<u32, String>, next_string_id: &mut u32, registers: &mut Vec<RegisterState>) -> u8 {
fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, var_ids: &mut HashMap<String, u32>, next_var_id: &mut u32, strings: &mut HashMap<u32, String>, next_string_id: &mut u32, functions: &mut HashMap<u32, Compiled>, next_function_id: &mut u32, registers: &mut Vec<RegisterState>) -> u8 {
*op_count += 1;
match ast_op {
ASTPart::Number(num) => {
@ -111,9 +129,65 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, va
set_register(registers, RegisterState { id: reg.register, used: true, variable: 0, last_used: *op_count });
return reg.register;
},
ASTPart::Boolean(bool) => {
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: 4, arg1: Some(reg.register), arg2: Some(bool.value as i64), arg3: None });
set_register(registers, RegisterState { id: reg.register, used: true, variable: 0, last_used: *op_count });
return reg.register;
},
ASTPart::Null(_) => {
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: None, arg3: None });
set_register(registers, RegisterState { id: reg.register, used: true, variable: 0, last_used: *op_count });
return reg.register;
},
ASTPart::VarRead(var_read) => {
if !var_ids.contains_key(&var_read.variable) {
panic!("Variable {} does not exist", var_read.variable);
}
let reg = get_register_by_variable(registers, var_ids[&var_read.variable]);
if reg.id == 0 {
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: 2, arg1: Some(reg.register), arg2: Some(var_ids[&var_read.variable] as i64), arg3: None });
set_register(registers, RegisterState { id: reg.register, used: true, variable: var_ids[&var_read.variable], last_used: *op_count });
return reg.register;
} else {
return reg.id;
}
},
ASTPart::Function(func) => {
let func_id = *next_function_id;
functions.insert(func_id, compile_function(func.body, Some(func.args), registers));
*next_function_id += 1;
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: 5, arg1: Some(reg.register), arg2: Some(func_id as i64), arg3: None });
set_register(registers, RegisterState { id: reg.register, used: true, variable: 0, last_used: *op_count });
},
ASTPart::Call(call) => {
let func = do_ast_op(*call.function, op_count, ops, var_ids, next_var_id, strings, next_string_id, functions, next_function_id, registers);
for arg in call.args {
let arg_reg = do_ast_op(arg, op_count, ops, var_ids, next_var_id, strings, next_string_id, functions, next_function_id, registers);
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 });
},
ASTPart::Operation(op) => {
let left_reg = do_ast_op(*op.left, op_count, ops, var_ids, next_var_id, strings, next_string_id, registers);
let right_reg = do_ast_op(*op.right, op_count, ops, var_ids, next_var_id, strings, next_string_id, registers);
let left_reg = do_ast_op(*op.left, op_count, ops, var_ids, next_var_id, strings, next_string_id, functions, next_function_id, registers);
let right_reg = do_ast_op(*op.right, op_count, ops, var_ids, next_var_id, strings, next_string_id, functions, next_function_id, registers);
let reg = allocate_register(registers);
if reg.unbind_before {
ops.push(Operation { opcode: 8, arg1: Some(reg.register), arg2: None, arg3: None });
@ -146,7 +220,7 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, va
}
var_ids.insert(asign.variable.clone(), *next_var_id);
*next_var_id += 1;
let reg = do_ast_op(*asign.value, op_count, ops, var_ids, next_var_id, strings, next_string_id, registers);
let reg = do_ast_op(*asign.value, op_count, ops, var_ids, next_var_id, strings, next_string_id, functions, next_function_id, registers);
ops.push(Operation { opcode: 7, arg1: Some(reg), arg2: Some(var_ids[&asign.variable.clone()] as i64), arg3: None });
set_register(registers, RegisterState { id: reg, used: true, variable: var_ids[&asign.variable.clone()], last_used: *op_count });
garbage_collect_registers(registers);
@ -156,13 +230,48 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, va
return 0;
}
pub fn compile(ast: Vec<ASTPart>) -> Vec<u8> {
fn compile_function(ast: Vec<ASTPart>, args: Option<Vec<String>>, registers: &mut Vec<RegisterState>) -> Compiled {
let mut ops: Vec<Operation> = vec![];
let mut var_ids: HashMap<String, u32> = HashMap::new();
let mut next_var_id: u32 = 1;
let mut strings: HashMap<u32, String> = HashMap::new();
let mut next_string_id: u32 = 1;
let mut functions: HashMap<u32, Compiled> = HashMap::new();
let mut next_function_id: u32 = 1;
match args {
Some(arg_list) => {
for arg in arg_list {
if var_ids.contains_key(&arg) {
panic!("Argument {} already exists", arg);
}
var_ids.insert(arg, next_var_id);
next_var_id += 1;
}
},
None => {}
}
let mut op_count = 0;
for ast_op in ast {
do_ast_op(ast_op, &mut op_count, &mut ops, &mut var_ids, &mut next_var_id, &mut strings, &mut next_string_id, &mut functions, &mut next_function_id, registers);
}
println!("Operations: {:?}\n", ops);
println!("Registers: {:?}\n", registers);
println!("Variable IDs: {:?}", var_ids);
println!("Strings: {:?}", strings);
println!("==========================");
return Compiled {
operations: ops,
var_ids,
strings,
functions,
};
}
pub fn compile(ast: Vec<ASTPart>) -> Vec<u8> {
let mut registers: Vec<RegisterState> = vec![];
for i in 0..17 {
registers.push(RegisterState {
@ -173,14 +282,8 @@ pub fn compile(ast: Vec<ASTPart>) -> Vec<u8> {
});
}
let mut op_count = 0;
for ast_op in ast {
do_ast_op(ast_op, &mut op_count, &mut ops, &mut var_ids, &mut next_var_id, &mut strings, &mut next_string_id, &mut registers);
println!("Operations: {:?}\n", ops);
println!("Registers: {:?}\n", registers);
println!("Variable IDs: {:?}", var_ids);
println!("Strings: {:?}", strings);
println!("==========================");
}
let compiled = compile_function(ast, None, &mut registers);
println!("Compiled: {:?}", compiled);
return vec![];
}