added functions and calls
This commit is contained in:
parent
1561abcc31
commit
4c69228848
2 changed files with 123 additions and 17 deletions
135
src/compiler.rs
135
src/compiler.rs
|
@ -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![];
|
||||
}
|
5
test.as
5
test.as
|
@ -1 +1,4 @@
|
|||
gethelj a = szaft"Hello"szaft
|
||||
gethelj a = lőcsve(test) {
|
||||
gethelj a = 1
|
||||
}
|
||||
a(5)
|
Loading…
Add table
Add a link
Reference in a new issue