added more enviroment functions and fixed some argument bugs
This commit is contained in:
parent
12d3250bc4
commit
cca26d9fc3
5 changed files with 107 additions and 25 deletions
|
@ -249,7 +249,10 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, va
|
||||||
for arg in call.args {
|
for arg in call.args {
|
||||||
let arg_reg = do_ast_op(arg, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx, traceback);
|
let arg_reg = do_ast_op(arg, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx, traceback);
|
||||||
ops.push(Operation { opcode: 28, arg1: Some(arg_reg), arg2: None, arg3: None, pos: call.pos as u32 });
|
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 reg = get_register_by_id(registers, arg_reg);
|
||||||
|
if reg.variable == 0 {
|
||||||
|
set_register(registers, RegisterState { id: arg_reg, used: false, variable: 0, last_used: 0 });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
let ret_reg = allocate_register(registers);
|
let ret_reg = allocate_register(registers);
|
||||||
if ret_reg.unbind_before {
|
if ret_reg.unbind_before {
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use std::collections::HashMap;
|
use std::{collections::HashMap, process, thread::sleep, time::Duration};
|
||||||
|
|
||||||
use crate::virtualmachine::{Machine, VMMemory, VMMemoryNativeFunction, VMMemoryNull};
|
use crate::{errors::{create_error, print_error, ErrorSubType, ErrorType}, virtualmachine::{DecompiledOperation, Machine, VMMemory, VMMemoryNativeFunction, VMMemoryNull, VMMemoryString}};
|
||||||
|
|
||||||
fn get_string_from_vmmem(mem: VMMemory) -> String {
|
fn get_string_from_vmmem(mem: &VMMemory) -> String {
|
||||||
let mut out = String::new();
|
let mut out = String::new();
|
||||||
match mem {
|
match mem {
|
||||||
VMMemory::String(s) => out.push_str(&s.value),
|
VMMemory::String(s) => out.push_str(&s.value),
|
||||||
|
@ -12,9 +12,9 @@ fn get_string_from_vmmem(mem: VMMemory) -> String {
|
||||||
VMMemory::Table(tbl) => {
|
VMMemory::Table(tbl) => {
|
||||||
out.push_str("{");
|
out.push_str("{");
|
||||||
for val in &tbl.values {
|
for val in &tbl.values {
|
||||||
out.push_str(&get_string_from_vmmem(val.key.clone()));
|
out.push_str(&get_string_from_vmmem(&val.key.clone()));
|
||||||
out.push_str("=");
|
out.push_str("=");
|
||||||
out.push_str(&get_string_from_vmmem(val.value.clone()));
|
out.push_str(&get_string_from_vmmem(&val.value.clone()));
|
||||||
out.push_str(", ");
|
out.push_str(", ");
|
||||||
}
|
}
|
||||||
out.pop();
|
out.pop();
|
||||||
|
@ -32,21 +32,83 @@ fn get_string_from_vmmem(mem: VMMemory) -> String {
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
fn get_type_str(mem: &VMMemory) -> String {
|
||||||
|
match mem {
|
||||||
|
VMMemory::String(_) => "string".to_string(),
|
||||||
|
VMMemory::Number(_) => "number".to_string(),
|
||||||
|
VMMemory::Boolean(_) => "boolean".to_string(),
|
||||||
|
VMMemory::Null(_) => "null".to_string(),
|
||||||
|
VMMemory::Table(_) => "table".to_string(),
|
||||||
|
VMMemory::Function(_) => "function".to_string(),
|
||||||
|
VMMemory::NativeFunction(_) => "native_function".to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn expect(mem: &VMMemory, expected_type: &str) -> bool {
|
||||||
|
let actual_type = get_type_str(&mem);
|
||||||
|
if actual_type == expected_type {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn error(msg: String, machine: &Machine, op: &DecompiledOperation) {
|
||||||
|
let err = create_error(&msg, op.pos, ErrorType::MachineError, ErrorSubType::RuntimeError);
|
||||||
|
let curr = machine.call_stack.len()-1;
|
||||||
|
let func = machine.call_stack[curr].func;
|
||||||
|
print_error(&err, &machine.ctx[func]);
|
||||||
|
process::exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
fn ugass(_machine: &mut Machine, args: Vec<VMMemory>) -> VMMemory {
|
fn ugass(_machine: &mut Machine, _op: &DecompiledOperation, args: Vec<VMMemory>) -> VMMemory {
|
||||||
let mut out = String::new();
|
let mut out = String::new();
|
||||||
for arg in args {
|
for arg in args {
|
||||||
out.push_str(&get_string_from_vmmem(arg));
|
out.push_str(&get_string_from_vmmem(&arg));
|
||||||
out.push_str(" ");
|
out.push_str(" ");
|
||||||
}
|
}
|
||||||
println!("{}", out.trim_end());
|
println!("{}", out.trim_end());
|
||||||
return VMMemory::Null(VMMemoryNull { variable_id: 0 });
|
return VMMemory::Null(VMMemoryNull { variable_id: 0 });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn bimba(machine: &mut Machine, op: &DecompiledOperation, args: Vec<VMMemory>) -> VMMemory {
|
||||||
|
if args.len() < 1 || !expect(&args[0], "number") {
|
||||||
|
error(format!("#1 number expected got {}", get_type_str(&args[0])), machine, op);
|
||||||
|
}
|
||||||
|
match &args[0] {
|
||||||
|
VMMemory::Number(n) => {
|
||||||
|
sleep(Duration::from_millis(n.value as u64));
|
||||||
|
},
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
return VMMemory::Null(VMMemoryNull { variable_id: 0 });
|
||||||
|
}
|
||||||
|
|
||||||
|
fn csomor(machine: &mut Machine, op: &DecompiledOperation, args: Vec<VMMemory>) -> VMMemory {
|
||||||
|
if args.len() < 1 || !expect(&args[0], "string") {
|
||||||
|
error(format!("#1 string expected got {}", get_type_str(&args[0])), machine, op);
|
||||||
|
}
|
||||||
|
match &args[0] {
|
||||||
|
VMMemory::String(s) => {
|
||||||
|
error(s.value.clone(), machine, op);
|
||||||
|
},
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
return VMMemory::Null(VMMemoryNull { variable_id: 0 });
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tarh(_machine: &mut Machine, _op: &DecompiledOperation, args: Vec<VMMemory>) -> VMMemory {
|
||||||
|
if args.len() < 1 {
|
||||||
|
return VMMemory::String(VMMemoryString { value: String::from("null"), variable_id: 0 });
|
||||||
|
}
|
||||||
|
return VMMemory::String(VMMemoryString { value: get_type_str(&args[0]), variable_id: 0 });
|
||||||
|
}
|
||||||
|
|
||||||
pub fn generate() -> HashMap<String, VMMemory> {
|
pub fn generate() -> HashMap<String, VMMemory> {
|
||||||
let mut mem: HashMap<String, VMMemory> = HashMap::new();
|
let mut mem: HashMap<String, VMMemory> = HashMap::new();
|
||||||
|
|
||||||
mem.insert(String::from("ugass"), VMMemory::NativeFunction(VMMemoryNativeFunction { func: ugass, variable_id: 0 }));
|
mem.insert(String::from("ugass"), VMMemory::NativeFunction(VMMemoryNativeFunction { func: ugass, variable_id: 0 }));
|
||||||
|
mem.insert(String::from("bimba"), VMMemory::NativeFunction(VMMemoryNativeFunction { func: bimba, variable_id: 0 }));
|
||||||
|
mem.insert(String::from("csömör"), VMMemory::NativeFunction(VMMemoryNativeFunction { func: csomor, variable_id: 0 }));
|
||||||
|
mem.insert(String::from("tarh"), VMMemory::NativeFunction(VMMemoryNativeFunction { func: tarh, variable_id: 0 }));
|
||||||
|
|
||||||
return mem;
|
return mem;
|
||||||
}
|
}
|
|
@ -33,6 +33,7 @@ pub enum ErrorSubType {
|
||||||
UnknownString,
|
UnknownString,
|
||||||
UnknownMemoryLocation,
|
UnknownMemoryLocation,
|
||||||
NonFunctionCall,
|
NonFunctionCall,
|
||||||
|
RuntimeError,
|
||||||
//Math errors
|
//Math errors
|
||||||
DivisionByZero,
|
DivisionByZero,
|
||||||
//Type errors
|
//Type errors
|
||||||
|
@ -94,6 +95,7 @@ fn convert_subtypes_to_string(stype: &ErrorSubType) -> String {
|
||||||
ErrorSubType::WrongType => String::from("Wrong type"),
|
ErrorSubType::WrongType => String::from("Wrong type"),
|
||||||
ErrorSubType::TooManyArguments => String::from("Too many arguments"),
|
ErrorSubType::TooManyArguments => String::from("Too many arguments"),
|
||||||
ErrorSubType::FileError => String::from("File error"),
|
ErrorSubType::FileError => String::from("File error"),
|
||||||
|
ErrorSubType::RuntimeError => String::from("Runtime error"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn convert_subtypes_to_short(stype: &ErrorSubType) -> String {
|
fn convert_subtypes_to_short(stype: &ErrorSubType) -> String {
|
||||||
|
@ -121,6 +123,7 @@ fn convert_subtypes_to_short(stype: &ErrorSubType) -> String {
|
||||||
ErrorSubType::WrongType => String::from("WT:"),
|
ErrorSubType::WrongType => String::from("WT:"),
|
||||||
ErrorSubType::TooManyArguments => String::from("TA:"),
|
ErrorSubType::TooManyArguments => String::from("TA:"),
|
||||||
ErrorSubType::FileError => String::from("FE:"),
|
ErrorSubType::FileError => String::from("FE:"),
|
||||||
|
ErrorSubType::RuntimeError => String::from("RE:"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,7 @@ pub struct TableValue {
|
||||||
}
|
}
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct VMMemoryNativeFunction {
|
pub struct VMMemoryNativeFunction {
|
||||||
pub func: fn(&mut Machine, Vec<VMMemory>) -> VMMemory,
|
pub func: fn(&mut Machine, &DecompiledOperation, Vec<VMMemory>) -> VMMemory,
|
||||||
pub variable_id: u32,
|
pub variable_id: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,12 +62,12 @@ struct DecompiledFunction {
|
||||||
functions: HashMap<u32, u32>
|
functions: HashMap<u32, u32>
|
||||||
}
|
}
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
struct DecompiledOperation {
|
pub struct DecompiledOperation {
|
||||||
opcode: u8,
|
pub opcode: u8,
|
||||||
arg1: u8,
|
pub arg1: u8,
|
||||||
arg2: i64,
|
pub arg2: i64,
|
||||||
arg3: u8,
|
pub arg3: u8,
|
||||||
pos: usize,
|
pub pos: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
@ -85,9 +85,9 @@ struct Variable {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CallStack {
|
pub struct CallStack {
|
||||||
func: usize,
|
pub func: usize,
|
||||||
return_reg: usize,
|
pub return_reg: usize,
|
||||||
pc: usize,
|
pub pc: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Machine {
|
pub struct Machine {
|
||||||
|
@ -110,11 +110,7 @@ fn read_be_num(input: &[u8]) -> usize {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_str(input: &[u8]) -> String {
|
fn read_str(input: &[u8]) -> String {
|
||||||
let mut result = String::new();
|
String::from_utf8(input.to_vec()).expect("Invalid UTF-8 sequence")
|
||||||
for &byte in input {
|
|
||||||
result.push(byte as char);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_bin(input: &[u8]) -> String {
|
fn read_bin(input: &[u8]) -> String {
|
||||||
|
@ -802,7 +798,23 @@ impl Machine {
|
||||||
executed_stack = self.call_stack.len() - 1;
|
executed_stack = self.call_stack.len() - 1;
|
||||||
},
|
},
|
||||||
VMMemory::NativeFunction(nfunc) => {
|
VMMemory::NativeFunction(nfunc) => {
|
||||||
(nfunc.func)(self, self.stack.clone());
|
let mut result = (nfunc.func)(self, &operation, self.stack.clone());
|
||||||
|
let ret_reg = get_register_by_id(&self.registers, operation.arg2 as u8);
|
||||||
|
if ret_reg.is_none() {
|
||||||
|
let err = create_error(&format!("Register `{}` not found", operation.arg2), operation.pos, ErrorType::MachineError, ErrorSubType::RegisterNotFound);
|
||||||
|
print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone());
|
||||||
|
process::exit(1);
|
||||||
|
}
|
||||||
|
let mut ret_pointer = ret_reg.unwrap().pointer;
|
||||||
|
if ret_pointer >= self.memory.len() || ret_pointer < 1 {
|
||||||
|
self.memory.push(VMMemory::Null(VMMemoryNull { variable_id: 0 }));
|
||||||
|
ret_pointer = self.memory.len() - 1;
|
||||||
|
set_register(&mut self.registers, Register { id: operation.arg2 as u8, pointer: ret_pointer });
|
||||||
|
}
|
||||||
|
let var_id = get_var_id(&self.memory[ret_pointer]);
|
||||||
|
set_var_id(&mut result, var_id);
|
||||||
|
self.memory[ret_pointer] = result;
|
||||||
|
|
||||||
self.stack.clear();
|
self.stack.clear();
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
|
|
4
test.asl
4
test.asl
|
@ -2,4 +2,6 @@ gethelj a = {
|
||||||
[szaft"test"szaft] = szaft"test"szaft,
|
[szaft"test"szaft] = szaft"test"szaft,
|
||||||
[szaft"teher"szaft] = szaft"teher"szaft
|
[szaft"teher"szaft] = szaft"teher"szaft
|
||||||
}
|
}
|
||||||
ugass(a)
|
ugass(a)
|
||||||
|
//csömör(szaft"háh, appja hám"szaft)
|
||||||
|
ugass(tarh(a))
|
Loading…
Add table
Add a link
Reference in a new issue