begin new error system, unfinished
This commit is contained in:
parent
32c2a20697
commit
532fffe725
6 changed files with 673 additions and 237 deletions
254
src/compiler.rs
254
src/compiler.rs
|
@ -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
220
src/errors.rs
Normal 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(¤t);
|
||||
|
||||
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);
|
||||
}
|
23
src/lexer.rs
23
src/lexer.rs
|
@ -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;
|
||||
|
|
19
src/main.rs
19
src/main.rs
|
@ -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);
|
||||
|
|
266
src/parser.rs
266
src/parser.rs
|
@ -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;
|
||||
}
|
|
@ -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(®_clone, operation.arg1);
|
||||
let reg2 = get_register_by_id(®_clone, operation.arg2 as u8);
|
||||
let reg3 = get_register_by_id(®_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(®_clone, operation.arg1);
|
||||
let reg2 = get_register_by_id(®_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(®_clone, operation.arg2 as u8);
|
||||
let reg3 = get_register_by_id(®_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(®_clone, operation.arg2 as u8);
|
||||
let reg3 = get_register_by_id(®_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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue