From 74fa0a85230a23fc2783a042b2f63576d44f95c1 Mon Sep 17 00:00:00 2001 From: afonya2 Date: Wed, 11 Jun 2025 12:52:05 +0200 Subject: [PATCH] functions now can use previous variables --- src/compiler.rs | 150 +++++++++++++++++++++++++++++------------------- test.as | 8 ++- 2 files changed, 96 insertions(+), 62 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index 9b8d30b..4cfb838 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -43,6 +43,12 @@ struct Variable { no_end: bool } +#[derive(Debug, Clone)] +struct PrevFunc { + variables: Vec, + previous: Option>, +} + fn get_register_by_id(registers: &Vec, id: u8) -> RegisterState { for register in registers { if register.id == id { @@ -129,7 +135,7 @@ fn garbage_collect_registers(_registers: &mut Vec) { }*/ } -fn get_variable_by_name(variables: &Vec, name: &str, position: usize) -> Option { +fn get_variable_by_name(variables: &Vec, name: &str, position: usize, traceback: &PrevFunc) -> Option { 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, 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, variables: &mut Vec, next_var_id: &mut u32, strings: &mut HashMap, next_string_id: &mut u32, functions: &mut HashMap, next_function_id: &mut u32, registers: &mut Vec, ctx: &Context) -> u8 { +fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec, variables: &mut Vec, next_var_id: &mut u32, strings: &mut HashMap, next_string_id: &mut u32, functions: &mut HashMap, next_function_id: &mut u32, registers: &mut Vec, 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, 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, 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, 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, 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, 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 = 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, 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, va ops.push(Operation { opcode: 0, arg1: None, arg2: None, arg3: None, pos: else_part.pos as u32 }); let mut fake_vars: Vec = 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, 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 = 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, va return 0; } -fn compile_function(ast: Vec, args: Option>, registers: &mut Vec, next_var_id: &mut u32, ctx: &Context) -> Compiled { +fn compile_function(ast: Vec, args: Option>, registers: &mut Vec, next_var_id: &mut u32, ctx: &Context, traceback: &PrevFunc) -> Compiled { let mut ops: Vec = vec![]; let mut variables: Vec = vec![]; @@ -598,10 +621,15 @@ fn compile_function(ast: Vec, args: Option>, registers: &mu let mut functions: HashMap = 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, args: Option>, 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, ctx: &Context) -> (Vec, Vec) { }); } - 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 = vec![]; //doctype specifier diff --git a/test.as b/test.as index 32877a9..2ac4a5d 100644 --- a/test.as +++ b/test.as @@ -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) \ No newline at end of file +b() \ No newline at end of file