From cca26d9fc39f4c9907a67cdc737124b2e0d49b8c Mon Sep 17 00:00:00 2001 From: afonya2 Date: Wed, 11 Jun 2025 17:57:52 +0200 Subject: [PATCH] added more enviroment functions and fixed some argument bugs --- src/compiler.rs | 5 ++- src/enviroment.rs | 76 +++++++++++++++++++++++++++++++++++++++---- src/errors.rs | 3 ++ src/virtualmachine.rs | 44 ++++++++++++++++--------- test.asl | 4 ++- 5 files changed, 107 insertions(+), 25 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index ec7eb7d..6673ad5 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -249,7 +249,10 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec, 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 { diff --git a/src/enviroment.rs b/src/enviroment.rs index 0dcd7ff..03911f6 100644 --- a/src/enviroment.rs +++ b/src/enviroment.rs @@ -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 { +fn ugass(_machine: &mut Machine, _op: &DecompiledOperation, args: Vec) -> 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 { + 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 { + 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 { + 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 { let mut mem: HashMap = 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; } \ No newline at end of file diff --git a/src/errors.rs b/src/errors.rs index acff961..9de5336 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -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:"), } } diff --git a/src/virtualmachine.rs b/src/virtualmachine.rs index 9ccd6a5..eaa9da2 100644 --- a/src/virtualmachine.rs +++ b/src/virtualmachine.rs @@ -50,7 +50,7 @@ pub struct TableValue { } #[derive(Debug, Clone)] pub struct VMMemoryNativeFunction { - pub func: fn(&mut Machine, Vec) -> VMMemory, + pub func: fn(&mut Machine, &DecompiledOperation, Vec) -> VMMemory, pub variable_id: u32, } @@ -62,12 +62,12 @@ struct DecompiledFunction { functions: HashMap } #[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(); }, _ => { diff --git a/test.asl b/test.asl index 13e0870..cc237d2 100644 --- a/test.asl +++ b/test.asl @@ -2,4 +2,6 @@ gethelj a = { [szaft"test"szaft] = szaft"test"szaft, [szaft"teher"szaft] = szaft"teher"szaft } -ugass(a) \ No newline at end of file +ugass(a) +//csömör(szaft"háh, appja hám"szaft) +ugass(tarh(a)) \ No newline at end of file