added more enviroment functions and fixed some argument bugs

This commit is contained in:
afonya2 2025-06-11 17:57:52 +02:00
parent 12d3250bc4
commit cca26d9fc3
Signed by: afonya
GPG key ID: EBB9C4CAFAAFB2DC
5 changed files with 107 additions and 25 deletions

View file

@ -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 {
let arg_reg = do_ast_op(arg, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx, traceback);
ops.push(Operation { opcode: 28, arg1: Some(arg_reg), arg2: None, arg3: None, pos: call.pos as u32 });
set_register(registers, RegisterState { id: arg_reg, used: false, variable: 0, last_used: 0 });
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);
if ret_reg.unbind_before {

View file

@ -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();
match mem {
VMMemory::String(s) => out.push_str(&s.value),
@ -12,9 +12,9 @@ fn get_string_from_vmmem(mem: VMMemory) -> String {
VMMemory::Table(tbl) => {
out.push_str("{");
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(&get_string_from_vmmem(val.value.clone()));
out.push_str(&get_string_from_vmmem(&val.value.clone()));
out.push_str(", ");
}
out.pop();
@ -32,21 +32,83 @@ fn get_string_from_vmmem(mem: VMMemory) -> String {
}
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();
for arg in args {
out.push_str(&get_string_from_vmmem(arg));
out.push_str(&get_string_from_vmmem(&arg));
out.push_str(" ");
}
println!("{}", out.trim_end());
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> {
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("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;
}

View file

@ -33,6 +33,7 @@ pub enum ErrorSubType {
UnknownString,
UnknownMemoryLocation,
NonFunctionCall,
RuntimeError,
//Math errors
DivisionByZero,
//Type errors
@ -94,6 +95,7 @@ fn convert_subtypes_to_string(stype: &ErrorSubType) -> String {
ErrorSubType::WrongType => String::from("Wrong type"),
ErrorSubType::TooManyArguments => String::from("Too many arguments"),
ErrorSubType::FileError => String::from("File error"),
ErrorSubType::RuntimeError => String::from("Runtime error"),
}
}
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::TooManyArguments => String::from("TA:"),
ErrorSubType::FileError => String::from("FE:"),
ErrorSubType::RuntimeError => String::from("RE:"),
}
}

View file

@ -50,7 +50,7 @@ pub struct TableValue {
}
#[derive(Debug, Clone)]
pub struct VMMemoryNativeFunction {
pub func: fn(&mut Machine, Vec<VMMemory>) -> VMMemory,
pub func: fn(&mut Machine, &DecompiledOperation, Vec<VMMemory>) -> VMMemory,
pub variable_id: u32,
}
@ -62,12 +62,12 @@ struct DecompiledFunction {
functions: HashMap<u32, u32>
}
#[derive(Debug, Clone)]
struct DecompiledOperation {
opcode: u8,
arg1: u8,
arg2: i64,
arg3: u8,
pos: usize,
pub struct DecompiledOperation {
pub opcode: u8,
pub arg1: u8,
pub arg2: i64,
pub arg3: u8,
pub pos: usize,
}
#[derive(Debug, Clone)]
@ -85,9 +85,9 @@ struct Variable {
}
pub struct CallStack {
func: usize,
return_reg: usize,
pc: usize,
pub func: usize,
pub return_reg: usize,
pub pc: usize,
}
pub struct Machine {
@ -110,11 +110,7 @@ fn read_be_num(input: &[u8]) -> usize {
}
fn read_str(input: &[u8]) -> String {
let mut result = String::new();
for &byte in input {
result.push(byte as char);
}
return result;
String::from_utf8(input.to_vec()).expect("Invalid UTF-8 sequence")
}
fn read_bin(input: &[u8]) -> String {
@ -802,7 +798,23 @@ impl Machine {
executed_stack = self.call_stack.len() - 1;
},
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();
},
_ => {

View file

@ -2,4 +2,6 @@ gethelj a = {
[szaft"test"szaft] = szaft"test"szaft,
[szaft"teher"szaft] = szaft"teher"szaft
}
ugass(a)
ugass(a)
//csömör(szaft"háh, appja hám"szaft)
ugass(tarh(a))