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 { 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 {

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(); 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;
} }

View file

@ -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:"),
} }
} }

View file

@ -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();
}, },
_ => { _ => {

View file

@ -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))