begin new error system, unfinished

This commit is contained in:
afonya2 2025-06-06 22:01:53 +02:00
parent 32c2a20697
commit 532fffe725
Signed by: afonya
GPG key ID: EBB9C4CAFAAFB2DC
6 changed files with 673 additions and 237 deletions

View file

@ -1,6 +1,5 @@
use std::{collections::HashMap, vec};
use crate::parser::ASTPart;
use std::{collections::HashMap, process, vec};
use crate::{errors::{create_error, print_error, ErrorType, ErrorSubType}, parser::ASTPart, Context};
const ASXVERSION: [u8; 3] = [0,1,0];
@ -10,6 +9,7 @@ pub struct Operation {
pub arg1: Option<u8>,
pub arg2: Option<i64>,
pub arg3: Option<u8>,
pub pos: u32,
}
#[derive(Debug, Clone)]
@ -139,15 +139,15 @@ fn get_variable_by_name(variables: &Vec<Variable>, name: &str, position: usize)
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>) -> 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) -> u8 {
*op_count += 1;
match ast_op {
ASTPart::Number(num) => {
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: 8, arg1: Some(reg.register), arg2: None, arg3: None, pos: num.pos as u32 });
}
ops.push(Operation { opcode: 3, arg1: Some(reg.register), arg2: Some(num.value), arg3: None });
ops.push(Operation { opcode: 3, arg1: Some(reg.register), arg2: Some(num.value), arg3: None, pos: num.pos as u32 });
set_register(registers, RegisterState { id: reg.register, used: true, variable: 0, last_used: *op_count });
return reg.register;
},
@ -157,27 +157,27 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, va
*next_string_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: 8, arg1: Some(reg.register), arg2: None, arg3: None, pos: str.pos as u32 });
}
ops.push(Operation { opcode: 1, arg1: Some(reg.register), arg2: Some(str_id as i64), arg3: None });
ops.push(Operation { opcode: 1, arg1: Some(reg.register), arg2: Some(str_id as i64), arg3: None, pos: str.pos as u32 });
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: 8, arg1: Some(reg.register), arg2: None, arg3: None, pos: bool.pos as u32 });
}
ops.push(Operation { opcode: 4, arg1: Some(reg.register), arg2: Some(bool.value as i64), arg3: None });
ops.push(Operation { opcode: 4, arg1: Some(reg.register), arg2: Some(bool.value as i64), arg3: None, pos: bool.pos as u32 });
set_register(registers, RegisterState { id: reg.register, used: true, variable: 0, last_used: *op_count });
return reg.register;
},
ASTPart::Null(_) => {
ASTPart::Null(nul) => {
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: 8, arg1: Some(reg.register), arg2: None, arg3: None, pos: nul.pos as u32 });
}
ops.push(Operation { opcode: 6, arg1: Some(reg.register), arg2: Some(0), arg3: None });
ops.push(Operation { opcode: 6, arg1: Some(reg.register), arg2: Some(0), arg3: None, pos: nul.pos as u32 });
set_register(registers, RegisterState { id: reg.register, used: true, variable: 0, last_used: *op_count });
return reg.register;
},
@ -185,13 +185,13 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, va
if get_variable_by_name(variables, &var_read.variable, ops.len()).is_none() {
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: 8, arg1: Some(reg.register), arg2: None, arg3: None, pos: var_read.pos as u32 });
}
let str_id = *next_string_id;
strings.insert(str_id, var_read.variable.clone());
*next_string_id += 1;
ops.push(Operation { opcode: 1, arg1: Some(reg.register), arg2: Some(str_id as i64), arg3: None });
ops.push(Operation { opcode: 30, arg1: Some(0), arg2: Some(reg.register as i64), arg3: Some(reg.register) });
ops.push(Operation { opcode: 1, arg1: Some(reg.register), arg2: Some(str_id as i64), arg3: None, pos: var_read.pos as u32 });
ops.push(Operation { opcode: 30, arg1: Some(0), arg2: Some(reg.register as i64), arg3: Some(reg.register), pos: var_read.pos as u32 });
set_register(registers, RegisterState { id: reg.register, used: true, variable: 0, last_used: *op_count });
return reg.register;
}
@ -199,9 +199,9 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, va
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: 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 });
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 });
return reg.register;
} else {
@ -210,47 +210,47 @@ 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));
functions.insert(func_id, compile_function(func.body, Some(func.args), registers, next_var_id, ctx));
*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: 8, arg1: Some(reg.register), arg2: None, arg3: None, pos: func.pos as u32 });
}
ops.push(Operation { opcode: 5, arg1: Some(reg.register), arg2: Some(func_id as i64), arg3: None });
ops.push(Operation { opcode: 5, arg1: Some(reg.register), arg2: Some(func_id as i64), arg3: None, pos: func.pos as u32 });
set_register(registers, RegisterState { id: reg.register, used: true, variable: 0, last_used: *op_count });
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);
let func = do_ast_op(*call.function, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx);
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);
ops.push(Operation { opcode: 28, arg1: Some(arg_reg), arg2: None, arg3: None });
let arg_reg = do_ast_op(arg, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx);
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 });
}
let ret_reg = allocate_register(registers);
if ret_reg.unbind_before {
ops.push(Operation { opcode: 8, arg1: Some(ret_reg.register), arg2: None, arg3: None });
ops.push(Operation { opcode: 8, arg1: Some(ret_reg.register), arg2: None, arg3: None, pos: call.pos as u32 });
}
ops.push(Operation { opcode: 27, arg1: Some(func), arg2: Some(ret_reg.register as i64), arg3: None });
ops.push(Operation { opcode: 27, arg1: Some(func), arg2: Some(ret_reg.register as i64), arg3: None, pos: call.pos as u32 });
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);
ops.push(Operation { opcode: 24, arg1: Some(condition_reg), arg2: Some(condition_reg as i64), arg3: None });
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);
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() {
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 });
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 });
let op_placeholder = ops.len();
ops.push(Operation { opcode: 0, arg1: None, arg2: None, arg3: None });
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);
do_ast_op(if_op, op_count, ops, &mut fake_vars, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx);
}
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 });
@ -260,39 +260,42 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, va
arg1: Some(condition_reg),
arg2: Some(ops.len() as i64),
arg3: None,
pos: if_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 {
ops.push(Operation { opcode: 8, arg1: Some(condition_reg), arg2: None, arg3: None });
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() {
panic!("Else used without an if statement before it");
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 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 });
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 });
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 });
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 });
ops.push(Operation { opcode: 24, arg1: Some(else_condition_reg), arg2: Some(else_condition_reg as i64), arg3: None, pos: else_part.pos as u32 });
let op_placeholder = ops.len();
ops.push(Operation { opcode: 0, arg1: None, arg2: None, arg3: None });
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);
do_ast_op(else_op, op_count, ops, &mut fake_vars, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx);
}
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 });
@ -302,46 +305,49 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, va
arg1: Some(else_condition_reg),
arg2: Some(ops.len() as i64),
arg3: None,
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 {
ops.push(Operation { opcode: 8, arg1: Some(else_condition_reg), arg2: None, arg3: None });
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() {
panic!("Else if used without an if statement before it");
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 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 });
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 });
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 });
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 });
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);
ops.push(Operation { opcode: 16, arg1: Some(else_condition_reg), arg2: Some(condition_reg as i64), arg3: Some(condition_reg) });
ops.push(Operation { opcode: 24, arg1: Some(condition_reg), arg2: Some(condition_reg as i64), arg3: None });
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);
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 });
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 });
let op_placeholder = ops.len();
ops.push(Operation { opcode: 0, arg1: None, arg2: None, arg3: None });
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);
do_ast_op(elseif_op, op_count, ops, &mut fake_vars, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx);
}
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 });
@ -351,44 +357,46 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, va
arg1: Some(condition_reg),
arg2: Some(ops.len() as i64),
arg3: None,
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 {
ops.push(Operation { opcode: 8, arg1: Some(condition_reg), arg2: None, arg3: None });
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 });
}
garbage_collect_registers(registers);
},
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);
ops.push(Operation { opcode: 24, arg1: Some(condition_reg), arg2: Some(condition_reg as i64), arg3: None });
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);
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();
let mut breaks: Vec<usize> = vec![];
let mut continues: Vec<usize> = vec![];
ops.push(Operation { opcode: 0, arg1: None, arg2: None, arg3: None });
ops.push(Operation { opcode: 0, arg1: None, arg2: None, arg3: None, pos: while_part.pos as u32 });
for while_op in while_part.body {
match while_op {
ASTPart::Break(_) => {
breaks.push(ops.len());
ops.push(Operation { opcode: 0, arg1: None, arg2: None, arg3: None });
ops.push(Operation { opcode: 0, arg1: None, arg2: None, arg3: None, pos: while_part.pos as u32 });
},
ASTPart::Continue(_) => {
continues.push(ops.len());
ops.push(Operation { opcode: 0, arg1: None, arg2: None, arg3: None });
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);
do_ast_op(while_op, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx);
}
}
}
ops.push(Operation { opcode: 25, arg1: None, arg2: Some(start as i64), arg3: None });
ops.push(Operation { opcode: 25, arg1: None, arg2: Some(start as i64), arg3: None, pos: while_part.pos as u32 });
ops[op_placeholder] = Operation {
opcode: 26,
arg1: Some(condition_reg),
arg2: Some(ops.len() as i64),
arg3: None,
pos: while_part.pos as u32
};
for brk in breaks {
ops[brk] = Operation {
@ -396,6 +404,7 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, va
arg1: None,
arg2: Some(ops.len() as i64),
arg3: None,
pos: while_part.pos as u32
};
}
for cont in continues {
@ -404,48 +413,54 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, va
arg1: None,
arg2: Some(start as i64),
arg3: None,
pos: while_part.pos as u32
};
}
},
ASTPart::Break(_) => {
panic!("Unexpected break outside of loop at {}", op_count);
ASTPart::Break(brk) => {
let err = create_error(&format!("Unexpected break outside of loop"), brk.pos, ErrorType::SemanticError, ErrorSubType::BreakContinueWithoutLoop);
print_error(&err, &ctx);
process::exit(1);
},
ASTPart::Continue(_) => {
panic!("Unexpected continue outside of loop at {}", op_count);
ASTPart::Continue(cont) => {
let err = create_error(&format!("Unexpected continue outside of loop"), cont.pos, ErrorType::SemanticError, ErrorSubType::BreakContinueWithoutLoop);
print_error(&err, &ctx);
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);
do_ast_op(*for_part.init, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx);
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);
ops.push(Operation { opcode: 24, arg1: Some(condition_reg), arg2: Some(condition_reg as i64), arg3: None });
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);
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();
let mut breaks: Vec<usize> = vec![];
let mut continues: Vec<usize> = vec![];
ops.push(Operation { opcode: 0, arg1: None, arg2: None, arg3: None });
ops.push(Operation { opcode: 0, arg1: None, arg2: None, arg3: None, pos: for_part.pos as u32 });
for for_op in for_part.body {
match for_op {
ASTPart::Break(_) => {
breaks.push(ops.len());
ops.push(Operation { opcode: 0, arg1: None, arg2: None, arg3: None });
ops.push(Operation { opcode: 0, arg1: None, arg2: None, arg3: None, pos: for_part.pos as u32 });
},
ASTPart::Continue(_) => {
continues.push(ops.len());
ops.push(Operation { opcode: 0, arg1: None, arg2: None, arg3: None });
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);
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_part.update, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers);
do_ast_op(*for_part.update, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx);
ops.push(Operation { opcode: 25, arg1: None, arg2: Some(start as i64), arg3: None });
ops.push(Operation { opcode: 25, arg1: None, arg2: Some(start as i64), arg3: None, pos: for_part.pos as u32 });
ops[op_placeholder] = Operation {
opcode: 26,
arg1: Some(condition_reg),
arg2: Some(ops.len() as i64),
arg3: None,
pos: for_part.pos as u32
};
for brk in breaks {
ops[brk] = Operation {
@ -453,6 +468,7 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, va
arg1: None,
arg2: Some(ops.len() as i64),
arg3: None,
pos: for_part.pos as u32
};
}
for cont in continues {
@ -461,19 +477,20 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, va
arg1: None,
arg2: Some(start as i64),
arg3: None,
pos: for_part.pos as u32
};
}
},
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);
ops.push(Operation { opcode: 29, arg1: Some(ret_reg), arg2: None, arg3: None });
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);
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);
let right_reg = do_ast_op(*op.right, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers);
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 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: 8, arg1: Some(reg.register), arg2: None, arg3: None, pos: op.pos as u32 });
}
let opcode = match op.operator.as_str() {
"+" => 10,
@ -491,78 +508,86 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, va
"<" => 22,
"<=" => 23,
"!" => {
ops.push(Operation { opcode: 24, arg1: Some(left_reg), arg2: Some(reg.register as i64), arg3: None });
ops.push(Operation { opcode: 24, arg1: Some(left_reg), arg2: Some(reg.register as i64), arg3: None, pos: op.pos as u32 });
set_register(registers, RegisterState { id: reg.register, used: true, variable: 0, last_used: *op_count });
return reg.register;
},
_ => panic!("Unknown operator {}", op.operator),
_ => {
let err = create_error(&format!("Unknown operator `{}`", op.operator), op.pos, ErrorType::SyntaxError, ErrorSubType::UnknownOperation);
print_error(&err, &ctx);
process::exit(1);
},
};
ops.push(Operation { opcode, arg1: Some(left_reg), arg2: Some(right_reg as i64), arg3: Some(reg.register) });
ops.push(Operation { opcode, arg1: Some(left_reg), arg2: Some(right_reg as i64), arg3: Some(reg.register), pos: op.pos as u32 });
set_register(registers, RegisterState { id: reg.register, used: true, variable: 0, last_used: *op_count });
return reg.register;
},
ASTPart::VarUpdate(upd) => {
if get_variable_by_name(variables, &upd.variable, ops.len()).is_none() {
panic!("Variable {} does not exist", upd.variable);
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());
if reg.id != 0 {
ops.push(Operation { opcode: 8, arg1: Some(reg.id), arg2: None, arg3: None });
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);
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 });
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 });
garbage_collect_registers(registers);
},
ASTPart::Assigment(asign) => {
if get_variable_by_name(variables, &asign.variable, ops.len()).is_some() {
panic!("Variable {} already exists", asign.variable);
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);
let reg = do_ast_op(*asign.value, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx);
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 });
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 });
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: 8, arg1: Some(reg.register), arg2: None, arg3: None, pos: tbl.pos as u32 });
}
ops.push(Operation { opcode: 6, arg1: Some(reg.register), arg2: Some(1), arg3: None });
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);
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) });
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);
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);
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);
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 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: 8, arg1: Some(reg.register), arg2: None, arg3: None, pos: tbl_get.pos as u32 });
}
ops.push(Operation { opcode: 30, arg1: Some(table_reg), arg2: Some(key_reg as i64), arg3: Some(reg.register) });
ops.push(Operation { opcode: 30, arg1: Some(table_reg), arg2: Some(key_reg as i64), arg3: Some(reg.register), pos: tbl_get.pos as u32 });
set_register(registers, RegisterState { id: reg.register, used: true, variable: 0, last_used: *op_count });
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);
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);
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);
ops.push(Operation { opcode: 31, arg1: Some(table_reg), arg2: Some(key_reg as i64), arg3: Some(value_reg) });
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);
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 });
},
_ => {}
}
return 0;
}
fn compile_function(ast: Vec<ASTPart>, args: Option<Vec<String>>, registers: &mut Vec<RegisterState>, next_var_id: &mut u32) -> Compiled {
fn compile_function(ast: Vec<ASTPart>, args: Option<Vec<String>>, registers: &mut Vec<RegisterState>, next_var_id: &mut u32, ctx: &Context) -> Compiled {
let mut ops: Vec<Operation> = vec![];
let mut variables: Vec<Variable> = vec![];
@ -575,7 +600,9 @@ fn compile_function(ast: Vec<ASTPart>, args: Option<Vec<String>>, registers: &mu
Some(arg_list) => {
for arg in arg_list {
if get_variable_by_name(&variables, &arg, 0).is_some() {
panic!("Argument {} already exists", arg);
let err = create_error(&format!("Argument `{}` already exists", arg), 0, ErrorType::SemanticError, ErrorSubType::ArgumentDuplication);
print_error(&err, &ctx);
process::exit(1);
}
variables.push( Variable { name: arg, id: *next_var_id, start: 0, end: 0, no_end: true });
*next_var_id += 1;
@ -586,9 +613,9 @@ 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);
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);
}
ops.push(Operation { opcode: 29, arg1: Some(0), arg2: None, arg3: None });
ops.push(Operation { opcode: 29, arg1: Some(0), arg2: None, arg3: None, pos: ctx.raw_file.len() as u32 });
for var in &mut variables {
if var.no_end {
var.end = ops.len() - 1;
@ -649,7 +676,7 @@ fn bin_to_num(bin: String) -> usize {
return num;
}
fn compile_body(compiled: Compiled, fpos: &mut usize) -> Vec<u8> {
fn compile_body(compiled: Compiled, fpos: &mut usize, ctx: &Context) -> Vec<u8> {
let mut output: Vec<u8> = vec![];
let mut additional: Vec<Vec<u8>> = vec![];
//function
@ -671,7 +698,7 @@ fn compile_body(compiled: Compiled, fpos: &mut usize) -> Vec<u8> {
*fpos += 1;
append_be_num(&mut output, 3, *funcs as usize);
append_be_num(&mut output, 4, *fpos);
additional.push(compile_body(compiled.functions[funcs].clone(), fpos));
additional.push(compile_body(compiled.functions[funcs].clone(), fpos, ctx));
}
//function body
append_be_num(&mut output, 4, compiled.operations.len());
@ -694,6 +721,7 @@ fn compile_body(compiled: Compiled, fpos: &mut usize) -> Vec<u8> {
}
op_bin.push_str(&num_to_bin(0, 3));
append_binary(&mut output, op_bin);
append_be_num(&mut output, 4, ops.pos as usize);
}
for addition in additional {
output.extend_from_slice(&addition);
@ -702,7 +730,7 @@ fn compile_body(compiled: Compiled, fpos: &mut usize) -> Vec<u8> {
return output;
}
pub fn compile(ast: Vec<ASTPart>) -> Vec<u8> {
pub fn compile(ast: Vec<ASTPart>, ctx: &Context) -> Vec<u8> {
let mut next_var_id: u32 = 1;
let mut registers: Vec<RegisterState> = vec![];
for i in 0..17 {
@ -714,7 +742,7 @@ pub fn compile(ast: Vec<ASTPart>) -> Vec<u8> {
});
}
let compiled = compile_function(ast, None, &mut registers, &mut next_var_id);
let compiled = compile_function(ast, None, &mut registers, &mut next_var_id, ctx);
let mut output: Vec<u8> = vec![];
//doctype specifier
@ -723,10 +751,22 @@ pub fn compile(ast: Vec<ASTPart>) -> Vec<u8> {
output.push(ASXVERSION[0]);
output.push(ASXVERSION[1]);
output.push(ASXVERSION[2]);
//number of functions
output.push(0);
output.push(0);
output.push(0);
output.push(0);
//functions
let mut fpos = 0;
let body = compile_body(compiled, &mut fpos);
let body = compile_body(compiled, &mut fpos, ctx);
output.extend_from_slice(&body);
//update function count
fpos += 1;
output[6] = ((fpos >> 24) & 0xFF) as u8;
output[7] = ((fpos >> 16) & 0xFF) as u8;
output[8] = ((fpos >> 8) & 0xFF) as u8;
output[9] = (fpos & 0xFF) as u8;
return output;
}

220
src/errors.rs Normal file
View file

@ -0,0 +1,220 @@
use std::f32::consts::E;
use crate::Context;
pub enum ErrorType {
SyntaxError,
SemanticError,
TypeError,
MathError,
MachineError,
}
pub enum ErrorSubType {
//Syntax errors
UnexpectedEnd,
Expected,
Unexpected,
UnknownOperation,
InvalidTableKeys,
Unclosed,
//Semantic errors
ElseWithoutIf,
BreakContinueWithoutLoop,
UnexpectedOperation,
VariableNotFound,
VariableAlreadyExists,
ArgumentDuplication,
//Machine errors
RegisterNotFound,
MemoryOutOfBounds,
UnknownOPCode,
UnknownFunction,
UnknownString,
UnknownMemoryLocation,
NonFunctionCall,
//Math errors
DivisionByZero,
//Type errors
InvalidType,
WrongType,
NonStringKey,
}
pub struct ASLError {
pub message: String,
pub position: usize,
pub typ: ErrorType,
pub subtype: ErrorSubType,
pub code: String,
}
fn convert_types_to_string(typ: &ErrorType) -> String {
match typ {
ErrorType::SyntaxError => String::from("Syntax Error: "),
ErrorType::TypeError => String::from("Type Error: "),
ErrorType::MathError => String::from("Math Error: "),
ErrorType::SemanticError => String::from("Semantic Error: "),
ErrorType::MachineError => String::from("Machine Error: "),
}
}
fn convert_types_to_short(typ: &ErrorType) -> String {
match typ {
ErrorType::SyntaxError => String::from("ST:"),
ErrorType::TypeError => String::from("TP:"),
ErrorType::MathError => String::from("MT:"),
ErrorType::SemanticError => String::from("SM:"),
ErrorType::MachineError => String::from("MC:"),
}
}
fn convert_subtypes_to_string(stype: &ErrorSubType) -> String {
match stype {
ErrorSubType::UnexpectedEnd => String::from("Unexpected end"),
ErrorSubType::UnexpectedOperation => String::from("Unexpected operation"),
ErrorSubType::Expected => String::from("Expected"),
ErrorSubType::Unexpected => String::from("Unexpected"),
ErrorSubType::InvalidTableKeys => String::from("Invalid table keys"),
ErrorSubType::Unclosed => String::from("Unclosed structure"),
ErrorSubType::ElseWithoutIf => String::from("Else/elseif without if"),
ErrorSubType::BreakContinueWithoutLoop => String::from("Break/continue without loop"),
ErrorSubType::UnknownOperation => String::from("Unknown operation"),
ErrorSubType::VariableNotFound => String::from("Variable not found"),
ErrorSubType::VariableAlreadyExists => String::from("Variable already exists"),
ErrorSubType::ArgumentDuplication => String::from("Argument duplication"),
ErrorSubType::RegisterNotFound => String::from("Register not found"),
ErrorSubType::MemoryOutOfBounds => String::from("Memory out of bounds"),
ErrorSubType::UnknownOPCode => String::from("Unknown OP code"),
ErrorSubType::UnknownFunction => String::from("Unknown function"),
ErrorSubType::UnknownString => String::from("Unknown string"),
ErrorSubType::UnknownMemoryLocation => String::from("Unknown memory location"),
ErrorSubType::NonFunctionCall => String::from("Non-function call"),
ErrorSubType::DivisionByZero => String::from("Division by zero"),
ErrorSubType::InvalidType => String::from("Invalid type"),
ErrorSubType::WrongType => String::from("Wrong type"),
ErrorSubType::NonStringKey => String::from("Non-string key"),
}
}
fn convert_subtypes_to_short(stype: &ErrorSubType) -> String {
match stype {
ErrorSubType::UnexpectedEnd => String::from("UE:"),
ErrorSubType::UnexpectedOperation => String::from("UP:"),
ErrorSubType::Expected => String::from("EX:"),
ErrorSubType::Unexpected => String::from("UN:"),
ErrorSubType::InvalidTableKeys => String::from("IK:"),
ErrorSubType::Unclosed => String::from("UC:"),
ErrorSubType::ElseWithoutIf => String::from("EW:"),
ErrorSubType::BreakContinueWithoutLoop => String::from("BC:"),
ErrorSubType::UnknownOperation => String::from("UO:"),
ErrorSubType::VariableNotFound => String::from("VN:"),
ErrorSubType::VariableAlreadyExists => String::from("VE:"),
ErrorSubType::ArgumentDuplication => String::from("AD:"),
ErrorSubType::RegisterNotFound => String::from("RF:"),
ErrorSubType::MemoryOutOfBounds => String::from("MO:"),
ErrorSubType::UnknownOPCode => String::from("OC:"),
ErrorSubType::UnknownFunction => String::from("UF:"),
ErrorSubType::UnknownString => String::from("US:"),
ErrorSubType::UnknownMemoryLocation => String::from("UM:"),
ErrorSubType::NonFunctionCall => String::from("NF:"),
ErrorSubType::DivisionByZero => String::from("DZ:"),
ErrorSubType::InvalidType => String::from("IT:"),
ErrorSubType::WrongType => String::from("WT:"),
ErrorSubType::NonStringKey => String::from("NS:"),
}
}
pub fn create_error(message: &str, position: usize, typ: ErrorType, stype: ErrorSubType) -> ASLError {
let mut code = convert_types_to_short(&typ);
code.push_str(&convert_subtypes_to_short(&stype));
code.push_str(&position.to_string());
ASLError {
message: String::from(message),
position,
typ,
subtype: stype,
code,
}
}
fn get_exact_pos(file: &String, pos: usize) -> (usize, usize) {
let mut line = 1;
let mut column = 1;
for (i, c) in file.char_indices() {
if i == pos {
return (line, column);
}
if c == '\n' {
line += 1;
column = 1;
} else {
column += 1;
}
}
(line, column)
}
fn get_sorrunding_lines(file: &String, line: usize) -> (String, String, String) {
let lines = file.lines();
let mut before = String::new();
let mut current = String::new();
let mut after = String::new();
let mut current_line = 1;
for l in lines {
if current_line == line - 1 {
before = l.to_string();
} else if current_line == line {
current = l.to_string();
} else if current_line == line + 1 {
after = l.to_string();
break;
}
current_line += 1;
}
(before, current, after)
}
pub fn print_error(error: &ASLError, ctx: &Context) {
let mut out = String::new();
out.push_str(&convert_types_to_string(&error.typ));
if error.message.len() > 0 {
out.push_str(&convert_subtypes_to_string(&error.subtype));
} else {
out.push_str(&error.message);
}
out.push_str(" at position ");
let (line, column) = get_exact_pos(&ctx.raw_file, error.position);
out.push_str(&ctx.file);
out.push_str(":");
out.push_str(&line.to_string());
out.push_str(":");
out.push_str(&column.to_string());
out.push_str("\n");
let (before, current, after) = get_sorrunding_lines(&ctx.raw_file, line);
if line > 1 {
out.push_str(&(line-1).to_string());
out.push_str(" | ");
} else {
out.push_str(" | ");
}
out.push_str(&before);
out.push_str("\n");
out.push_str(&line.to_string());
out.push_str(" | ");
out.push_str(&current);
out.push_str("\n");
out.push_str(" ");
out.push_str(&" ".repeat(column - 1));
out.push_str("^ ");
out.push_str(&error.message);
out.push_str("\n");
out.push_str(&(line+1).to_string());
out.push_str(" | ");
out.push_str(&after);
out.push_str("\n");
out.push_str("Error Code: ");
out.push_str(&error.code);
println!("{}", out);
}

View file

@ -1,3 +1,6 @@
use std::process;
use crate::{errors::{create_error, print_error, ErrorSubType, ErrorType}, Context};
#[derive(Debug, PartialEq)]
pub enum TokenType {
STRING,
@ -46,7 +49,7 @@ fn is_sep(char: &str) -> bool {
return chars.contains(&check.as_str());
}*/
fn read_string(splitted: &Vec<&str>, pos: &mut usize, out: &mut Vec<Token>) {
fn read_string(splitted: &Vec<&str>, pos: &mut usize, out: &mut Vec<Token>, ctx: &Context) {
let mut str = String::from("");
let start_pos = *pos-1;
*pos += 5;
@ -61,12 +64,14 @@ fn read_string(splitted: &Vec<&str>, pos: &mut usize, out: &mut Vec<Token>) {
str += nchar;
}
if !success {
panic!("Unexpected end of string at {}", pos);
let err = create_error("Unexpected end of string", *pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd);
print_error(&err, &ctx);
process::exit(1);
}
*pos += 5;
out.push(Token { typ: TokenType::STRING, value: str, pos: start_pos });
}
fn read_comment(splitted: &Vec<&str>, pos: &mut usize, is_multiline: bool) {
fn read_comment(splitted: &Vec<&str>, pos: &mut usize, is_multiline: bool, ctx: &Context) {
let mut str = String::from("");
*pos += 1;
let mut success = !is_multiline;
@ -83,7 +88,9 @@ fn read_comment(splitted: &Vec<&str>, pos: &mut usize, is_multiline: bool) {
str += nchar;
}
if !success {
panic!("Unexpected end of comment at {}", pos);
let err = create_error("Unexpected end of comment", *pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd);
print_error(&err, &ctx);
process::exit(1);
}
*pos += 1;
}
@ -204,7 +211,7 @@ fn read_identifier(splitted: &Vec<&str>, pos: &mut usize, out: &mut Vec<Token>)
out.extend(pre_out);
}
pub fn lex(input: String) -> Vec<Token> {
pub fn lex(input: String, ctx: &Context) -> Vec<Token> {
let mut out: Vec<Token> = vec![];
let splitted: Vec<&str> = input.split("").collect();
let mut pos = 1;
@ -232,11 +239,11 @@ pub fn lex(input: String) -> Vec<Token> {
pos -= 1;
out.push(Token { typ: TokenType::NUMBER, value: num, pos: start_pos });
} else if splitted.len() >= pos+5 && splitted[(pos-1)..(pos+5)].join("") == "szaft\"" {
read_string(&splitted, &mut pos, &mut out);
read_string(&splitted, &mut pos, &mut out, ctx);
} else if splitted.len() >= pos+1 && splitted[(pos-1)..(pos+1)].join("") == "//" {
read_comment(&splitted, &mut pos, false);
read_comment(&splitted, &mut pos, false, ctx);
} else if splitted.len() >= pos+1 && splitted[(pos-1)..(pos+1)].join("") == "/*" {
read_comment(&splitted, &mut pos, true);
read_comment(&splitted, &mut pos, true, ctx);
} else if is_mul_operator(char, splitted[pos]) {
out.push(Token { typ: TokenType::OPERATOR, value: String::from(char) + splitted[pos], pos: pos-1 });
pos += 1;

View file

@ -9,6 +9,7 @@ mod parser;
mod enviroment;
mod compiler;
mod virtualmachine;
mod errors;
fn log_ast_part(part: &ASTPart, prefix: String) {
match part {
@ -134,23 +135,33 @@ fn log_ast_part(part: &ASTPart, prefix: String) {
}
}
#[derive(Clone)]
struct Context {
file: String,
raw_file: String,
}
fn main() {
let inp = fs::read_to_string("./test.as");
match inp {
Result::Ok(data) => {
let lexed = lexer::lex(data);
let ctx = Context {
file: String::from("./test.as"),
raw_file: data.clone(),
};
let lexed = lexer::lex(data, &ctx);
println!("Lexer output: ");
for token in &lexed {
println!(" {}: {:?}: {}", token.pos, token.typ, token.value);
}
let ast = parser::parse(lexed);
let ast = parser::parse(lexed, &ctx);
println!("AST: ");
for part in &ast {
log_ast_part(part, String::from(" "));
}
let compiled = compiler::compile(ast);
let compiled = compiler::compile(ast, &ctx);
println!("Compiled output: {:?}", compiled);
let mut vm = Machine::new();
let mut vm = Machine::new(vec![ctx]);
vm.load(compiled);
vm.run();
println!("Registers: {:?}", vm.registers);

View file

@ -1,4 +1,6 @@
use crate::lexer::{Token, TokenType};
use crate::{lexer::{Token, TokenType}, Context};
use std::process;
use crate::errors::{create_error, print_error, ErrorSubType, ErrorType};
#[derive(Debug, Clone, PartialEq)]
pub enum ASTPart {
@ -158,7 +160,7 @@ fn is_end(input: &Token, end: &Vec<Token>) -> bool {
return false;
}
fn read_call(variable: ASTPart, pos: &mut usize, input: &Vec<Token>) -> ASTPart {
fn read_call(variable: ASTPart, pos: &mut usize, input: &Vec<Token>, ctx: &Context) -> ASTPart {
let mut args: Vec<ASTPart> = vec![];
*pos += 1;
let start_pos = input[*pos-1].pos;
@ -176,7 +178,7 @@ fn read_call(variable: ASTPart, pos: &mut usize, input: &Vec<Token>) -> ASTPart
Token { typ: TokenType::SEPARATOR, value: String::from(","), pos: 0 },
Token { typ: TokenType::SEPARATOR, value: String::from(")"), pos: 0 }
];
let arg = read_exp(pos, input, &ends, &ends);
let arg = read_exp(pos, input, &ends, &ends, ctx);
args.push(arg);
}
return ASTPart::Call(AstCall { function: Box::new(variable), args: args, pos: start_pos });
@ -193,7 +195,7 @@ fn operator_precedence(op: &str) -> i64 {
}
}
fn shunt(input: Vec<ASTPart>) -> ASTPart {
fn shunt(input: Vec<ASTPart>, ctx: &Context) -> ASTPart {
let mut output: Vec<ASTPart> = vec![];
let mut stack: Vec<ASTPart> = vec![];
for part in input {
@ -262,7 +264,9 @@ fn shunt(input: Vec<ASTPart>) -> ASTPart {
if op.operator == "!" {
println!("{:?}", output);
if i < 1 {
panic!("Unexpected operation at {}", op.pos);
let err = create_error(&format!("Unexpected operation `{}`", op.operator), op.pos, ErrorType::SemanticError, ErrorSubType::UnexpectedOperation);
print_error(&err, &ctx);
process::exit(1);
}
let left = output[i-1].clone();
output[i] = ASTPart::Operation(AstOperation {
@ -274,7 +278,9 @@ fn shunt(input: Vec<ASTPart>) -> ASTPart {
output.remove(i-1);
} else {
if i < 2 {
panic!("Unexpected operation at {}", op.pos);
let err = create_error(&format!("Unexpected operation `{}`", op.operator), op.pos, ErrorType::SemanticError, ErrorSubType::UnexpectedOperation);
print_error(&err, &ctx);
process::exit(1);
}
let left = output[i-2].clone();
let right = output[i-1].clone();
@ -296,12 +302,14 @@ fn shunt(input: Vec<ASTPart>) -> ASTPart {
}
return output[0].clone();
}
fn read_function(input: &Vec<Token>, pos: &mut usize, with_args: bool) -> ASTPart {
fn read_function(input: &Vec<Token>, pos: &mut usize, with_args: bool, ctx: &Context) -> ASTPart {
let mut args: Vec<String> = vec![];
let start_pos = input[*pos].pos;
if with_args {
if input[*pos].typ != TokenType::SEPARATOR || input[*pos].value != "(" {
panic!("Expected ( at {}", input[*pos].pos);
let err = create_error(&format!("Expected `(`"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::Expected);
print_error(&err, &ctx);
process::exit(1);
}
*pos += 1;
while pos < &mut input.len() {
@ -316,16 +324,22 @@ fn read_function(input: &Vec<Token>, pos: &mut usize, with_args: bool) -> ASTPar
if token.typ == TokenType::IDENTIFIER {
args.push(token.value.clone());
} else {
panic!("Unexpected {:?}({}) at {}", token.typ, token.value, token.pos);
let err = create_error(&format!("Unexpected `{:?}({})`", token.typ, token.value), token.pos, ErrorType::SyntaxError, ErrorSubType::Unexpected);
print_error(&err, &ctx);
process::exit(1);
}
}
if input[*pos].typ != TokenType::SEPARATOR || input[*pos].value != ")" {
panic!("Unexpected end of arguments at {}", input[*pos].pos);
let err = create_error(&format!("Unexpected end of arguments"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd);
print_error(&err, &ctx);
process::exit(1);
}
*pos += 1;
}
if input[*pos].typ != TokenType::SEPARATOR || input[*pos].value != "{" {
panic!("Expected {{ at {}", input[*pos].pos);
let err = create_error(&format!("Expected {{"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::Expected);
print_error(&err, &ctx);
process::exit(1);
}
*pos += 1;
let op_ends: Vec<Token> = vec![
@ -336,15 +350,17 @@ fn read_function(input: &Vec<Token>, pos: &mut usize, with_args: bool) -> ASTPar
let parse_ends: Vec<Token> = vec![
Token { typ: TokenType::SEPARATOR, value: String::from("}"), pos: 0 }
];
let body = parse_internal(input, &op_ends, &parse_ends, pos);
let body = parse_internal(input, &op_ends, &parse_ends, pos, ctx);
if input[*pos].typ != TokenType::SEPARATOR || input[*pos].value != "}" {
panic!("Unexpected end of function at {}", input[*pos].pos);
let err = create_error(&format!("Unexpected end of function"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd);
print_error(&err, &ctx);
process::exit(1);
}
*pos += 1;
return ASTPart::Function(AstFunction { args: args, body: body, pos: start_pos });
}
fn read_table(input: &Vec<Token>, pos: &mut usize) -> ASTPart {
fn read_table(input: &Vec<Token>, pos: &mut usize, ctx: &Context) -> ASTPart {
let start_pos = input[*pos].pos;
let key_ends: Vec<Token> = vec![
Token { typ: TokenType::SEPARATOR, value: String::from("]"), pos: 0 }
@ -358,28 +374,36 @@ fn read_table(input: &Vec<Token>, pos: &mut usize) -> ASTPart {
while *pos < input.len() {
if input[*pos].typ == TokenType::SEPARATOR && input[*pos].value == "[" {
*pos += 1;
let keyy = read_exp(pos, input, &key_ends, &key_ends);
let keyy = read_exp(pos, input, &key_ends, &key_ends, ctx);
match keyy {
ASTPart::Table(_) => {
panic!("Table keys cannot be tables at {}", input[*pos].pos);
let err = create_error(&format!("Table keys cannot be tables"), input[*pos].pos, ErrorType::SemanticError, ErrorSubType::InvalidTableKeys);
print_error(&err, &ctx);
process::exit(1);
},
ASTPart::Function(_) => {
panic!("Table keys cannot be functions at {}", input[*pos].pos);
let err = create_error(&format!("Table keys cannot be functions"), input[*pos].pos, ErrorType::SemanticError, ErrorSubType::InvalidTableKeys);
print_error(&err, &ctx);
process::exit(1);
},
_ => {}
}
if input[*pos].typ != TokenType::SEPARATOR || input[*pos].value != "]" {
panic!("Unexpected end of key at {}", input[*pos].pos);
let err = create_error(&format!("Unexpected end of key"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd);
print_error(&err, &ctx);
process::exit(1);
}
*pos += 1;
if input[*pos].typ != TokenType::SEPARATOR || input[*pos].value != "=" {
panic!("Expected = after key at {}", input[*pos].pos);
let err = create_error(&format!("Expected `=` after key"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::Expected);
print_error(&err, &ctx);
process::exit(1);
}
*pos += 1;
let value = read_exp(pos, input, &ends, &ends);
let value = read_exp(pos, input, &ends, &ends, ctx);
tbl.push(TableValue { key: keyy, value: value, pos: input[*pos].pos });
} else {
let value = read_exp(pos, input, &ends, &ends);
let value = read_exp(pos, input, &ends, &ends, ctx);
tbl.push(TableValue { key: ASTPart::Number(AstNumber { value: key, pos: 0 }), value: value, pos: input[*pos].pos });
key += 1;
}
@ -390,13 +414,15 @@ fn read_table(input: &Vec<Token>, pos: &mut usize) -> ASTPart {
*pos += 1;
continue;
} else {
panic!("Unexpected end of table at {}", input[*pos].pos);
let err = create_error(&format!("Unexpected end of table"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd);
print_error(&err, &ctx);
process::exit(1);
}
}
return ASTPart::Table(AstTable { values: tbl, pos: start_pos });
}
fn read_exp(pos: &mut usize, input: &Vec<Token>, ends: &Vec<Token>, parse_ends: &Vec<Token>) -> ASTPart {
fn read_exp(pos: &mut usize, input: &Vec<Token>, ends: &Vec<Token>, parse_ends: &Vec<Token>, ctx: &Context) -> ASTPart {
let mut expressions: Vec<ASTPart> = vec![];
while pos < &mut input.len() {
let token = &input[*pos];
@ -427,33 +453,41 @@ fn read_exp(pos: &mut usize, input: &Vec<Token>, ends: &Vec<Token>, parse_ends:
} else if token.value == "nincs hám" {
expressions.push(ASTPart::Null(AstNull { pos: token.pos }));
} else if token.value == "lőcsve" {
let func = read_function(input, pos, true);
let func = read_function(input, pos, true, ctx);
expressions.push(func);
} else {
panic!("Unexpected {:?}({}) at {}", token.typ, token.value, token.pos);
let err = create_error(&format!("Unexpected `{:?}({})`", token.typ, token.value), token.pos, ErrorType::SyntaxError, ErrorSubType::Unexpected);
print_error(&err, &ctx);
process::exit(1);
}
} else if token.typ == TokenType::IDENTIFIER {
if next_token.typ == TokenType::SEPARATOR && next_token.value == "(" {
let var = ASTPart::VarRead(AstVarRead { variable: token.value.clone(), pos: token.pos });
expressions.push(read_call(var, pos, input));
expressions.push(read_call(var, pos, input, ctx));
} else if next_token.typ == TokenType::SEPARATOR && next_token.value == "[" {
let var_pos = token.pos;
let key_ends: Vec<Token> = vec![
Token { typ: TokenType::SEPARATOR, value: String::from("]"), pos: 0 }
];
*pos += 1;
let keyy = read_exp(pos, input, &key_ends, &key_ends);
let keyy = read_exp(pos, input, &key_ends, &key_ends, ctx);
match keyy {
ASTPart::Table(_) => {
panic!("Table keys cannot be tables at {}", input[*pos].pos);
let err = create_error(&format!("Table keys cannot be tables"), input[*pos].pos, ErrorType::SemanticError, ErrorSubType::InvalidTableKeys);
print_error(&err, &ctx);
process::exit(1);
},
ASTPart::Function(_) => {
panic!("Table keys cannot be functions at {}", input[*pos].pos);
let err = create_error(&format!("Table keys cannot be functions"), input[*pos].pos, ErrorType::SemanticError, ErrorSubType::InvalidTableKeys);
print_error(&err, &ctx);
process::exit(1);
},
_ => {}
}
if input[*pos].typ != TokenType::SEPARATOR || input[*pos].value != "]" {
panic!("Unexpected end of key at {}", input[*pos].pos);
let err = create_error(&format!("Unexpected end of key"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd);
print_error(&err, &ctx);
process::exit(1);
}
*pos += 1;
expressions.push(ASTPart::TableGet(AstTableGet { table: Box::new(ASTPart::VarRead(AstVarRead { variable: token.value.clone(), pos: var_pos })), key: Box::new(keyy), pos: var_pos+1 }));
@ -468,28 +502,34 @@ fn read_exp(pos: &mut usize, input: &Vec<Token>, ends: &Vec<Token>, parse_ends:
let ends: Vec<Token> = vec![
Token { typ: TokenType::SEPARATOR, value: String::from(")"), pos: 0 }
];
let exp = read_exp(pos, input, &ends, &ends);
let exp = read_exp(pos, input, &ends, &ends, ctx);
if input[*pos].typ == TokenType::SEPARATOR && input[*pos].value == ")" {
*pos += 1;
} else {
panic!("Unclosed parenthesis at {}", token.pos);
let err = create_error(&format!("Unclosed parenthesis"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::Unclosed);
print_error(&err, &ctx);
process::exit(1);
}
expressions.push(exp);
} else if token.value == "{" {
let tbl = read_table(input, pos);
let tbl = read_table(input, pos, ctx);
expressions.push(tbl);
} else {
panic!("Unexpected {:?}({}) at {}", token.typ, token.value, token.pos);
let err = create_error(&format!("Unexpected `{:?}({})`", token.typ, token.value), token.pos, ErrorType::SyntaxError, ErrorSubType::Unexpected);
print_error(&err, &ctx);
process::exit(1);
}
} else {
panic!("Unexpected {:?}({}) at {}", token.typ, token.value, token.pos);
let err = create_error(&format!("Unexpected `{:?}({})`", token.typ, token.value), token.pos, ErrorType::SyntaxError, ErrorSubType::Unexpected);
print_error(&err, &ctx);
process::exit(1);
}
}
let shunted = shunt(expressions);
let shunted = shunt(expressions, ctx);
return shunted;
}
fn next_operation(pos: &mut usize, input: &Vec<Token>, op_ends: &Vec<Token>, parse_ends: &Vec<Token>) -> ASTPart {
fn next_operation(pos: &mut usize, input: &Vec<Token>, op_ends: &Vec<Token>, parse_ends: &Vec<Token>, ctx: &Context) -> ASTPart {
let token = &input[*pos];
let mut next_token = &Token {
typ: TokenType::OPEND,
@ -511,173 +551,233 @@ fn next_operation(pos: &mut usize, input: &Vec<Token>, op_ends: &Vec<Token>, par
let variable = &input[*pos];
*pos += 1;
if variable.typ != TokenType::IDENTIFIER {
panic!("Unexpected {:?} at {}", variable.typ, variable.pos)
let err = create_error(&format!("Unexpected `{:?}`", variable.typ,), token.pos, ErrorType::SyntaxError, ErrorSubType::Unexpected);
print_error(&err, &ctx);
process::exit(1);
}
let eq = &input[*pos];
if eq.typ == TokenType::SEPARATOR && eq.value == "=" {
*pos += 1;
}
let value = read_exp(pos, input, op_ends, parse_ends);
let value = read_exp(pos, input, op_ends, parse_ends, ctx);
return ASTPart::Assigment(AstAssigment { variable: variable.value.clone(), value: Box::new(value), pos: token.pos });
} else if token.value == "ha geny" {
if next_token.typ != TokenType::SEPARATOR || next_token.value != "(" {
panic!("Expected ( at {}", token.pos);
let err = create_error(&format!("Expected `(`"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected);
print_error(&err, &ctx);
process::exit(1);
}
*pos += 1;
let condition_end = vec![
Token { typ: TokenType::SEPARATOR, value: String::from(")"), pos: 0 }
];
let condition = read_exp(pos, input, &condition_end, &condition_end);
let condition = read_exp(pos, input, &condition_end, &condition_end, ctx);
if input[*pos].typ != TokenType::SEPARATOR || input[*pos].value != ")" {
panic!("Unexpected end of condition at {}", token.pos);
let err = create_error(&format!("Unexpected end of condition"), token.pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd);
print_error(&err, &ctx);
process::exit(1);
}
*pos += 1;
let body = read_function(input, pos, false);
let body = read_function(input, pos, false, ctx);
let real_body = match body {
ASTPart::Function(func) => func.body,
_ => panic!("Expected function body at {}", token.pos)
_ => {
let err = create_error(&format!("Expected function body"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected);
print_error(&err, &ctx);
process::exit(1);
}
};
return ASTPart::If(AstIf { condition: Box::new(condition), body: real_body, pos: token.pos });
} else if token.value == "amíg geny" {
if next_token.typ != TokenType::SEPARATOR || next_token.value != "(" {
panic!("Expected ( at {}", token.pos);
let err = create_error(&format!("Expected `(`"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected);
print_error(&err, &ctx);
process::exit(1);
}
*pos += 1;
let condition_end = vec![
Token { typ: TokenType::SEPARATOR, value: String::from(")"), pos: 0 }
];
let condition = read_exp(pos, input, &condition_end, &condition_end);
let condition = read_exp(pos, input, &condition_end, &condition_end, ctx);
if input[*pos].typ != TokenType::SEPARATOR || input[*pos].value != ")" {
panic!("Unexpected end of condition at {}", token.pos);
let err = create_error(&format!("Unexpected end of condition"), token.pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd);
print_error(&err, &ctx);
process::exit(1);
}
*pos += 1;
let body = read_function(input, pos, false);
let body = read_function(input, pos, false, ctx);
let real_body = match body {
ASTPart::Function(func) => func.body,
_ => panic!("Expected function body at {}", token.pos)
_ => {
let err = create_error(&format!("Expected function body"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected);
print_error(&err, &ctx);
process::exit(1);
}
};
return ASTPart::While(AstWhile { condition: Box::new(condition), body: real_body, pos: token.pos });
} else if token.value == "kraf" {
return ASTPart::Break(AstBreak { pos: token.pos });
} else if token.value == "kopva" {
if next_token.typ != TokenType::SEPARATOR || next_token.value != "(" {
panic!("Expected ( at {}", token.pos);
let err = create_error(&format!("Expected `(`"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected);
print_error(&err, &ctx);
process::exit(1);
}
*pos += 1;
let ends = vec![
Token { typ: TokenType::SEPARATOR, value: String::from(")"), pos: 0 },
Token { typ: TokenType::OPEND, value: String::from(";"), pos: 0 }
];
let init = parse_internal(input, &ends, &ends, pos);
let init = parse_internal(input, &ends, &ends, pos, ctx);
if init.len() != 1 {
panic!("Only one expression is expected for init at {}", token.pos);
let err = create_error(&format!("Only one expression is expected for init"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected);
print_error(&err, &ctx);
process::exit(1);
}
if input[*pos].typ != TokenType::OPEND || input[*pos].value != ";" {
panic!("Unexpected end of init at {}", token.pos);
let err = create_error(&format!("Unexpected end of init"), token.pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd);
print_error(&err, &ctx);
process::exit(1);
}
*pos += 1;
let condition = read_exp(pos, input, &ends, &ends);
let condition = read_exp(pos, input, &ends, &ends, ctx);
if input[*pos].typ != TokenType::OPEND || input[*pos].value != ";" {
panic!("Unexpected end of condition at {}", token.pos);
let err = create_error(&format!("Unexpected end of condition"), token.pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd);
print_error(&err, &ctx);
process::exit(1);
}
*pos += 1;
let update = parse_internal(input, &ends, &ends, pos);
let update = parse_internal(input, &ends, &ends, pos, ctx);
if update.len() != 1 {
panic!("Only one expression is expected for update at {}", token.pos);
let err = create_error(&format!("Only one expression is expected for update"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected);
print_error(&err, &ctx);
process::exit(1);
}
if input[*pos].typ != TokenType::SEPARATOR || input[*pos].value != ")" {
panic!("Unexpected end of update at {}", token.pos);
let err = create_error(&format!("Unexpected end of update"), token.pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd);
print_error(&err, &ctx);
process::exit(1);
}
*pos += 1;
let body = read_function(input, pos, false);
let body = read_function(input, pos, false, ctx);
let real_body = match body {
ASTPart::Function(func) => func.body,
_ => panic!("Expected function body at {}", token.pos)
_ => {
let err = create_error(&format!("Expected function body"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected);
print_error(&err, &ctx);
process::exit(1);
}
};
return ASTPart::For(AstFor { init: Box::new(init[0].clone()), condition: Box::new(condition), update: Box::new(update[0].clone()), body: real_body, pos: token.pos });
} else if token.value == "szard le" {
return ASTPart::Continue(AstContinue { pos: token.pos });
} else if token.value == "ha nem geny akkor geny" {
if next_token.typ != TokenType::SEPARATOR || next_token.value != "(" {
panic!("Expected ( at {}", token.pos);
let err = create_error(&format!("Expected `(`"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected);
print_error(&err, &ctx);
process::exit(1);
}
*pos += 1;
let condition_end = vec![
Token { typ: TokenType::SEPARATOR, value: String::from(")"), pos: 0 }
];
let condition = read_exp(pos, input, &condition_end, &condition_end);
let condition = read_exp(pos, input, &condition_end, &condition_end, ctx);
if input[*pos].typ != TokenType::SEPARATOR || input[*pos].value != ")" {
panic!("Unexpected end of condition at {}", token.pos);
let err = create_error(&format!("Unexpected end of condition"), token.pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd);
print_error(&err, &ctx);
process::exit(1);
}
*pos += 1;
let body = read_function(input, pos, false);
let body = read_function(input, pos, false, ctx);
let real_body = match body {
ASTPart::Function(func) => func.body,
_ => panic!("Expected function body at {}", token.pos)
_ => {
let err = create_error(&format!("Expected function body"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected);
print_error(&err, &ctx);
process::exit(1);
}
};
return ASTPart::ElseIf(AstElseIf { condition: Box::new(condition), body: real_body, pos: token.pos });
} else if token.value == "ha nem geny" {
let body = read_function(input, pos, false);
let body = read_function(input, pos, false, ctx);
let real_body = match body {
ASTPart::Function(func) => func.body,
_ => panic!("Expected function body at {}", token.pos)
_ => {
let err = create_error(&format!("Expected function body"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected);
print_error(&err, &ctx);
process::exit(1);
}
};
return ASTPart::Else(AstElse { body: real_body, pos: token.pos });
} else if token.value == "reti" {
if is_end(next_token, op_ends) || is_end(next_token, parse_ends) {
return ASTPart::Return(AstReturn { value: Box::new(ASTPart::Null(AstNull { pos: token.pos })), pos: token.pos });
} else {
let value = read_exp(pos, input, op_ends, parse_ends);
let value = read_exp(pos, input, op_ends, parse_ends, ctx);
return ASTPart::Return(AstReturn { value: Box::new(value), pos: token.pos });
}
} else {
panic!("Unexpected {:?}({}) at {}", token.typ, token.value, token.pos);
let err = create_error(&format!("Unexpected `{:?}({})`", token.typ, token.value), token.pos, ErrorType::SyntaxError, ErrorSubType::Unexpected);
print_error(&err, &ctx);
process::exit(1);
}
} else if token.typ == TokenType::IDENTIFIER {
if next_token.typ == TokenType::SEPARATOR && next_token.value == "(" {
let var = ASTPart::VarRead(AstVarRead { variable: token.value.clone(), pos: token.pos });
return read_call(var, pos, input);
return read_call(var, pos, input, ctx);
} else if next_token.typ == TokenType::SEPARATOR && next_token.value == "[" {
*pos += 1;
let key_ends: Vec<Token> = vec![
Token { typ: TokenType::SEPARATOR, value: String::from("]"), pos: 0 }
];
let keyy = read_exp(pos, input, &key_ends, &key_ends);
let keyy = read_exp(pos, input, &key_ends, &key_ends, ctx);
match keyy {
ASTPart::Table(_) => {
panic!("Table keys cannot be tables at {}", input[*pos].pos);
let err = create_error(&format!("Table keys cannot be tables"), input[*pos].pos, ErrorType::SemanticError, ErrorSubType::InvalidTableKeys);
print_error(&err, &ctx);
process::exit(1);
},
ASTPart::Function(_) => {
panic!("Table keys cannot be functions at {}", input[*pos].pos);
let err = create_error(&format!("Table keys cannot be functions"), input[*pos].pos, ErrorType::SemanticError, ErrorSubType::InvalidTableKeys);
print_error(&err, &ctx);
process::exit(1);
},
_ => {}
}
if input[*pos].typ != TokenType::SEPARATOR || input[*pos].value != "]" {
panic!("Unexpected end of key at {}", input[*pos].pos);
let err = create_error(&format!("Unexpected end of key"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd);
print_error(&err, &ctx);
process::exit(1);
}
*pos += 1;
if input[*pos].typ != TokenType::SEPARATOR || input[*pos].value != "=" {
panic!("Expected = after key at {}", input[*pos].pos);
let err = create_error(&format!("Expected `=` after key"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::Expected);
print_error(&err, &ctx);
process::exit(1);
}
*pos += 1;
let value = read_exp(pos, input, op_ends, parse_ends);
let value = read_exp(pos, input, op_ends, parse_ends, ctx);
return ASTPart::TableSet(AstTableSet { table: Box::new(ASTPart::VarRead(AstVarRead { variable: token.value.clone(), pos: token.pos })), key: Box::new(keyy), value: Box::new(value), pos: token.pos });
} else if next_token.typ == TokenType::SEPARATOR && next_token.value == "=" {
*pos += 1;
let value = read_exp(pos, input, op_ends, parse_ends);
let value = read_exp(pos, input, op_ends, parse_ends, ctx);
return ASTPart::VarUpdate(AstVarUpdate { variable: token.value.clone(), value: Box::new(value), pos: token.pos });
} else {
panic!("Unexpected {:?}({}) at {}", token.typ, token.value, token.pos);
let err = create_error(&format!("Unexpected `{:?}({})`", token.typ, token.value), token.pos, ErrorType::SyntaxError, ErrorSubType::Unexpected);
print_error(&err, &ctx);
process::exit(1);
}
} else {
panic!("Unexpected {:?}({}) at {}", token.typ, token.value, token.pos);
let err = create_error(&format!("Unexpected `{:?}({})`", token.typ, token.value), token.pos, ErrorType::SyntaxError, ErrorSubType::Unexpected);
print_error(&err, &ctx);
process::exit(1);
}
}
fn parse_internal(input: &Vec<Token>, op_ends: &Vec<Token>, parse_ends: &Vec<Token>, pos: &mut usize) -> Vec<ASTPart> {
fn parse_internal(input: &Vec<Token>, op_ends: &Vec<Token>, parse_ends: &Vec<Token>, pos: &mut usize, ctx: &Context) -> Vec<ASTPart> {
let mut out: Vec<ASTPart> = vec![];
while *pos < input.len() {
let op = next_operation(pos, &input, &op_ends, &parse_ends);
let op = next_operation(pos, &input, &op_ends, &parse_ends, ctx);
match op {
ASTPart::NOOP => {},
_ => {
@ -690,7 +790,7 @@ fn parse_internal(input: &Vec<Token>, op_ends: &Vec<Token>, parse_ends: &Vec<Tok
}
return out;
}
pub fn parse(input: Vec<Token>) -> Vec<ASTPart> {
pub fn parse(input: Vec<Token>, ctx: &Context) -> Vec<ASTPart> {
let op_ends: Vec<Token> = vec![
Token { typ: TokenType::OPEND, value: String::from("\n"), pos: 0 },
Token { typ: TokenType::OPEND, value: String::from(";"), pos: 0 },
@ -699,6 +799,6 @@ pub fn parse(input: Vec<Token>) -> Vec<ASTPart> {
let parse_ends: Vec<Token> = vec![
Token { typ: TokenType::OPEND, value: String::from("EOF"), pos: 0 }
];
let out = parse_internal(&input, &op_ends, &parse_ends, &mut 0);
let out = parse_internal(&input, &op_ends, &parse_ends, &mut 0, ctx);
return out;
}

View file

@ -1,6 +1,5 @@
use std::collections::HashMap;
use crate::enviroment;
use std::{collections::HashMap, process, vec};
use crate::{enviroment, errors::{create_error, print_error, ErrorSubType, ErrorType}, Context};
const ASXVERSION: [u8; 3] = [0,1,0];
@ -68,6 +67,7 @@ struct DecompiledOperation {
arg1: u8,
arg2: i64,
arg3: u8,
pos: usize,
}
#[derive(Debug, Clone)]
@ -96,7 +96,8 @@ pub struct Machine {
pub stack: Vec<VMMemory>,
pub registers: Vec<Register>,
pub call_stack: Vec<CallStack>,
pub env: HashMap<String, VMMemory>
pub env: HashMap<String, VMMemory>,
pub ctx: Vec<Context>,
}
fn read_be_num(input: &[u8]) -> usize {
@ -228,18 +229,22 @@ fn get_mem_tbl_val(tbl: &VMMemoryTable, key: VMMemory) -> Option<&VMMemory> {
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, ctx: &Context) {
let reg_clone = registers.clone();
let reg1 = get_register_by_id(&reg_clone, operation.arg1);
let reg2 = get_register_by_id(&reg_clone, operation.arg2 as u8);
let reg3 = get_register_by_id(&reg_clone, operation.arg3);
if reg1.is_none() || reg2.is_none() || reg3.is_none() {
panic!("One or more registers not found for operation");
let err = create_error(&format!("One or more registers not found for operation"), operation.pos, ErrorType::MachineError, ErrorSubType::RegisterNotFound);
print_error(&err, &ctx);
process::exit(1);
}
let mem1 = reg1.unwrap().pointer;
let mem2 = reg2.unwrap().pointer;
if mem1 >= memory.len() || mem2 >= memory.len() || mem1 < 1 || mem2 < 1 {
panic!("Memory location out of bounds for registers {} and {}", operation.arg1, operation.arg2);
let err = create_error(&format!("Memory location out of bounds `{}` or `{}`", mem1, mem2), operation.pos, ErrorType::MachineError, ErrorSubType::MemoryOutOfBounds);
print_error(&err, &ctx);
process::exit(1);
}
let mut result: VMMemory;
match (&memory[mem1], &memory[mem2]) {
@ -256,7 +261,9 @@ fn do_operation_operation(registers: &mut Vec<Register>, memory: &mut Vec<VMMemo
},
13 => {
if num2.value == 0 {
panic!("Division by zero");
let err = create_error(&format!("Division by zero"), operation.pos, ErrorType::MathError, ErrorSubType::DivisionByZero);
print_error(&err, &ctx);
process::exit(1);
}
result = VMMemory::Number(VMMemoryNumber { value: num1.value / num2.value, variable_id: 0 });
},
@ -285,7 +292,9 @@ fn do_operation_operation(registers: &mut Vec<Register>, memory: &mut Vec<VMMemo
result = VMMemory::Boolean(VMMemoryBoolean { value: num1.value <= num2.value, variable_id: 0 });
},
_ => {
panic!("Unknown operation code for number operation: {}", operation.opcode);
let err = create_error(&format!("Unknown operation code for number operation: `{}`", operation.opcode), operation.pos, ErrorType::MachineError, ErrorSubType::UnknownOPCode);
print_error(&err, &ctx);
process::exit(1);
}
};
},
@ -301,7 +310,9 @@ fn do_operation_operation(registers: &mut Vec<Register>, memory: &mut Vec<VMMemo
result = VMMemory::Boolean(VMMemoryBoolean { value: str1.value != str2.value, variable_id: 0 });
},
_ => {
panic!("Unknown operation code for string operation: {}", operation.opcode);
let err = create_error(&format!("Unknown operation code for string operation: `{}`", operation.opcode), operation.pos, ErrorType::MachineError, ErrorSubType::UnknownOPCode);
print_error(&err, &ctx);
process::exit(1);
}
};
},
@ -320,7 +331,9 @@ fn do_operation_operation(registers: &mut Vec<Register>, memory: &mut Vec<VMMemo
result = VMMemory::Boolean(VMMemoryBoolean { value: bool1.value != bool2.value, variable_id: 0 });
},
_ => {
panic!("Unknown operation code for boolean operation: {}", operation.opcode);
let err = create_error(&format!("Unknown operation code for boolean operation: `{}`", operation.opcode), operation.pos, ErrorType::MachineError, ErrorSubType::UnknownOPCode);
print_error(&err, &ctx);
process::exit(1);
}
};
},
@ -333,12 +346,16 @@ fn do_operation_operation(registers: &mut Vec<Register>, memory: &mut Vec<VMMemo
result = VMMemory::Boolean(VMMemoryBoolean { value: false, variable_id: 0 });
},
_ => {
panic!("Unknown operation code for null operation: {}", operation.opcode);
let err = create_error(&format!("Unknown operation code for null operation: `{}`", operation.opcode), operation.pos, ErrorType::MachineError, ErrorSubType::UnknownOPCode);
print_error(&err, &ctx);
process::exit(1);
}
};
},
_ => {
panic!("Invalid memory types for operation: {} and {}", mem1, mem2);
let err = create_error(&format!("Invalid memory types for operation: `{}` and `{}`", mem1, mem2), operation.pos, ErrorType::TypeError, ErrorSubType::InvalidType);
print_error(&err, &ctx);
process::exit(1);
}
}
let mut reg3_pointer = reg3.unwrap().pointer;
@ -431,11 +448,14 @@ fn load_func(data: Vec<u8>, offset: &mut usize) -> DecompiledFunction {
let arg1 = bin_to_num(op[5..9].to_string());
let arg2 = bin_to_snum(op[9..73].to_string());
let arg3 = bin_to_num(op[73..77].to_string());
let pos = read_be_num(&data[*offset..*offset + 4]);
*offset += 4;
body.push(DecompiledOperation {
opcode: op_code as u8,
arg1: arg1 as u8,
arg2: arg2,
arg3: arg3 as u8,
pos: pos,
});
}
println!("Variables: {:?}", variables);
@ -450,7 +470,7 @@ fn load_func(data: Vec<u8>, offset: &mut usize) -> DecompiledFunction {
}
impl Machine {
pub fn new() -> Self {
pub fn new(ctx: Vec<Context>) -> Self {
let mut registers = Vec::new();
for i in 0..17 {
registers.push(Register {
@ -470,7 +490,8 @@ impl Machine {
return_reg: 0,
pc: 0,
}],
env: enviroment::generate()
env: enviroment::generate(),
ctx: ctx,
};
}
@ -481,6 +502,7 @@ impl Machine {
if data[3..6] != ASXVERSION {
panic!("Unsupported ASX version");
}
let _func_count = read_be_num(&data[6..10]);
let mut offset = 6;
while offset < data.len() {
let func = load_func(data.clone(), &mut offset);
@ -494,11 +516,13 @@ impl Machine {
}
let func_clone = self.functions.clone();
let executed_func = func_clone.get(self.call_stack[self.call_stack.len()-1].func);
let mut executed_stack = self.call_stack.len()-1;
if executed_func.is_none() {
panic!("Current function not found!");
let err = create_error(&format!("Current function not found"), 0, ErrorType::MachineError, ErrorSubType::UnknownFunction);
print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone());
process::exit(1);
}
let mut executed_func = executed_func.unwrap();
let mut executed_stack = self.call_stack.len()-1;
while self.call_stack[executed_stack].pc < executed_func.body.len() {
let operation = &executed_func.body[self.call_stack[executed_stack].pc];
self.call_stack[executed_stack].pc += 1;
@ -511,7 +535,9 @@ impl Machine {
//LDS
let str = executed_func.strings.get(&(operation.arg2 as u32));
if str.is_none() {
panic!("String with ID {} not found", operation.arg2);
let err = create_error(&format!("String with ID `{}` not found", operation.arg2), 0, ErrorType::MachineError, ErrorSubType::UnknownString);
print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone());
process::exit(1);
}
let str = str.unwrap();
self.memory.push(VMMemory::String(VMMemoryString { value: str.clone(), variable_id: 0 }));
@ -521,11 +547,15 @@ impl Machine {
//LDM
let mem = get_mem_pos_by_var_id(&self.memory, operation.arg2 as u32);
if mem.is_none() {
panic!("Memory with variable ID {} not found", operation.arg2);
let err = create_error(&format!("Memory with variable ID `{}` not found", operation.arg2), 0, ErrorType::MachineError, ErrorSubType::UnknownMemoryLocation);
print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone());
process::exit(1);
}
let mem = mem.unwrap();
if mem >= self.memory.len() || mem < 1 {
panic!("Memory location out of bounds for variable ID {}", operation.arg2);
let err = create_error(&format!("Memory location out of bounds for variable ID `{}`", operation.arg2), 0, ErrorType::MachineError, ErrorSubType::MemoryOutOfBounds);
print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone());
process::exit(1);
}
let mut nmem = self.memory[mem].clone();
match &mut nmem {
@ -568,12 +598,16 @@ impl Machine {
//LDF
let func_pos = executed_func.functions.get(&(operation.arg2 as u32));
if func_pos.is_none() {
panic!("Function with ID {} not found", operation.arg2);
let err = create_error(&format!("Function with ID `{}` not found", operation.arg2), 0, ErrorType::MachineError, ErrorSubType::UnknownFunction);
print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone());
process::exit(1);
}
let func_pos = func_pos.unwrap();
let func = self.functions.get(*func_pos as usize);
if func.is_none() {
panic!("Function with position {} not found", func_pos);
let err = create_error(&format!("Function with position `{}` not found", func_pos), 0, ErrorType::MachineError, ErrorSubType::UnknownFunction);
print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone());
process::exit(1);
}
self.memory.push(VMMemory::Function(VMMemoryFunction {
id: *func_pos as usize,
@ -595,11 +629,15 @@ impl Machine {
//ASS
let reg = get_register_by_id(&self.registers, operation.arg1);
if reg.is_none() {
panic!("Register {} not found", operation.arg1);
let err = create_error(&format!("Register `{}` not found", operation.arg1), 0, ErrorType::MachineError, ErrorSubType::RegisterNotFound);
print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone());
process::exit(1);
}
let reg = reg.unwrap();
if reg.pointer >= self.memory.len() || reg.pointer < 1 {
panic!("Register {} points to an invalid memory location", operation.arg1);
let err = create_error(&format!("Register `{}` points to an invalid memory location", operation.arg1), 0, ErrorType::MachineError, ErrorSubType::MemoryOutOfBounds);
print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone());
process::exit(1);
}
let used_var = get_mem_pos_by_var_id(&self.memory, operation.arg2 as u32);
if let Some(pos) = used_var {
@ -660,13 +698,15 @@ impl Machine {
let temp_regs = self.registers.clone();
let reg1 = get_register_by_id(&temp_regs, operation.arg1);
if reg1.is_none() {
panic!("Register {} not found", operation.arg1);
let err = create_error(&format!("Register `{}` not found", operation.arg1), 0, ErrorType::MachineError, ErrorSubType::RegisterNotFound);
print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone());
process::exit(1);
}
let reg1 = reg1.unwrap();
set_register(&mut self.registers, Register { id: operation.arg2 as u8, pointer: reg1.pointer });
},
10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 => {
do_operation_operation(&mut self.registers, &mut self.memory, operation);
do_operation_operation(&mut self.registers, &mut self.memory, operation, &self.ctx[self.call_stack[executed_stack].func].clone());
},
24 => {
//NOT
@ -674,7 +714,9 @@ impl Machine {
let reg1 = get_register_by_id(&reg_clone, operation.arg1);
let reg2 = get_register_by_id(&reg_clone, operation.arg2 as u8);
if reg1.is_none() || reg2.is_none() {
panic!("One or more registers not found for operation");
let err = create_error(&format!("Register `{}` or `{}` not found", operation.arg1, operation.arg2), 0, ErrorType::MachineError, ErrorSubType::RegisterNotFound);
print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone());
process::exit(1);
}
let mem1 = reg1.unwrap().pointer;
if mem1 >= self.memory.len() || mem1 < 1 {
@ -737,7 +779,9 @@ impl Machine {
//CJP
let reg = get_register_by_id(&self.registers, operation.arg1);
if reg.is_none() {
panic!("Register {} not found", operation.arg1);
let err = create_error(&format!("Register `{}` not found", operation.arg1), 0, ErrorType::MachineError, ErrorSubType::RegisterNotFound);
print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone());
process::exit(1);
}
let reg = reg.unwrap();
let mem = self.memory.get(reg.pointer);
@ -758,7 +802,9 @@ impl Machine {
//CAL
let reg = get_register_by_id(&self.registers, operation.arg1);
if reg.is_none() {
panic!("Register {} doesn't exist", operation.arg1);
let err = create_error(&format!("Register `{}` not found", operation.arg1), 0, ErrorType::MachineError, ErrorSubType::RegisterNotFound);
print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone());
process::exit(1);
}
let reg = reg.unwrap();
let mem = self.memory.get(reg.pointer);
@ -818,7 +864,9 @@ impl Machine {
//PSH
let reg = get_register_by_id(&self.registers, operation.arg1);
if reg.is_none() {
panic!("Register {} not found", operation.arg1);
let err = create_error(&format!("Register `{}` not found", operation.arg1), 0, ErrorType::MachineError, ErrorSubType::RegisterNotFound);
print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone());
process::exit(1);
}
let reg = reg.unwrap();
let mem = self.memory.get(reg.pointer);
@ -833,7 +881,9 @@ impl Machine {
let target_reg = get_register_by_id(&self.registers, self.call_stack[executed_stack].return_reg as u8);
let ret_reg = get_register_by_id(&self.registers, operation.arg1);
if target_reg.is_none() || ret_reg.is_none() {
panic!("Return register or target register not found");
let err = create_error(&format!("Register `{}` or `{}` not found", self.call_stack[executed_stack].return_reg, operation.arg1), 0, ErrorType::MachineError, ErrorSubType::RegisterNotFound);
print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone());
process::exit(1);
}
let ret_mem = self.memory.get(ret_reg.unwrap().pointer);
if ret_mem.is_none() {
@ -859,7 +909,9 @@ impl Machine {
let reg2 = get_register_by_id(&reg_clone, operation.arg2 as u8);
let reg3 = get_register_by_id(&reg_clone, operation.arg3);
if reg2.is_none() || reg3.is_none() {
panic!("One or more registers not found for GET operation");
let err = create_error(&format!("Register `{}` or `{}` not found", operation.arg2, operation.arg3), 0, ErrorType::MachineError, ErrorSubType::RegisterNotFound);
print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone());
process::exit(1);
}
let mem2 = self.memory.get(reg2.unwrap().pointer);
if mem2.is_none() {
@ -925,7 +977,9 @@ impl Machine {
let reg2 = get_register_by_id(&reg_clone, operation.arg2 as u8);
let reg3 = get_register_by_id(&reg_clone, operation.arg3);
if reg.is_none() || reg2.is_none() || reg3.is_none() {
panic!("One or more registers not found for SET operation");
let err = create_error(&format!("Register `{}` or `{}` or `{}` not found", operation.arg1, operation.arg2, operation.arg3), 0, ErrorType::MachineError, ErrorSubType::RegisterNotFound);
print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone());
process::exit(1);
}
let mem1 = self.memory.get(reg.unwrap().pointer);
let mem2 = self.memory.get(reg2.unwrap().pointer);
@ -994,7 +1048,9 @@ impl Machine {
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 err = create_error(&format!("Register `{}` or `{}` or `{}` not found", operation.arg1, operation.arg2, operation.arg3), 0, ErrorType::MachineError, ErrorSubType::RegisterNotFound);
print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone());
process::exit(1);
}
let mem1 = self.memory.get(reg.unwrap().pointer);
let mem2 = self.memory.get(reg2.unwrap().pointer);
@ -1015,7 +1071,9 @@ impl Machine {
}
},
_ => {
panic!("Unknown operation code: {}", operation.opcode);
let err = create_error(&format!("Unknown operation code: `{}`", operation.opcode), 0, ErrorType::MachineError, ErrorSubType::UnknownOPCode);
print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone());
process::exit(1);
}
}
}