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;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue