functions now can use previous variables

This commit is contained in:
afonya2 2025-06-11 12:52:05 +02:00
parent e0c3cf4407
commit 74fa0a8523
Signed by: afonya
GPG key ID: EBB9C4CAFAAFB2DC
2 changed files with 96 additions and 62 deletions

View file

@ -43,6 +43,12 @@ struct Variable {
no_end: bool
}
#[derive(Debug, Clone)]
struct PrevFunc {
variables: Vec<Variable>,
previous: Option<Box<PrevFunc>>,
}
fn get_register_by_id(registers: &Vec<RegisterState>, id: u8) -> RegisterState {
for register in registers {
if register.id == id {
@ -129,7 +135,7 @@ fn garbage_collect_registers(_registers: &mut Vec<RegisterState>) {
}*/
}
fn get_variable_by_name(variables: &Vec<Variable>, name: &str, position: usize) -> Option<Variable> {
fn get_variable_by_name(variables: &Vec<Variable>, name: &str, position: usize, traceback: &PrevFunc) -> Option<Variable> {
for variable in variables {
if variable.name == name {
if variable.start <= position && (variable.no_end || variable.end >= position) {
@ -137,10 +143,23 @@ fn get_variable_by_name(variables: &Vec<Variable>, name: &str, position: usize)
}
}
}
let mut cur = traceback.clone();
loop {
for variable in &cur.variables {
if variable.name == name {
return Some(variable.clone());
}
}
if let Some(prev) = &cur.previous {
cur = *prev.clone();
} else {
break;
}
}
None
}
fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, variables: &mut Vec<Variable>, 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>, ctx: &Context) -> u8 {
fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, variables: &mut Vec<Variable>, 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>, ctx: &Context, traceback: &PrevFunc) -> u8 {
*op_count += 1;
match ast_op {
ASTPart::Number(num) => {
@ -183,7 +202,7 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, va
return reg.register;
},
ASTPart::VarRead(var_read) => {
if get_variable_by_name(variables, &var_read.variable, ops.len()).is_none() {
if get_variable_by_name(variables, &var_read.variable, ops.len(), traceback).is_none() {
let reg = allocate_register(registers);
if reg.unbind_before {
ops.push(Operation { opcode: 8, arg1: Some(reg.register), arg2: None, arg3: None, pos: var_read.pos as u32 });
@ -196,14 +215,14 @@ 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;
}
let reg = get_register_by_variable(registers, get_variable_by_name(variables, &var_read.variable, ops.len()).expect("Variable should exist"));
let reg = get_register_by_variable(registers, get_variable_by_name(variables, &var_read.variable, ops.len(), traceback).expect("Variable should exist"));
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, pos: var_read.pos as u32 });
}
ops.push(Operation { opcode: 2, arg1: Some(reg.register), arg2: Some(get_variable_by_name(variables, &var_read.variable, ops.len()).expect("Variable should exist").id as i64), arg3: None, pos: var_read.pos as u32 });
set_register(registers, RegisterState { id: reg.register, used: true, variable: get_variable_by_name(variables, &var_read.variable, ops.len()).expect("Variable should exist").id, last_used: *op_count });
ops.push(Operation { opcode: 2, arg1: Some(reg.register), arg2: Some(get_variable_by_name(variables, &var_read.variable, ops.len(), traceback).expect("Variable should exist").id as i64), arg3: None, pos: var_read.pos as u32 });
set_register(registers, RegisterState { id: reg.register, used: true, variable: get_variable_by_name(variables, &var_read.variable, ops.len(), traceback).expect("Variable should exist").id, last_used: *op_count });
return reg.register;
} else {
return reg.id;
@ -211,7 +230,11 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, va
},
ASTPart::Function(func) => {
let func_id = *next_function_id;
functions.insert(func_id, compile_function(func.body, Some(func.args), registers, next_var_id, ctx));
let self_tb = PrevFunc {
variables: variables.clone(),
previous: Some(Box::new(traceback.clone())),
};
functions.insert(func_id, compile_function(func.body, Some(func.args), registers, next_var_id, ctx, &self_tb));
*next_function_id += 1;
let reg = allocate_register(registers);
if reg.unbind_before {
@ -222,9 +245,9 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, va
return reg.register;
},
ASTPart::Call(call) => {
let func = do_ast_op(*call.function, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx);
let func = do_ast_op(*call.function, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx, traceback);
for arg in call.args {
let arg_reg = do_ast_op(arg, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx);
let arg_reg = do_ast_op(arg, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx, traceback);
ops.push(Operation { opcode: 28, arg1: Some(arg_reg), arg2: None, arg3: None, pos: call.pos as u32 });
set_register(registers, RegisterState { id: arg_reg, used: false, variable: 0, last_used: 0 });
}
@ -237,22 +260,22 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, va
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, ctx);
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, ctx, traceback);
ops.push(Operation { opcode: 24, arg1: Some(condition_reg), arg2: Some(condition_reg as i64), arg3: None, pos: if_part.pos as u32 });
//Update the lastif variable
if get_variable_by_name(variables, "__LASTIF", ops.len()).is_none() {
if get_variable_by_name(variables, "__LASTIF", ops.len(), traceback).is_none() {
variables.push(Variable { name: String::from("__LASTIF"), id: *next_var_id, start: ops.len(), end: 0, no_end: true });
*next_var_id += 1;
}
ops.push(Operation { opcode: 7, arg1: Some(condition_reg), arg2: Some(get_variable_by_name(variables, "__LASTIF", ops.len()).expect("__LASTIF should exist").id as i64), arg3: None, pos: if_part.pos as u32 });
set_register(registers, RegisterState { id: condition_reg, used: true, variable: get_variable_by_name(variables, "__LASTIF", ops.len()).expect("__LASTIF should exist").id, last_used: *op_count });
ops.push(Operation { opcode: 7, arg1: Some(condition_reg), arg2: Some(get_variable_by_name(variables, "__LASTIF", ops.len(), traceback).expect("__LASTIF should exist").id as i64), arg3: None, pos: if_part.pos as u32 });
set_register(registers, RegisterState { id: condition_reg, used: true, variable: get_variable_by_name(variables, "__LASTIF", ops.len(), traceback).expect("__LASTIF should exist").id, last_used: *op_count });
let op_placeholder = ops.len();
ops.push(Operation { opcode: 0, arg1: None, arg2: None, arg3: None, pos: if_part.pos as u32 });
let mut fake_vars: Vec<Variable> = vec![];
for if_op in if_part.body {
do_ast_op(if_op, op_count, ops, &mut fake_vars, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx);
do_ast_op(if_op, op_count, ops, &mut fake_vars, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx, traceback);
}
for fake_var in fake_vars {
variables.push(Variable { name: fake_var.name, id: fake_var.id, start: fake_var.start, end: ops.len()-1, no_end: false });
@ -266,27 +289,27 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, va
};
//Unbind the lastif variable
if get_register_by_id(registers, condition_reg).variable == get_variable_by_name(variables, "__LASTIF", ops.len()).expect("__LASTIF should exist").id {
if get_register_by_id(registers, condition_reg).variable == get_variable_by_name(variables, "__LASTIF", ops.len(), traceback).expect("__LASTIF should exist").id {
ops.push(Operation { opcode: 8, arg1: Some(condition_reg), arg2: None, arg3: None, pos: if_part.pos as u32 });
set_register(registers, RegisterState { id: condition_reg, used: false, variable: 0, last_used: 0 });
}
garbage_collect_registers(registers);
},
ASTPart::Else(else_part) => {
if get_variable_by_name(variables, "__LASTIF", ops.len()).is_none() {
if get_variable_by_name(variables, "__LASTIF", ops.len(), traceback).is_none() {
let err = create_error(&format!("Else used without an if statement before it"), else_part.pos, ErrorType::SemanticError, ErrorSubType::ElseWithoutIf);
print_error(&err, &ctx);
process::exit(1);
}
let reg = get_register_by_variable(registers, get_variable_by_name(variables, "__LASTIF", ops.len()).expect("__LASTIF should exist").clone());
let reg = get_register_by_variable(registers, get_variable_by_name(variables, "__LASTIF", ops.len(), traceback).expect("__LASTIF should exist").clone());
let else_condition_reg;
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, pos: else_part.pos as u32 });
}
ops.push(Operation { opcode: 2, arg1: Some(reg.register), arg2: Some(get_variable_by_name(variables, "__LASTIF", ops.len()).expect("__LASTIF should exist").id as i64), arg3: None, pos: else_part.pos as u32 });
set_register(registers, RegisterState { id: reg.register, used: true, variable: get_variable_by_name(variables, "__LASTIF", ops.len()).expect("__LASTIF should exist").id, last_used: *op_count });
ops.push(Operation { opcode: 2, arg1: Some(reg.register), arg2: Some(get_variable_by_name(variables, "__LASTIF", ops.len(), traceback).expect("__LASTIF should exist").id as i64), arg3: None, pos: else_part.pos as u32 });
set_register(registers, RegisterState { id: reg.register, used: true, variable: get_variable_by_name(variables, "__LASTIF", ops.len(), traceback).expect("__LASTIF should exist").id, last_used: *op_count });
else_condition_reg = reg.register;
} else {
else_condition_reg = reg.id;
@ -297,7 +320,7 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, va
ops.push(Operation { opcode: 0, arg1: None, arg2: None, arg3: None, pos: else_part.pos as u32 });
let mut fake_vars: Vec<Variable> = vec![];
for else_op in else_part.body {
do_ast_op(else_op, op_count, ops, &mut fake_vars, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx);
do_ast_op(else_op, op_count, ops, &mut fake_vars, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx, traceback);
}
for fake_var in fake_vars {
variables.push(Variable { name: fake_var.name, id: fake_var.id, start: fake_var.start, end: ops.len()-1, no_end: false });
@ -310,46 +333,46 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, va
pos: else_part.pos as u32,
};
//Unbind the lastif variable
if get_register_by_id(registers, else_condition_reg).variable == get_variable_by_name(variables, "__LASTIF", ops.len()).expect("__LASTIF should exist").id {
if get_register_by_id(registers, else_condition_reg).variable == get_variable_by_name(variables, "__LASTIF", ops.len(), traceback).expect("__LASTIF should exist").id {
ops.push(Operation { opcode: 8, arg1: Some(else_condition_reg), arg2: None, arg3: None, pos: else_part.pos as u32 });
set_register(registers, RegisterState { id: else_condition_reg, used: false, variable: 0, last_used: 0 });
}
garbage_collect_registers(registers);
},
ASTPart::ElseIf(elseif_part) => {
if get_variable_by_name(variables, "__LASTIF", ops.len()).is_none() {
if get_variable_by_name(variables, "__LASTIF", ops.len(), traceback).is_none() {
let err = create_error(&format!("Else if used without an if statement before it"), elseif_part.pos, ErrorType::SemanticError, ErrorSubType::ElseWithoutIf);
print_error(&err, &ctx);
process::exit(1);
}
let reg = get_register_by_variable(registers, get_variable_by_name(variables, "__LASTIF", ops.len()).expect("__LASTIF should exist").clone());
let reg = get_register_by_variable(registers, get_variable_by_name(variables, "__LASTIF", ops.len(), traceback).expect("__LASTIF should exist").clone());
let else_condition_reg;
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, pos: elseif_part.pos as u32 });
}
ops.push(Operation { opcode: 2, arg1: Some(reg.register), arg2: Some(get_variable_by_name(variables, "__LASTIF", ops.len()).expect("__LASTIF should exist").id as i64), arg3: None, pos: elseif_part.pos as u32 });
set_register(registers, RegisterState { id: reg.register, used: true, variable: get_variable_by_name(variables, "__LASTIF", ops.len()).expect("__LASTIF should exist").id, last_used: *op_count });
ops.push(Operation { opcode: 2, arg1: Some(reg.register), arg2: Some(get_variable_by_name(variables, "__LASTIF", ops.len(), traceback).expect("__LASTIF should exist").id as i64), arg3: None, pos: elseif_part.pos as u32 });
set_register(registers, RegisterState { id: reg.register, used: true, variable: get_variable_by_name(variables, "__LASTIF", ops.len(), traceback).expect("__LASTIF should exist").id, last_used: *op_count });
else_condition_reg = reg.register;
} else {
else_condition_reg = reg.id;
}
ops.push(Operation { opcode: 24, arg1: Some(else_condition_reg), arg2: Some(else_condition_reg as i64), arg3: None, pos: elseif_part.pos as u32 });
let condition_reg = do_ast_op(*elseif_part.condition, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx);
let condition_reg = do_ast_op(*elseif_part.condition, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx, traceback);
ops.push(Operation { opcode: 16, arg1: Some(else_condition_reg), arg2: Some(condition_reg as i64), arg3: Some(condition_reg), pos: elseif_part.pos as u32 });
ops.push(Operation { opcode: 24, arg1: Some(condition_reg), arg2: Some(condition_reg as i64), arg3: None, pos: elseif_part.pos as u32 });
//Update the lastif variable
ops.push(Operation { opcode: 7, arg1: Some(condition_reg), arg2: Some(get_variable_by_name(variables, "__LASTIF", ops.len()).expect("__LASTIF should exist").id as i64), arg3: None, pos: elseif_part.pos as u32 });
set_register(registers, RegisterState { id: condition_reg, used: true, variable: get_variable_by_name(variables, "__LASTIF", ops.len()).expect("__LASTIF should exist").id, last_used: *op_count });
ops.push(Operation { opcode: 7, arg1: Some(condition_reg), arg2: Some(get_variable_by_name(variables, "__LASTIF", ops.len(), traceback).expect("__LASTIF should exist").id as i64), arg3: None, pos: elseif_part.pos as u32 });
set_register(registers, RegisterState { id: condition_reg, used: true, variable: get_variable_by_name(variables, "__LASTIF", ops.len(), traceback).expect("__LASTIF should exist").id, last_used: *op_count });
let op_placeholder = ops.len();
ops.push(Operation { opcode: 0, arg1: None, arg2: None, arg3: None, pos: elseif_part.pos as u32 });
let mut fake_vars: Vec<Variable> = vec![];
for elseif_op in elseif_part.body {
do_ast_op(elseif_op, op_count, ops, &mut fake_vars, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx);
do_ast_op(elseif_op, op_count, ops, &mut fake_vars, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx, traceback);
}
for fake_var in fake_vars {
variables.push(Variable { name: fake_var.name, id: fake_var.id, start: fake_var.start, end: ops.len()-1, no_end: false });
@ -362,7 +385,7 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, va
pos: elseif_part.pos as u32
};
//Unbind the lastif variable
if get_register_by_id(registers, condition_reg).variable == get_variable_by_name(variables, "__LASTIF", ops.len()).expect("__LASTIF should exist").id {
if get_register_by_id(registers, condition_reg).variable == get_variable_by_name(variables, "__LASTIF", ops.len(), traceback).expect("__LASTIF should exist").id {
ops.push(Operation { opcode: 8, arg1: Some(condition_reg), arg2: None, arg3: None, pos: elseif_part.pos as u32 });
set_register(registers, RegisterState { id: condition_reg, used: false, variable: 0, last_used: 0 });
}
@ -370,7 +393,7 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, va
},
ASTPart::While(while_part) => {
let start = ops.len();
let condition_reg = do_ast_op(*while_part.condition, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx);
let condition_reg = do_ast_op(*while_part.condition, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx, traceback);
ops.push(Operation { opcode: 24, arg1: Some(condition_reg), arg2: Some(condition_reg as i64), arg3: None, pos: while_part.pos as u32 });
let op_placeholder = ops.len();
@ -388,7 +411,7 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, va
ops.push(Operation { opcode: 0, arg1: None, arg2: None, arg3: None, pos: while_part.pos as u32 });
},
_ => {
do_ast_op(while_op, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx);
do_ast_op(while_op, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx, traceback);
}
}
}
@ -430,9 +453,9 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, va
process::exit(1);
},
ASTPart::For(for_part) => {
do_ast_op(*for_part.init, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx);
do_ast_op(*for_part.init, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx, traceback);
let start = ops.len();
let condition_reg = do_ast_op(*for_part.condition, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx);
let condition_reg = do_ast_op(*for_part.condition, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx, traceback);
ops.push(Operation { opcode: 24, arg1: Some(condition_reg), arg2: Some(condition_reg as i64), arg3: None, pos: for_part.pos as u32 });
let op_placeholder = ops.len();
@ -450,11 +473,11 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, va
ops.push(Operation { opcode: 0, arg1: None, arg2: None, arg3: None, pos: for_part.pos as u32 });
},
_ => {
do_ast_op(for_op, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx);
do_ast_op(for_op, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx, traceback);
}
}
}
do_ast_op(*for_part.update, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx);
do_ast_op(*for_part.update, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx, traceback);
ops.push(Operation { opcode: 25, arg1: None, arg2: Some(start as i64), arg3: None, pos: for_part.pos as u32 });
ops[op_placeholder] = Operation {
@ -484,12 +507,12 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, va
}
},
ASTPart::Return(ret) => {
let ret_reg = do_ast_op(*ret.value, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx);
let ret_reg = do_ast_op(*ret.value, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx, traceback);
ops.push(Operation { opcode: 29, arg1: Some(ret_reg), arg2: None, arg3: None, pos: ret.pos as u32 });
},
ASTPart::Operation(op) => {
let left_reg = do_ast_op(*op.left, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx);
let right_reg = do_ast_op(*op.right, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx);
let left_reg = do_ast_op(*op.left, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx, traceback);
let right_reg = do_ast_op(*op.right, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx, traceback);
let reg = allocate_register(registers);
if reg.unbind_before {
ops.push(Operation { opcode: 8, arg1: Some(reg.register), arg2: None, arg3: None, pos: op.pos as u32 });
@ -525,32 +548,32 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, va
return reg.register;
},
ASTPart::VarUpdate(upd) => {
if get_variable_by_name(variables, &upd.variable, ops.len()).is_none() {
if get_variable_by_name(variables, &upd.variable, ops.len(), traceback).is_none() {
let err = create_error(&format!("Variable `{}` does not exist", upd.variable), upd.pos, ErrorType::SemanticError, ErrorSubType::VariableNotFound);
print_error(&err, &ctx);
process::exit(1);
}
let reg = get_register_by_variable(registers, get_variable_by_name(variables, &upd.variable, ops.len()).expect("Variable should exist").clone());
let reg = get_register_by_variable(registers, get_variable_by_name(variables, &upd.variable, ops.len(), traceback).expect("Variable should exist").clone());
if reg.id != 0 {
ops.push(Operation { opcode: 8, arg1: Some(reg.id), arg2: None, arg3: None, pos: upd.pos as u32 });
set_register(registers, RegisterState { id: reg.id, used: false, variable: 0, last_used: 0 });
}
let value_reg = do_ast_op(*upd.value, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx);
ops.push(Operation { opcode: 7, arg1: Some(value_reg), arg2: Some(get_variable_by_name(variables, &upd.variable, ops.len()).expect("Variable should exist").id as i64), arg3: None, pos: upd.pos as u32 });
set_register(registers, RegisterState { id: value_reg, used: true, variable: get_variable_by_name(variables, &upd.variable, ops.len()).expect("Variable should exist").id, last_used: *op_count });
let value_reg = do_ast_op(*upd.value, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx, traceback);
ops.push(Operation { opcode: 7, arg1: Some(value_reg), arg2: Some(get_variable_by_name(variables, &upd.variable, ops.len(), traceback).expect("Variable should exist").id as i64), arg3: None, pos: upd.pos as u32 });
set_register(registers, RegisterState { id: value_reg, used: true, variable: get_variable_by_name(variables, &upd.variable, ops.len(), traceback).expect("Variable should exist").id, last_used: *op_count });
garbage_collect_registers(registers);
},
ASTPart::Assigment(asign) => {
if get_variable_by_name(variables, &asign.variable, ops.len()).is_some() {
if get_variable_by_name(variables, &asign.variable, ops.len(), traceback).is_some() {
let err = create_error(&format!("Variable `{}` already exists", asign.variable), asign.pos, ErrorType::SemanticError, ErrorSubType::VariableAlreadyExists);
print_error(&err, &ctx);
process::exit(1);
}
let reg = do_ast_op(*asign.value, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx);
let reg = do_ast_op(*asign.value, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx, traceback);
variables.push(Variable { name: asign.variable.clone(), id: *next_var_id, start: ops.len(), end: 0, no_end: true });
*next_var_id += 1;
ops.push(Operation { opcode: 7, arg1: Some(reg), arg2: Some(get_variable_by_name(variables, &asign.variable, ops.len()).expect("Variable should exist").id as i64), arg3: None, pos: asign.pos as u32 });
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 });
ops.push(Operation { opcode: 7, arg1: Some(reg), arg2: Some(get_variable_by_name(variables, &asign.variable, ops.len(), traceback).expect("Variable should exist").id as i64), arg3: None, pos: asign.pos as u32 });
set_register(registers, RegisterState { id: reg, used: true, variable: get_variable_by_name(variables, &asign.variable, ops.len(), traceback).expect("Variable should exist").id, last_used: *op_count });
garbage_collect_registers(registers);
},
ASTPart::Table(tbl) => {
@ -561,15 +584,15 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, va
ops.push(Operation { opcode: 6, arg1: Some(reg.register), arg2: Some(1), arg3: None, pos: tbl.pos as u32 });
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, ctx);
let value_reg = do_ast_op(val.value, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx);
let key_reg = do_ast_op(val.key, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx, traceback);
let value_reg = do_ast_op(val.value, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx, traceback);
ops.push(Operation { opcode: 31, arg1: Some(reg.register), arg2: Some(key_reg as i64), arg3: Some(value_reg), pos: tbl.pos as u32 });
}
return reg.register;
},
ASTPart::TableGet(tbl_get) => {
let table_reg = do_ast_op(*tbl_get.table, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx);
let key_reg = do_ast_op(*tbl_get.key, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx);
let table_reg = do_ast_op(*tbl_get.table, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx, traceback);
let key_reg = do_ast_op(*tbl_get.key, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx, traceback);
let reg = allocate_register(registers);
if reg.unbind_before {
ops.push(Operation { opcode: 8, arg1: Some(reg.register), arg2: None, arg3: None, pos: tbl_get.pos as u32 });
@ -579,9 +602,9 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, va
return reg.register;
},
ASTPart::TableSet(tbl_set) => {
let table_reg = do_ast_op(*tbl_set.table, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx);
let key_reg = do_ast_op(*tbl_set.key, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx);
let value_reg = do_ast_op(*tbl_set.value, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx);
let table_reg = do_ast_op(*tbl_set.table, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx, traceback);
let key_reg = do_ast_op(*tbl_set.key, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx, traceback);
let value_reg = do_ast_op(*tbl_set.value, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx, traceback);
ops.push(Operation { opcode: 31, arg1: Some(table_reg), arg2: Some(key_reg as i64), arg3: Some(value_reg), pos: tbl_set.pos as u32 });
},
_ => {}
@ -589,7 +612,7 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, va
return 0;
}
fn compile_function(ast: Vec<ASTPart>, args: Option<Vec<String>>, registers: &mut Vec<RegisterState>, next_var_id: &mut u32, ctx: &Context) -> Compiled {
fn compile_function(ast: Vec<ASTPart>, args: Option<Vec<String>>, registers: &mut Vec<RegisterState>, next_var_id: &mut u32, ctx: &Context, traceback: &PrevFunc) -> Compiled {
let mut ops: Vec<Operation> = vec![];
let mut variables: Vec<Variable> = vec![];
@ -598,10 +621,15 @@ fn compile_function(ast: Vec<ASTPart>, args: Option<Vec<String>>, registers: &mu
let mut functions: HashMap<u32, Compiled> = HashMap::new();
let mut next_function_id: u32 = 1;
let empty_tb = PrevFunc {
variables: vec![],
previous: None,
};
match args {
Some(arg_list) => {
for arg in arg_list {
if get_variable_by_name(&variables, &arg, 0).is_some() {
if get_variable_by_name(&variables, &arg, 0, &empty_tb).is_some() {
let err = create_error(&format!("Argument `{}` already exists", arg), 0, ErrorType::SemanticError, ErrorSubType::ArgumentDuplication);
print_error(&err, &ctx);
process::exit(1);
@ -615,7 +643,7 @@ fn compile_function(ast: Vec<ASTPart>, args: Option<Vec<String>>, registers: &mu
let mut op_count = 0;
for ast_op in ast {
do_ast_op(ast_op, &mut op_count, &mut ops, &mut variables, next_var_id, &mut strings, &mut next_string_id, &mut functions, &mut next_function_id, registers, ctx);
do_ast_op(ast_op, &mut op_count, &mut ops, &mut variables, next_var_id, &mut strings, &mut next_string_id, &mut functions, &mut next_function_id, registers, ctx, traceback);
}
ops.push(Operation { opcode: 29, arg1: Some(0), arg2: None, arg3: None, pos: ctx.raw_file.len() as u32 });
for var in &mut variables {
@ -750,7 +778,11 @@ pub fn compile(ast: Vec<ASTPart>, ctx: &Context) -> (Vec<u8>, Vec<Context>) {
});
}
let compiled = compile_function(ast, None, &mut registers, &mut next_var_id, ctx);
let empty_tb = PrevFunc {
variables: vec![],
previous: None,
};
let compiled = compile_function(ast, None, &mut registers, &mut next_var_id, ctx, &empty_tb);
let mut output: Vec<u8> = vec![];
//doctype specifier

View file

@ -1,5 +1,7 @@
gethelj a = lőcsve() {
reti {[szaft"test"szaft]=1}
gethelj a = 5
gethelj b = lőcsve() {
ugass(a, c)
}
gethelj c = 10
ugass(a().test)
b()