From ae1cc90a2ac277e7d188b5cdb1fe9ec7abdac70a Mon Sep 17 00:00:00 2001 From: afonya Date: Tue, 17 Jun 2025 19:38:20 +0200 Subject: [PATCH 01/19] added a download button to the docs site --- docs/src/pages/index.tsx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/src/pages/index.tsx b/docs/src/pages/index.tsx index 1303cd7..1b44412 100644 --- a/docs/src/pages/index.tsx +++ b/docs/src/pages/index.tsx @@ -23,6 +23,12 @@ function HomepageHeader() { to="/docs/intro"> Nézd meg a dokumentációt! + + Töltsd le! + From 10eef39f12ca2aaa6b88a73bffa89874dbad36ea Mon Sep 17 00:00:00 2001 From: afonya Date: Tue, 17 Jun 2025 23:47:38 +0200 Subject: [PATCH 02/19] made a basic extension --- docs/docs/langfunctions.md | 2 +- extension/astrolang.tmLanguage.json | 35 +++++++++++ extension/index.js | 79 +++++++++++++++++++++++++ extension/language-configuration.json | 24 ++++++++ extension/package.json | 41 +++++++++++++ extension/snippets.json | 84 +++++++++++++++++++++++++++ 6 files changed, 264 insertions(+), 1 deletion(-) create mode 100644 extension/astrolang.tmLanguage.json create mode 100644 extension/index.js create mode 100644 extension/language-configuration.json create mode 100644 extension/package.json create mode 100644 extension/snippets.json diff --git a/docs/docs/langfunctions.md b/docs/docs/langfunctions.md index 8434f5a..13562ad 100644 --- a/docs/docs/langfunctions.md +++ b/docs/docs/langfunctions.md @@ -252,7 +252,7 @@ ugass(a[0]) // 1 ``` ### Gyors lekérés -Használat: `tábla[kulcs]` +Használat: `tábla.kulcs` :::warning diff --git a/extension/astrolang.tmLanguage.json b/extension/astrolang.tmLanguage.json new file mode 100644 index 0000000..5244766 --- /dev/null +++ b/extension/astrolang.tmLanguage.json @@ -0,0 +1,35 @@ +{ + "scopeName": "source.astrolang", + "patterns": [ + { + "name": "comment.line.astrolang", + "match": "//.*$" + }, + { + "name": "comment.block.astrolang", + "begin": "/\\*", + "end": "\\*/" + }, + { + "name": "keyword.control.astrolang", + "match": "\\b(kraf|piszolj|ha nem geny akkor geny|ha nem geny|nem piszv|kopva|gethelj|ha geny|lőcsve|csecs|reti|piszv|amíg geny|nincs hám|szard le|hámozd|be|ba)\\b" + }, + { + "name": "keyword.operator.astrolang", + "match": "(\\+|-|\\*|\\/|%|=|==|!=|<=|>=|<|>|&&|\\|\\||!)" + }, + { + "name": "string.quoted.double.astrolang", + "begin": "(?<=szaft)\"", + "end": "\"(?=szaft)" + }, + { + "name": "variable.astrolang", + "match": "\\b([a-zA-Z_][a-zA-Z0-9_]*)\\b" + }, + { + "name": "constant.numeric.astrolang", + "match": "([0-9]+)" + } + ] +} \ No newline at end of file diff --git a/extension/index.js b/extension/index.js new file mode 100644 index 0000000..7d50f2c --- /dev/null +++ b/extension/index.js @@ -0,0 +1,79 @@ +import * as vscode from 'vscode' + +vscode.languages.registerCompletionItemProvider('astrolang', { + provideCompletionItems() { + const words = [ + "kraf", + "piszolj", + "ha nem geny akkor geny", + "ha nem geny", + "nem piszv", + "kopva", + "gethelj", + "ha geny", + "lőcsve", + "csecs", + "reti", + "piszv", + "amíg geny", + "nincs hám", + "szard le", + "hámozd", + "be", + "ba", + "szaft" + ] + const env = [ + "ugass", + "bimba", + "csömör", + "tarh", + "bimbabemb", + "nerd", + "tábla", + "kábel", + "szenvedés", + + "abs", + "kerek", + "sin", + "cos", + "tan", + "sqrt", + "legnagyobb", + "legkisebb", + "pi", + + "csemerd fel", + "csemerd le", + "hossz", + "ismételd", + "uno reverse", + "darabos", + "keres", + "átrak", + "számmá", + "betűvé", + + "hozzáad", + "töröl", + "kulcsok", + + "vége", + + "halgass", + "kérés", + "írj", + "olvass", + "zár" + ] + let out = [] + for (let i = 0; i < words.length; i++) { + out.push(new vscode.CompletionItem(words[i], vscode.CompletionItemKind.Keyword)) + } + for (let i = 0; i < env.length; i++) { + out.push(new vscode.CompletionItem(env[i], vscode.CompletionItemKind.Variable)) + } + return out + } +}) \ No newline at end of file diff --git a/extension/language-configuration.json b/extension/language-configuration.json new file mode 100644 index 0000000..c973f64 --- /dev/null +++ b/extension/language-configuration.json @@ -0,0 +1,24 @@ +{ + "comments": { + "lineComment": "//", + "blockComment": ["/*", "*/"] + }, + "brackets": [ + ["{", "}"], + ["[", "]"], + ["(", ")"] + ], + "autoClosingPairs": [ + { "open": "{", "close": "}" }, + { "open": "[", "close": "]" }, + { "open": "(", "close": ")" }, + { "open": "/*", "close": " */", "notIn": ["string"] }, + { "open": "szaft\"", "close": "\"szaft", "notIn": ["string"] } + ], + "surroundingPairs": [ + ["{", "}"], + ["[", "]"], + ["(", ")"], + ["szaft\"", "\"szaft"] + ] +} diff --git a/extension/package.json b/extension/package.json new file mode 100644 index 0000000..5617a1a --- /dev/null +++ b/extension/package.json @@ -0,0 +1,41 @@ +{ + "name": "asl-extension", + "version": "0.2.0", + "description": "The extension for Astro Lang", + "license": "MIT", + "author": "Afonya", + "type": "module", + "main": "index.js", + "engines": { + "vscode": "^1.22.0" + }, + "contributes": { + "languages": [ + { + "id": "astrolang", + "aliases": [ + "Astro Lang", + "AstroLang", + "ASL" + ], + "extensions": [ + ".asl" + ], + "configuration": "./language-configuration.json" + } + ], + "grammars": [ + { + "language": "astrolang", + "scopeName": "source.astrolang", + "path": "./astrolang.tmLanguage.json" + } + ], + "snippets": [ + { + "language": "astrolang", + "path": "./snippets.json" + } + ] + } +} diff --git a/extension/snippets.json b/extension/snippets.json new file mode 100644 index 0000000..b949adb --- /dev/null +++ b/extension/snippets.json @@ -0,0 +1,84 @@ +{ + "if": { + "prefix": "ha geny", + "body": [ + "ha geny(${1:feltétel}) {", + "$0", + "}" + ], + "description": "Egy if" + }, + "else": { + "prefix": "ha nem geny", + "body": [ + "ha nem geny {", + "$0", + "}" + ], + "description": "Egy else" + }, + "elseif": { + "prefix": "ha nem geny akkor geny", + "body": [ + "ha nem geny akkor geny(${1:feltétel}) {", + "$0", + "}" + ], + "description": "Egy else if" + }, + "while": { + "prefix": "amíg geny", + "body": [ + "amíg geny(${1:feltétel}) {", + "$0", + "}" + ], + "description": "Egy while ciklus" + }, + "for": { + "prefix": "kraf", + "body": [ + "kraf(gethelj ${1:i} = ${2:0}; ${3:feltétel}; ${1:i}=${1:i}+1) {", + "$0", + "}" + ], + "description": "Egy for ciklus" + }, + "var create": { + "prefix": "gethelj", + "body": [ + "gethelj ${1:változó} = ${2:érték}" + ], + "description": "Egy változó létrehozása" + }, + "function create": { + "prefix": "lőcsve", + "body": [ + "lőcsve ${1:függvény név}(${2:paraméterek}) {", + "$0", + "}" + ], + "description": "Egy függvény létrehozása" + }, + "import": { + "prefix": "hámozd", + "body": [ + "hámozd ${1:modul név} ${2|be,ba|} szaft\"${3:elérési út}\"szaft" + ], + "description": "Egy modul importálása" + }, + "string": { + "prefix": "szaft", + "body": [ + "szaft\"${1:szöveg}\"szaft" + ], + "description": "Egy szöveg létrehozása" + }, + "print": { + "prefix": "ugass", + "body": [ + "ugass(${1:üzenet})" + ], + "description": "Egy üzenet kiírása a konzolra" + } +} \ No newline at end of file From b35f52d02e7e6bedb4d0c6403c8ae2b12b0093d5 Mon Sep 17 00:00:00 2001 From: afonya Date: Wed, 18 Jun 2025 00:05:17 +0200 Subject: [PATCH 03/19] added some more enviroment functions (table, filesystem) --- src/enviroment.rs | 97 ++++++++++++++++++++++++++++++++++++++++++++++- src/main.rs | 2 +- 2 files changed, 97 insertions(+), 2 deletions(-) diff --git a/src/enviroment.rs b/src/enviroment.rs index 08c9a4f..c5ef1d1 100644 --- a/src/enviroment.rs +++ b/src/enviroment.rs @@ -1,4 +1,4 @@ -use std::{collections::HashMap, io::{BufReader, Read, Write}, net::{self, TcpListener, TcpStream}, process, thread::sleep, time::Duration, vec}; +use std::{collections::HashMap, fs, io::{BufReader, Read, Write}, net::{self, TcpListener, TcpStream}, process, thread::sleep, time::{Duration, UNIX_EPOCH}, vec}; use crate::{decompiler::DecompiledOperation, errors::{create_error, print_error, ErrorSubType, ErrorType}, virtualmachine::{Machine, TableValue, VMMemory, VMMemoryBoolean, VMMemoryNativeFunction, VMMemoryNull, VMMemoryNumber, VMMemoryString, VMMemoryTable}}; @@ -739,6 +739,35 @@ fn tabla_kulcsok(machine: &mut Machine, op: &DecompiledOperation, args: Vec) -> VMMemory { + arg_expect(&args, 0, "table", machine, op); + let tbl = match &args[0] { + VMMemory::Table(tbl) => tbl.clone(), + _ => { + error(String::from("Expected a table"), machine, op); + return VMMemory::Null(VMMemoryNull { variable_id: 0 }); + } + }; + let mut vals = VMMemoryTable { + values: vec![], + variable_id: 0, + }; + for kv in &tbl.values { + vals.values.push(TableValue { key: VMMemory::Number(VMMemoryNumber { value: vals.values.len() as f64, variable_id: 0 }), value: kv.value.clone() }); + } + return VMMemory::Table(vals); +} +fn tabla_hossz(machine: &mut Machine, op: &DecompiledOperation, args: Vec) -> VMMemory { + arg_expect(&args, 0, "table", machine, op); + let tbl = match &args[0] { + VMMemory::Table(tbl) => tbl.clone(), + _ => { + error(String::from("Expected a table"), machine, op); + return VMMemory::Null(VMMemoryNull { variable_id: 0 }); + } + }; + return VMMemory::Number(VMMemoryNumber { value: tbl.values.len() as f64, variable_id: 0 }); +} fn szenvedes_vege(machine: &mut Machine, op: &DecompiledOperation, args: Vec) -> VMMemory { arg_expect(&args, 0, "number", machine, op); @@ -752,6 +781,64 @@ fn szenvedes_vege(machine: &mut Machine, op: &DecompiledOperation, args: Vec) -> VMMemory { + arg_expect(&args, 0, "string", machine, op); + let str = match &args[0] { + VMMemory::String(s) => s.value.clone(), + _ => String::new() + }; + let res = match fs::exists(str) { + Ok(exists) => exists, + Err(e) => { + error(format!("Failed to check if file exists: {}", e), machine, op); + false + } + }; + return VMMemory::Boolean(VMMemoryBoolean { value: res, variable_id: 0 }); +} +fn intezo_info(machine: &mut Machine, op: &DecompiledOperation, args: Vec) -> VMMemory { + arg_expect(&args, 0, "string", machine, op); + let str = match &args[0] { + VMMemory::String(s) => s.value.clone(), + _ => String::new() + }; + let res = match fs::metadata(str) { + Ok(exists) => exists, + Err(e) => { + error(format!("Failed to check if file exists: {}", e), machine, op); + panic!() + } + }; + let modf = match res.modified() { + Ok(time) => time.duration_since(UNIX_EPOCH).unwrap().as_millis() as f64, + Err(e) => { + error(format!("Failed to get file modification time: {}", e), machine, op); + 0.0 + } + }; + let creatf = match res.created() { + Ok(time) => time.duration_since(UNIX_EPOCH).unwrap().as_millis() as f64, + Err(e) => { + error(format!("Failed to get file modification time: {}", e), machine, op); + 0.0 + } + }; + let mut to_tbl: HashMap = HashMap::new(); + to_tbl.insert(String::from("mappa-e"), VMMemory::Boolean(VMMemoryBoolean { value: res.is_dir(), variable_id: 0 })); + to_tbl.insert(String::from("fájl-e"), VMMemory::Boolean(VMMemoryBoolean { value: res.is_file(), variable_id: 0 })); + to_tbl.insert(String::from("szerkesztve"), VMMemory::Number(VMMemoryNumber { value: modf, variable_id: 0 })); + to_tbl.insert(String::from("létrehozva"), VMMemory::Number(VMMemoryNumber { value: creatf, variable_id: 0 })); + to_tbl.insert(String::from("hossz"), VMMemory::Number(VMMemoryNumber { value: res.len() as f64, variable_id: 0 })); + let mut res_tbl = VMMemoryTable { + values: vec![], + variable_id: 0, + }; + for (k, v) in to_tbl { + set_mem_tbl_val(&mut res_tbl, VMMemory::String(VMMemoryString { value: k, variable_id: 0 }), v); + } + return VMMemory::Table(res_tbl); +} + pub fn generate() -> HashMap { let mut mem: HashMap = HashMap::new(); @@ -865,6 +952,14 @@ pub fn generate() -> HashMap { TableValue { key: VMMemory::String(VMMemoryString { value: String::from("kulcsok"), variable_id: 0 }), value: VMMemory::NativeFunction(VMMemoryNativeFunction { func: tabla_kulcsok, variable_id: 0 }), + }, + TableValue { + key: VMMemory::String(VMMemoryString { value: String::from("értékek"), variable_id: 0 }), + value: VMMemory::NativeFunction(VMMemoryNativeFunction { func: tabla_ertekek, variable_id: 0 }), + }, + TableValue { + key: VMMemory::String(VMMemoryString { value: String::from("hossz"), variable_id: 0 }), + value: VMMemory::NativeFunction(VMMemoryNativeFunction { func: tabla_hossz, variable_id: 0 }), } ]; mem.insert(String::from("tábla"), VMMemory::Table(VMMemoryTable { values: table, variable_id: 0 })); diff --git a/src/main.rs b/src/main.rs index bf38df7..a127b70 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,7 +10,7 @@ mod virtualmachine; mod errors; mod decompiler; -const CLIVER: [u8; 3] = [0, 2, 0]; +const CLIVER: [u8; 3] = [0, 3, 0]; #[derive(Clone)] struct Context { From 00207f544a39437ae12888045a9ec7d511acf87f Mon Sep 17 00:00:00 2001 From: afonya Date: Wed, 18 Jun 2025 11:30:44 +0200 Subject: [PATCH 04/19] fixed the register allocation issue --- src/compiler.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index 5431925..6e98c67 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -103,6 +103,7 @@ fn allocate_register(registers: &Vec) -> AllocateResult { let mut oldest_register: u8 = 0; let mut oldest_temp: usize = 0; let mut oldest_temp_register: u8 = 0; + let mut tempc = 0; for register in registers { if ((register.last_used < oldest) || (oldest == 0)) && register.id != 0 { oldest = register.last_used; @@ -112,13 +113,16 @@ fn allocate_register(registers: &Vec) -> AllocateResult { oldest_temp = register.last_used; oldest_temp_register = register.id; } + if register.id != 0 && register.variable == 0 { + tempc += 1; + } } - /*if oldest_temp_register != 0 { + if oldest_temp_register != 0 && tempc > 3 { return AllocateResult { register: oldest_temp_register, unbind_before: false, }; - }*/ + } return AllocateResult { register: oldest_register, unbind_before: true, @@ -245,7 +249,6 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec, va 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, ctx, traceback); 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 }); @@ -254,6 +257,7 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec, va set_register(registers, RegisterState { id: arg_reg, used: false, variable: 0, last_used: 0 }); } } + let func = do_ast_op(*call.function, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx, traceback); 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, pos: call.pos as u32 }); From f817a83f1de787b2f65aff5ddfb1ce99374a24d9 Mon Sep 17 00:00:00 2001 From: afonya Date: Wed, 18 Jun 2025 11:47:42 +0200 Subject: [PATCH 05/19] added more enviroment functions, fixed a bug with function calls --- src/enviroment.rs | 168 +++++++++++++++++++++++++++++++++++++++++++++- src/main.rs | 9 +-- src/parser.rs | 2 +- test.asl | 29 +++----- 4 files changed, 182 insertions(+), 26 deletions(-) diff --git a/src/enviroment.rs b/src/enviroment.rs index c5ef1d1..0f00927 100644 --- a/src/enviroment.rs +++ b/src/enviroment.rs @@ -1,4 +1,4 @@ -use std::{collections::HashMap, fs, io::{BufReader, Read, Write}, net::{self, TcpListener, TcpStream}, process, thread::sleep, time::{Duration, UNIX_EPOCH}, vec}; +use std::{collections::HashMap, fs, io::{stdin, BufReader, Read, Write}, net::{self, TcpListener, TcpStream}, process, thread::sleep, time::{Duration, UNIX_EPOCH}, vec}; use crate::{decompiler::DecompiledOperation, errors::{create_error, print_error, ErrorSubType, ErrorType}, virtualmachine::{Machine, TableValue, VMMemory, VMMemoryBoolean, VMMemoryNativeFunction, VMMemoryNull, VMMemoryNumber, VMMemoryString, VMMemoryTable}}; @@ -204,6 +204,27 @@ fn bimbabemb(machine: &mut Machine, op: &DecompiledOperation, args: Vec) -> VMMemory { + let now = match UNIX_EPOCH.elapsed() { + Ok(duration) => duration.as_millis() as f64, + Err(e) => { + error(format!("Failed to get elapsed time: {}", e), machine, op); + 0.0 + } + }; + return VMMemory::Number(VMMemoryNumber { value: now, variable_id: 0 }); +} +fn joink(machine: &mut Machine, op: &DecompiledOperation, _args: Vec) -> VMMemory { + let mut str = String::new(); + match stdin().read_line(&mut str) { + Err(e) => { + error(format!("Failed to read from stdin: {}", e), machine, op); + return VMMemory::Null(VMMemoryNull { variable_id: 0 }); + }, + _ => {} + }; + return VMMemory::String(VMMemoryString { value: str, variable_id: 0 }); +} fn nerd_abs(machine: &mut Machine, op: &DecompiledOperation, args: Vec) -> VMMemory { arg_expect(&args, 0, "number", machine, op); @@ -805,8 +826,8 @@ fn intezo_info(machine: &mut Machine, op: &DecompiledOperation, args: Vec exists, Err(e) => { - error(format!("Failed to check if file exists: {}", e), machine, op); - panic!() + error(format!("Failed to get file metadata: {}", e), machine, op); + return VMMemory::Null(VMMemoryNull { variable_id: 0 }); } }; let modf = match res.modified() { @@ -838,6 +859,113 @@ fn intezo_info(machine: &mut Machine, op: &DecompiledOperation, args: Vec) -> VMMemory { + arg_expect(&args, 0, "string", machine, op); + let str = match &args[0] { + VMMemory::String(s) => s.value.clone(), + _ => String::new() + }; + match fs::create_dir_all(str) { + Err(e) => { + error(format!("Failed to create directory: {}", e), machine, op); + }, + _ => {} + } + return VMMemory::Null(VMMemoryNull { variable_id: 0 }); +} +fn intezo_mappattorol(machine: &mut Machine, op: &DecompiledOperation, args: Vec) -> VMMemory { + arg_expect(&args, 0, "string", machine, op); + let str = match &args[0] { + VMMemory::String(s) => s.value.clone(), + _ => String::new() + }; + let res = match fs::exists(&str) { + Ok(exists) => exists, + Err(_) => { + error(format!("Folder does not exist"), machine, op); + return VMMemory::Null(VMMemoryNull { variable_id: 0 }); + } + }; + if !res { + error(format!("Folder does not exist"), machine, op); + } + match fs::remove_dir_all(&str) { + Err(e) => { + error(format!("Failed to remove directory: {}", e), machine, op); + }, + _ => {} + }; + return VMMemory::Null(VMMemoryNull { variable_id: 0 }); +} +fn intezo_fajlttorol(machine: &mut Machine, op: &DecompiledOperation, args: Vec) -> VMMemory { + arg_expect(&args, 0, "string", machine, op); + let str = match &args[0] { + VMMemory::String(s) => s.value.clone(), + _ => String::new() + }; + let res = match fs::exists(&str) { + Ok(exists) => exists, + Err(_) => { + error(format!("File does not exist"), machine, op); + return VMMemory::Null(VMMemoryNull { variable_id: 0 }); + } + }; + if !res { + error(format!("File does not exist"), machine, op); + } + match fs::remove_file(&str) { + Err(e) => { + error(format!("Failed to remove file: {}", e), machine, op); + }, + _ => {} + }; + return VMMemory::Null(VMMemoryNull { variable_id: 0 }); +} +fn intezo_olvass(machine: &mut Machine, op: &DecompiledOperation, args: Vec) -> VMMemory { + arg_expect(&args, 0, "string", machine, op); + let str = match &args[0] { + VMMemory::String(s) => s.value.clone(), + _ => String::new() + }; + let res = match fs::exists(&str) { + Ok(exists) => exists, + Err(_) => { + error(format!("File does not exist"), machine, op); + return VMMemory::Null(VMMemoryNull { variable_id: 0 }); + } + }; + if !res { + error(format!("File does not exist"), machine, op); + } + let data = match fs::read_to_string(&str) { + Ok(data) => data, + Err(e) => { + error(format!("Failed to read file: {}", e), machine, op); + return VMMemory::Null(VMMemoryNull { variable_id: 0 }); + } + }; + return VMMemory::String(VMMemoryString { value: data, variable_id: 0 }); +} +fn intezo_irj(machine: &mut Machine, op: &DecompiledOperation, args: Vec) -> VMMemory { + arg_expect(&args, 0, "string", machine, op); + arg_expect(&args, 1, "string", machine, op); + let str = match &args[0] { + VMMemory::String(s) => s.value.clone(), + _ => String::new() + }; + let str2 = match &args[1] { + VMMemory::String(s) => s.value.clone(), + _ => String::new() + }; + match fs::write(&str, str2) { + Err(e) => { + error(format!("Failed to write file: {}", e), machine, op); + return VMMemory::Null(VMMemoryNull { variable_id: 0 }); + }, + _ => {} + }; + return VMMemory::Null(VMMemoryNull { variable_id: 0 }); +} pub fn generate() -> HashMap { let mut mem: HashMap = HashMap::new(); @@ -847,6 +975,8 @@ pub fn generate() -> HashMap { 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 })); mem.insert(String::from("bimbabemb"), VMMemory::NativeFunction(VMMemoryNativeFunction { func: bimbabemb, variable_id: 0 })); + mem.insert(String::from("mennyi az idő"), VMMemory::NativeFunction(VMMemoryNativeFunction { func: mennyiazido, variable_id: 0 })); + mem.insert(String::from("joink"), VMMemory::NativeFunction(VMMemoryNativeFunction { func: joink, variable_id: 0 })); let nerd: Vec = vec![ TableValue { @@ -972,5 +1102,37 @@ pub fn generate() -> HashMap { ]; mem.insert(String::from("szenvedés"), VMMemory::Table(VMMemoryTable { values: szenvedes, variable_id: 0 })); + let intezo: Vec = vec![ + TableValue { + key: VMMemory::String(VMMemoryString { value: String::from("létezik"), variable_id: 0 }), + value: VMMemory::NativeFunction(VMMemoryNativeFunction { func: intezo_letezik, variable_id: 0 }), + }, + TableValue { + key: VMMemory::String(VMMemoryString { value: String::from("infó"), variable_id: 0 }), + value: VMMemory::NativeFunction(VMMemoryNativeFunction { func: intezo_info, variable_id: 0 }), + }, + TableValue { + key: VMMemory::String(VMMemoryString { value: String::from("mappít"), variable_id: 0 }), + value: VMMemory::NativeFunction(VMMemoryNativeFunction { func: intezo_mappit, variable_id: 0 }), + }, + TableValue { + key: VMMemory::String(VMMemoryString { value: String::from("mappát töröl"), variable_id: 0 }), + value: VMMemory::NativeFunction(VMMemoryNativeFunction { func: intezo_mappattorol, variable_id: 0 }), + }, + TableValue { + key: VMMemory::String(VMMemoryString { value: String::from("fájlt töröl"), variable_id: 0 }), + value: VMMemory::NativeFunction(VMMemoryNativeFunction { func: intezo_fajlttorol, variable_id: 0 }), + }, + TableValue { + key: VMMemory::String(VMMemoryString { value: String::from("olvass"), variable_id: 0 }), + value: VMMemory::NativeFunction(VMMemoryNativeFunction { func: intezo_olvass, variable_id: 0 }), + }, + TableValue { + key: VMMemory::String(VMMemoryString { value: String::from("írj"), variable_id: 0 }), + value: VMMemory::NativeFunction(VMMemoryNativeFunction { func: intezo_irj, variable_id: 0 }), + }, + ]; + mem.insert(String::from("intéző"), VMMemory::Table(VMMemoryTable { values: intezo, variable_id: 0 })); + return mem; } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index a127b70..1a24992 100644 --- a/src/main.rs +++ b/src/main.rs @@ -195,13 +195,14 @@ fn main() { let mut longest = 0; for op in &func.body { let op_name = operation_to_name(op.opcode); - let str = format!(" {}{} {}{} {}{} {} at {}", + let str = format!(" {}{} {}{} {}{} {}{} at {}", + " ".repeat(longest_cols[0] - op_name.len()), op_name, - " ".repeat(longest_cols[0] - op_name.len()), - op.arg1, " ".repeat(longest_cols[1] - op.arg1.to_string().len()), - op.arg2, + op.arg1, " ".repeat(longest_cols[2] - op.arg2.to_string().len()), + op.arg2, + " ".repeat(longest_cols[3] - op.arg3.to_string().len()), op.arg3, op.pos); longest = longest.max(str.len()+4); diff --git a/src/parser.rs b/src/parser.rs index 929ee50..3ec85e0 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -213,7 +213,7 @@ fn shunt(input: Vec, ctx: &Context) -> ASTPart { output.push(part); }, ASTPart::Call(_) => { - stack.push(part); + output.push(part); }, ASTPart::VarRead(_) => { output.push(part); diff --git a/test.asl b/test.asl index 005e58d..de2e50f 100644 --- a/test.asl +++ b/test.asl @@ -1,18 +1,11 @@ -gethelj a = 125 -gethelj b = 567 -gethelj c = 8765 -gethelj d = 123 -gethelj e = 123 -gethelj f = 123 -gethelj g = 123 -gethelj h = 123 -gethelj i = 123 -gethelj j = 123 -gethelj k = 123 -gethelj l = 123 -gethelj m = 123 -gethelj n = 123 -gethelj o = 123 -gethelj p = 123 -gethelj q = 123 -ugass(a+b+c) \ No newline at end of file +gethelj time = mennyi az idő() +ugass(time) +gethelj bemenet = joink() +ugass(bemenet) +gethelj time2 = mennyi az idő() +gethelj msg = szaft"Took: "szaft+bimbabemb(time2-time, szaft"string"szaft)+szaft"ms"szaft +ugass(msg) + +ugass(intéző.infó(szaft"test.asl"szaft)) +ugass(intéző.olvass(szaft"test.asl"szaft)) +ugass(intéző.írj(szaft"bimbabemb.txt"szaft,szaft"óóóóó bimbabemb!"szaft)) \ No newline at end of file From 8dee35c68f2b6613f6f285c682d6c714d7ec570f Mon Sep 17 00:00:00 2001 From: afonya Date: Wed, 18 Jun 2025 12:19:34 +0200 Subject: [PATCH 06/19] update the docs and the extension --- docs/docs/enviroment.md | 34 +++++++++++++++++++++++++++-- extension/astrolang.tmLanguage.json | 2 +- extension/index.js | 13 ++++++++++- extension/package.json | 7 ++++++ src/enviroment.rs | 2 +- 5 files changed, 53 insertions(+), 5 deletions(-) diff --git a/docs/docs/enviroment.md b/docs/docs/enviroment.md index 8a5fbda..fc4860d 100644 --- a/docs/docs/enviroment.md +++ b/docs/docs/enviroment.md @@ -15,6 +15,8 @@ description: Az Astro Lang környezete |csömör|Hibával befejezi a programot.|`csömör(error: string)`|`csömör(szaft"Sikertelen: Sikeresen befejezve!"szaft)`| |tarh|Kíírja, hogy a megadott érték milyen típusú.|`tarh(object: any): string`|`tarh(82)`| |bimbabemb|Átalakítja a megadott érétk típusát, ha lehetséges.|`bimbabemb(object: any, target: string): any`|`bimbabemb(7,szaft"string"szaft)`| +|mennyi az idő|Visszaadja a pillanatnyi UNIX időt milisec-ben.|`mennyi az idő(): number`|`mennyi az idő()`| +|joink|Bekér egy szöveget a terminálból.|`joink(): string`|`joink()`| --- @@ -65,7 +67,7 @@ Példa: `szaft.csemerd fel` --- -## Tábla (Tábla) +## Tábla (Table) Táblákkal lévő funkciók :::tip @@ -134,4 +136,32 @@ Ezek a funkciók kérik, hogy az első értékük a szülő táblájuk legyen |---|---|---|---| |olvass|Beleolvas a kapcsolatba.|`olvass(stream: kapcsolat, len: number): string`|`olvass(stream, 1024)`| |írj|Beleír a kapcsolatba.|`írj(stream: kapcsolat, data: string)`|`írj(stream, szaft"Hello from ASL!"szaft)`| -|zár|Bezárja a kapcsolatot.|`zár(stream: kapcsolat)`|`zár(stream)`| \ No newline at end of file +|zár|Bezárja a kapcsolatot.|`zár(stream: kapcsolat)`|`zár(stream)`| + +--- + +## Intéző (Filesystem) +Fájlokkal lévő funkciók +:::tip + +A példák elé kell írni a kulcsszót: `intéző` + +Példa: `intéző.létezik` + +::: +:::warning + +A fájlok, helyét bárhogy megadhatod, viszont a törlésnél légy óvatos! + +A fájl írása felülírja a már fájlban lévő adatokat! + +::: +|Név|Leírás|Használat|Példa| +|---|---|---|---| +|létezik|Megnézi, hogy létezik-e az elérési út.|`létezik(path: string): boolean`|`létezik(szaft"test.asl"szaft)`| +|infó|Lekéri a metaadatokat az adott elérési útból.|`infó(path: string): table`|`infó(szaft"test.asl"szaft)`| +|mappít|Létrehozza a mappákat, hogy elérje az elérési útat.|`mappít(path: string)`|`mappít(szaft"test1/test2/"szaft)`| +|mappát töröl|Kitöröl egy mappát.|`mappát töröl(path: string)`|`mappát töröl(szaft"test1/"szaft)`| +|fájlt töröl|Kitöröl egy fájlt.|`fájlt töröl(path: string)`|`fájlt töröl(szaft"compiled.asx"szaft)`| +|olvass|Beolvas egy fájlt.|`olvass(path: string): string`|`olvass(szaft"test.asl"szaft)`| +|írj|Beleírja egy fájlba a kapott adatokat.|`írj(path: string, data: string)`|`írj(szaft"test.txt"szaft, szaft"Hello from ASL!"szaft)`| \ No newline at end of file diff --git a/extension/astrolang.tmLanguage.json b/extension/astrolang.tmLanguage.json index 5244766..4036bb6 100644 --- a/extension/astrolang.tmLanguage.json +++ b/extension/astrolang.tmLanguage.json @@ -25,7 +25,7 @@ }, { "name": "variable.astrolang", - "match": "\\b([a-zA-Z_][a-zA-Z0-9_]*)\\b" + "match": "\\b([a-zA-Zöüóőúéáűí_][a-zA-Zöüóőúéáűí0-9_]*)\\b" }, { "name": "constant.numeric.astrolang", diff --git a/extension/index.js b/extension/index.js index 7d50f2c..9f69f5b 100644 --- a/extension/index.js +++ b/extension/index.js @@ -33,6 +33,9 @@ vscode.languages.registerCompletionItemProvider('astrolang', { "tábla", "kábel", "szenvedés", + "mennyi az idő", + "joink", + "intéző", "abs", "kerek", @@ -65,7 +68,15 @@ vscode.languages.registerCompletionItemProvider('astrolang', { "kérés", "írj", "olvass", - "zár" + "zár", + + "létezik", + "infó", + "mappít", + "mappát töröl", + "fájlt töröl", + "olvass", + "írj" ] let out = [] for (let i = 0; i < words.length; i++) { diff --git a/extension/package.json b/extension/package.json index 5617a1a..4573a41 100644 --- a/extension/package.json +++ b/extension/package.json @@ -6,9 +6,16 @@ "author": "Afonya", "type": "module", "main": "index.js", + "repository": { + "type": "git", + "url": "https://git.afonyanet.hu/afonya/AstroLang" + }, "engines": { "vscode": "^1.22.0" }, + "activationEvents": [ + "onStartupFinished" + ], "contributes": { "languages": [ { diff --git a/src/enviroment.rs b/src/enviroment.rs index 0f00927..a64dbf4 100644 --- a/src/enviroment.rs +++ b/src/enviroment.rs @@ -889,7 +889,7 @@ fn intezo_mappattorol(machine: &mut Machine, op: &DecompiledOperation, args: Vec if !res { error(format!("Folder does not exist"), machine, op); } - match fs::remove_dir_all(&str) { + match fs::remove_dir(&str) { Err(e) => { error(format!("Failed to remove directory: {}", e), machine, op); }, From 1a98959be01aca27807beefe7f38d0ddff817f61 Mon Sep 17 00:00:00 2001 From: afonya Date: Wed, 18 Jun 2025 12:56:54 +0200 Subject: [PATCH 07/19] begin adding try/catch --- docs/docs/asx.md | 2 ++ src/compiler.rs | 41 ++++++++++++++++++++++++++++++++++++----- src/decompiler.rs | 6 +++++- src/main.rs | 1 + src/parser.rs | 33 +++++++++++++++++++++++++++++++++ test.asl | 16 +++++----------- 6 files changed, 82 insertions(+), 17 deletions(-) diff --git a/docs/docs/asx.md b/docs/docs/asx.md index 04263d8..7062399 100644 --- a/docs/docs/asx.md +++ b/docs/docs/asx.md @@ -36,6 +36,8 @@ Ezt megtudod nézni a `ASL viewx ` parancs használatával. |Szövegek|Lásd: [Szövegek](#szövegek)|| |Funkciók száma|Elmondja, hogy a funkcióban mennyi funkció meghívás van.|4 bytes| |Funkciók|Lásd: [Funkció meghívások](#funkció-meghívások)|| +|Catch pos|Megmutatja a catch funkció helyzetét, csak try-ban. Normál funkciók esetén 0|4 bytes| +|Instrukciók száma|Elmondja, hogy a funkcióban mennyi instrukció van.|4 bytes| |Instukciók|Lásd: [Instrukciók](#instrukciók)|| ## Változók: diff --git a/src/compiler.rs b/src/compiler.rs index 6e98c67..33351e2 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -31,7 +31,8 @@ struct Compiled { operations: Vec, variables: Vec, strings: HashMap, - functions: HashMap + functions: HashMap, + try_catch: Option } #[derive(Debug, Clone)] @@ -238,7 +239,7 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec, va variables: variables.clone(), previous: Some(Box::new(traceback.clone())), }; - functions.insert(func_id, compile_function(func.body, Some(func.args), registers, next_var_id, ctx, &self_tb)); + functions.insert(func_id, compile_function(func.body, Some(func.args), registers, next_var_id, ctx, &self_tb, None)); *next_function_id += 1; let reg = allocate_register(registers); if reg.unbind_before { @@ -658,7 +659,7 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec, va }; let lexed = lex(data, &imp_ctx); let ast = parse(lexed, &imp_ctx); - let compiled = compile_function(ast, None, registers, next_var_id, &imp_ctx, &self_tb); + let compiled = compile_function(ast, None, registers, next_var_id, &imp_ctx, &self_tb, None); functions.insert(*next_function_id, compiled); *next_function_id += 1; let reg = allocate_register(registers); @@ -677,12 +678,33 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec, va } } }, + ASTPart::TryCatch(tc) => { + let catch_f = compile_function(tc.catch_block.body, None, registers, next_var_id, ctx, traceback, None); + let mut try_f = compile_function(tc.try_block.body, None, registers, next_var_id, ctx, traceback, Some(0)); + let mut nextt_f = 1; + for (fid, _) in &try_f.functions { + if fid >= &nextt_f { + nextt_f = fid+1; + } + } + try_f.functions.insert(nextt_f, catch_f); + try_f.try_catch = Some(nextt_f); + functions.insert(*next_function_id, try_f); + *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, pos: tc.pos as u32 }); + } + ops.push(Operation { opcode: 5, arg1: Some(reg.register), arg2: Some((*next_function_id-1) as f64), arg3: None, pos: tc.pos as u32 }); + ops.push(Operation { opcode: 27, arg1: Some(reg.register), arg2: None, arg3: None, pos: tc.pos as u32 }); + set_register(registers, RegisterState { id: reg.register, used: true, variable: 0, last_used: *op_count }); + }, _ => {} } return 0; } -fn compile_function(ast: Vec, args: Option>, registers: &mut Vec, next_var_id: &mut u32, ctx: &Context, traceback: &PrevFunc) -> Compiled { +fn compile_function(ast: Vec, args: Option>, registers: &mut Vec, next_var_id: &mut u32, ctx: &Context, traceback: &PrevFunc, try_catch: Option) -> Compiled { let mut ops: Vec = vec![]; let mut variables: Vec = vec![]; @@ -727,6 +749,7 @@ fn compile_function(ast: Vec, args: Option>, registers: &mu variables, strings, functions, + try_catch }; } @@ -805,6 +828,14 @@ fn compile_body(compiled: Compiled, fpos: &mut usize, ctx: &Context) -> (Vec contexts.extend_from_slice(&context); additional.push(compiled); } + match compiled.try_catch { + Some(tc) => { + append_be_num(&mut output, 4, tc as usize); + }, + None => { + append_be_num(&mut output, 4, 0); + } + } //function body append_be_num(&mut output, 4, compiled.operations.len()); for ops in compiled.operations { @@ -851,7 +882,7 @@ pub fn compile(ast: Vec, ctx: &Context) -> (Vec, Vec) { variables: vec![], previous: None, }; - let compiled = compile_function(ast, None, &mut registers, &mut next_var_id, ctx, &empty_tb); + let compiled = compile_function(ast, None, &mut registers, &mut next_var_id, ctx, &empty_tb, None); let mut output: Vec = vec![]; //doctype specifier diff --git a/src/decompiler.rs b/src/decompiler.rs index ae39057..f572519 100644 --- a/src/decompiler.rs +++ b/src/decompiler.rs @@ -7,7 +7,8 @@ pub struct DecompiledFunction { pub body: Vec, pub variables: Vec, pub strings: HashMap, - pub functions: HashMap + pub functions: HashMap, + pub try_catch: u32, } #[derive(Debug, Clone)] pub struct DecompiledOperation { @@ -145,6 +146,8 @@ fn load_func(data: Vec, offset: &mut usize) -> DecompiledFunction { *offset += 4; functions.insert(func_id, func_pos); } + let try_catch = read_be_num(&data[*offset..*offset + 4]); + *offset += 4; let mut body: Vec = Vec::new(); let instr_len: usize = read_be_num(&data[*offset..*offset + 4]); *offset += 4; @@ -170,6 +173,7 @@ fn load_func(data: Vec, offset: &mut usize) -> DecompiledFunction { variables: variables, strings: strings, functions: functions, + try_catch: try_catch as u32, }; } diff --git a/src/main.rs b/src/main.rs index 1a24992..892827c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -183,6 +183,7 @@ fn main() { for (id, pos) in &func.functions { println!(" {}: {}", id, pos); } + println!(" Try/Catch: {}", func.try_catch); println!(" Body:"); //Print these under each other like when you tabulate let mut longest_cols: Vec = vec![0, 0, 0, 0]; diff --git a/src/parser.rs b/src/parser.rs index 3ec85e0..c5d8687 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -26,6 +26,7 @@ pub enum ASTPart { TableGet(AstTableGet), TableSet(AstTableSet), Import(AstImport), + TryCatch(AstTryCatch), NOOP } #[derive(Debug, Clone, PartialEq)] @@ -156,6 +157,12 @@ pub struct AstImport { pub path: String, pub pos: usize } +#[derive(Debug, Clone, PartialEq)] +pub struct AstTryCatch { + pub try_block: AstFunction, + pub catch_block: AstFunction, + pub pos: usize +} fn is_end(input: &Token, end: &Vec) -> bool { for token in end { @@ -857,6 +864,32 @@ fn next_operation(pos: &mut usize, input: &Vec, op_ends: &Vec, par let func = read_function(input, pos, true, ctx); return check_continue(pos, input, func, op_ends, parse_ends, ctx); } + } else if token.value == "piszolj" { + let func = read_function(input, pos, false, ctx); + let tryp = match func { + ASTPart::Function(f) => f, + _ => { + let err = create_error(&format!("Expected function body"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected); + print_error(&err, &ctx); + process::exit(1); + } + }; + if input[*pos].typ != TokenType::KEYWORD || input[*pos].value != "csecs" { + let err = create_error(&format!("Expected `csecs` after piszolj"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::Expected); + print_error(&err, &ctx); + process::exit(1); + } + *pos += 1; + let func2 = read_function(input, pos, true, ctx); + let catchp = match func2 { + ASTPart::Function(f) => f, + _ => { + let err = create_error(&format!("Expected function body"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::Expected); + print_error(&err, &ctx); + process::exit(1); + } + }; + return ASTPart::TryCatch(AstTryCatch { try_block: tryp, catch_block: catchp, pos: token.pos }); } else { let err = create_error(&format!("Unexpected `{:?}({})`", token.typ, token.value), token.pos, ErrorType::SyntaxError, ErrorSubType::Unexpected); print_error(&err, &ctx); diff --git a/test.asl b/test.asl index de2e50f..60adf39 100644 --- a/test.asl +++ b/test.asl @@ -1,11 +1,5 @@ -gethelj time = mennyi az idő() -ugass(time) -gethelj bemenet = joink() -ugass(bemenet) -gethelj time2 = mennyi az idő() -gethelj msg = szaft"Took: "szaft+bimbabemb(time2-time, szaft"string"szaft)+szaft"ms"szaft -ugass(msg) - -ugass(intéző.infó(szaft"test.asl"szaft)) -ugass(intéző.olvass(szaft"test.asl"szaft)) -ugass(intéző.írj(szaft"bimbabemb.txt"szaft,szaft"óóóóó bimbabemb!"szaft)) \ No newline at end of file +piszolj { + gethelj test = szaft"a"szaft+1 +} csecs(err) { + ugass(szaft"Hibás bemb"szaft) +} \ No newline at end of file From 3dd28cedd3dad0292d92ef6c28af4f9640ae0864 Mon Sep 17 00:00:00 2001 From: afonya Date: Wed, 18 Jun 2025 13:14:58 +0200 Subject: [PATCH 08/19] prepare the error system for try/catch --- src/compiler.rs | 18 +++---- src/enviroment.rs | 2 +- src/errors.rs | 9 ++-- src/lexer.rs | 4 +- src/main.rs | 6 +-- src/parser.rs | 112 ++++++++++++++++++++--------------------- src/virtualmachine.rs | 113 ++++++++++++++++++++++++++---------------- 7 files changed, 146 insertions(+), 118 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index 33351e2..a0b3b02 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -309,7 +309,7 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec, va }, ASTPart::Else(else_part) => { if get_variable_by_name(variables, "__LASTIF", ops.len(), traceback).is_none() { - let err = create_error(&format!("Else used without an if statement before it"), else_part.pos, ErrorType::SemanticError, ErrorSubType::ElseWithoutIf); + let err = create_error(&format!("Else used without an if statement before it"), else_part.pos, ErrorType::SemanticError, ErrorSubType::ElseWithoutIf, ctx); print_error(&err, &ctx); process::exit(1); } @@ -357,7 +357,7 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec, va }, ASTPart::ElseIf(elseif_part) => { if get_variable_by_name(variables, "__LASTIF", ops.len(), traceback).is_none() { - let err = create_error(&format!("Else if used without an if statement before it"), elseif_part.pos, ErrorType::SemanticError, ErrorSubType::ElseWithoutIf); + let err = create_error(&format!("Else if used without an if statement before it"), elseif_part.pos, ErrorType::SemanticError, ErrorSubType::ElseWithoutIf, ctx); print_error(&err, &ctx); process::exit(1); } @@ -471,12 +471,12 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec, va } }, ASTPart::Break(brk) => { - let err = create_error(&format!("Unexpected break outside of loop"), brk.pos, ErrorType::SemanticError, ErrorSubType::BreakContinueWithoutLoop); + let err = create_error(&format!("Unexpected break outside of loop"), brk.pos, ErrorType::SemanticError, ErrorSubType::BreakContinueWithoutLoop, ctx); print_error(&err, &ctx); process::exit(1); }, ASTPart::Continue(cont) => { - let err = create_error(&format!("Unexpected continue outside of loop"), cont.pos, ErrorType::SemanticError, ErrorSubType::BreakContinueWithoutLoop); + let err = create_error(&format!("Unexpected continue outside of loop"), cont.pos, ErrorType::SemanticError, ErrorSubType::BreakContinueWithoutLoop, ctx); print_error(&err, &ctx); process::exit(1); }, @@ -574,7 +574,7 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec, va return reg.register; }, _ => { - let err = create_error(&format!("Unknown operator `{}`", op.operator), op.pos, ErrorType::SyntaxError, ErrorSubType::UnknownOperation); + let err = create_error(&format!("Unknown operator `{}`", op.operator), op.pos, ErrorType::SyntaxError, ErrorSubType::UnknownOperation, ctx); print_error(&err, &ctx); process::exit(1); }, @@ -585,7 +585,7 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec, va }, ASTPart::VarUpdate(upd) => { if get_variable_by_name(variables, &upd.variable, ops.len(), traceback).is_none() { - let err = create_error(&format!("Variable `{}` does not exist", upd.variable), upd.pos, ErrorType::SemanticError, ErrorSubType::VariableNotFound); + let err = create_error(&format!("Variable `{}` does not exist", upd.variable), upd.pos, ErrorType::SemanticError, ErrorSubType::VariableNotFound, ctx); print_error(&err, &ctx); process::exit(1); } @@ -601,7 +601,7 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec, va }, ASTPart::Assigment(asign) => { if get_variable_by_name(variables, &asign.variable, ops.len(), traceback).is_some() { - let err = create_error(&format!("Variable `{}` already exists", asign.variable), asign.pos, ErrorType::SemanticError, ErrorSubType::VariableAlreadyExists); + let err = create_error(&format!("Variable `{}` already exists", asign.variable), asign.pos, ErrorType::SemanticError, ErrorSubType::VariableAlreadyExists, ctx); print_error(&err, &ctx); process::exit(1); } @@ -672,7 +672,7 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec, va return reg.register; }, Err(e) => { - let err = create_error(&format!("Failed to read file `{}`: {}", impr.path, e), impr.pos, ErrorType::IOError, ErrorSubType::FileError); + let err = create_error(&format!("Failed to read file `{}`: {}", impr.path, e), impr.pos, ErrorType::IOError, ErrorSubType::FileError, ctx); print_error(&err, &ctx); process::exit(1); } @@ -722,7 +722,7 @@ fn compile_function(ast: Vec, args: Option>, registers: &mu Some(arg_list) => { for arg in arg_list { if get_variable_by_name(&variables, &arg, 0, &empty_tb).is_some() { - let err = create_error(&format!("Argument `{}` already exists", arg), 0, ErrorType::SemanticError, ErrorSubType::ArgumentDuplication); + let err = create_error(&format!("Argument `{}` already exists", arg), 0, ErrorType::SemanticError, ErrorSubType::ArgumentDuplication, ctx); print_error(&err, &ctx); process::exit(1); } diff --git a/src/enviroment.rs b/src/enviroment.rs index a64dbf4..57a2488 100644 --- a/src/enviroment.rs +++ b/src/enviroment.rs @@ -58,9 +58,9 @@ fn arg_expect(args: &Vec, pos: usize, expected_type: &str, machine: &M } } 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; + let err = create_error(&msg, op.pos, ErrorType::MachineError, ErrorSubType::RuntimeError, &machine.ctx[func]); print_error(&err, &machine.ctx[func]); process::exit(1); } diff --git a/src/errors.rs b/src/errors.rs index ad9a024..c77071c 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -1,5 +1,6 @@ use crate::Context; +#[derive(Debug, Clone)] pub enum ErrorType { SyntaxError, SemanticError, @@ -9,6 +10,7 @@ pub enum ErrorType { IOError, } +#[derive(Debug, Clone)] pub enum ErrorSubType { //Syntax errors UnexpectedEnd, @@ -43,6 +45,7 @@ pub enum ErrorSubType { FileError } +#[derive(Debug, Clone)] pub struct ASLError { pub message: String, pub position: usize, @@ -171,9 +174,11 @@ pub fn reverse_subtype_short(str: String) -> ErrorSubType { } } -pub fn create_error(message: &str, position: usize, typ: ErrorType, stype: ErrorSubType) -> ASLError { +pub fn create_error(message: &str, position: usize, typ: ErrorType, stype: ErrorSubType, ctx: &Context) -> ASLError { let mut code = convert_types_to_short(&typ); code.push_str(&convert_subtypes_to_short(&stype)); + code.push_str(ctx.c_funcid.to_string().as_str()); + code.push(':'); code.push_str(&position.to_string()); ASLError { message: String::from(message), @@ -276,7 +281,5 @@ pub fn print_error(error: &ASLError, ctx: &Context) { out.push_str("\n"); out.push_str("Error Code: "); out.push_str(&error.code); - out.push_str(":"); - out.push_str(&ctx.c_funcid.to_string()); println!("{}", out); } \ No newline at end of file diff --git a/src/lexer.rs b/src/lexer.rs index 7494f78..5fbd48e 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -70,7 +70,7 @@ fn read_string(splitted: &Vec<&str>, pos: &mut usize, out: &mut Vec, ctx: str += nchar; } if !success { - let err = create_error("Unexpected end of string", *pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd); + let err = create_error("Unexpected end of string", *pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd, ctx); print_error(&err, &ctx); process::exit(1); } @@ -94,7 +94,7 @@ fn read_comment(splitted: &Vec<&str>, pos: &mut usize, is_multiline: bool, ctx: str += nchar; } if !success { - let err = create_error("Unexpected end of comment", *pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd); + let err = create_error("Unexpected end of comment", *pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd, ctx); print_error(&err, &ctx); process::exit(1); } diff --git a/src/main.rs b/src/main.rs index 892827c..7ead5cd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -59,7 +59,7 @@ fn main() { println!("Build successful. Took: {}ms", ntime.as_millis()); let mut vm = Machine::new(contexts); vm.load(&compiled); - vm.run(); + vm.resume(); }, Result::Err(err) => { panic!("Can't read file: {}", err); @@ -76,7 +76,7 @@ fn main() { } let mut vm = Machine::new(contexts); vm.load(&data); - vm.run(); + vm.resume(); }, Result::Err(err) => { panic!("Can't read file: {}", err); @@ -147,8 +147,8 @@ fn main() { println!("Error code {} is invalid for this file.", args[3]); return; } - let error = create_error("", errcode_data[2].parse().unwrap(), reverse_type_short(errcode_data[0].to_string()), reverse_subtype_short(errcode_data[1].to_string())); let func_ctx = contexts[errcode_data[3].parse::().unwrap()].clone(); + let error = create_error("", errcode_data[3].parse().unwrap(), reverse_type_short(errcode_data[0].to_string()), reverse_subtype_short(errcode_data[1].to_string()), &func_ctx); print_error(&error, &func_ctx); return; }, diff --git a/src/parser.rs b/src/parser.rs index c5d8687..e312670 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -277,7 +277,7 @@ fn shunt(input: Vec, ctx: &Context) -> ASTPart { if op.operator == "!" { println!("{:?}", output); if i < 1 { - let err = create_error(&format!("Unexpected operation `{}`", op.operator), op.pos, ErrorType::SemanticError, ErrorSubType::UnexpectedOperation); + let err = create_error(&format!("Unexpected operation `{}`", op.operator), op.pos, ErrorType::SemanticError, ErrorSubType::UnexpectedOperation, ctx); print_error(&err, &ctx); process::exit(1); } @@ -291,7 +291,7 @@ fn shunt(input: Vec, ctx: &Context) -> ASTPart { output.remove(i-1); } else { if i < 2 { - let err = create_error(&format!("Unexpected operation `{}`", op.operator), op.pos, ErrorType::SemanticError, ErrorSubType::UnexpectedOperation); + let err = create_error(&format!("Unexpected operation `{}`", op.operator), op.pos, ErrorType::SemanticError, ErrorSubType::UnexpectedOperation, ctx); print_error(&err, &ctx); process::exit(1); } @@ -314,7 +314,7 @@ fn shunt(input: Vec, ctx: &Context) -> ASTPart { } } if output.len() == 0 { - let err = create_error(&format!("No expressions found after applying order of operations"), 0, ErrorType::SemanticError, ErrorSubType::NoExpression); + let err = create_error(&format!("No expressions found after applying order of operations"), 0, ErrorType::SemanticError, ErrorSubType::NoExpression, ctx); print_error(&err, &ctx); process::exit(1); } @@ -325,7 +325,7 @@ fn read_function(input: &Vec, pos: &mut usize, with_args: bool, ctx: &Con let start_pos = input[*pos].pos; if with_args { if input[*pos].typ != TokenType::SEPARATOR || input[*pos].value != "(" { - let err = create_error(&format!("Expected `(`"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::Expected); + let err = create_error(&format!("Expected `(`"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::Expected, ctx); print_error(&err, &ctx); process::exit(1); } @@ -342,20 +342,20 @@ fn read_function(input: &Vec, pos: &mut usize, with_args: bool, ctx: &Con if token.typ == TokenType::IDENTIFIER { args.push(token.value.clone()); } else { - let err = create_error(&format!("Unexpected `{:?}({})`", token.typ, token.value), token.pos, ErrorType::SyntaxError, ErrorSubType::Unexpected); + let err = create_error(&format!("Unexpected `{:?}({})`", token.typ, token.value), token.pos, ErrorType::SyntaxError, ErrorSubType::Unexpected, ctx); print_error(&err, &ctx); process::exit(1); } } if input[*pos].typ != TokenType::SEPARATOR || input[*pos].value != ")" { - let err = create_error(&format!("Unexpected end of arguments"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd); + let err = create_error(&format!("Unexpected end of arguments"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd, ctx); print_error(&err, &ctx); process::exit(1); } *pos += 1; } if input[*pos].typ != TokenType::SEPARATOR || input[*pos].value != "{" { - let err = create_error(&format!("Expected {{"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::Expected); + let err = create_error(&format!("Expected {{"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::Expected, ctx); print_error(&err, &ctx); process::exit(1); } @@ -370,7 +370,7 @@ fn read_function(input: &Vec, pos: &mut usize, with_args: bool, ctx: &Con ]; let body = parse_internal(input, &op_ends, &parse_ends, pos, ctx); if input[*pos].typ != TokenType::SEPARATOR || input[*pos].value != "}" { - let err = create_error(&format!("Unexpected end of function"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd); + let err = create_error(&format!("Unexpected end of function"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd, ctx); print_error(&err, &ctx); process::exit(1); } @@ -403,25 +403,25 @@ fn read_table(input: &Vec, pos: &mut usize, ctx: &Context) -> ASTPart { let keyy = read_exp(pos, input, &key_ends, &key_ends, ctx); match keyy { ASTPart::Table(_) => { - let err = create_error(&format!("Table keys cannot be tables"), input[*pos].pos, ErrorType::SemanticError, ErrorSubType::InvalidTableKeys); + let err = create_error(&format!("Table keys cannot be tables"), input[*pos].pos, ErrorType::SemanticError, ErrorSubType::InvalidTableKeys, ctx); print_error(&err, &ctx); process::exit(1); }, ASTPart::Function(_) => { - let err = create_error(&format!("Table keys cannot be functions"), input[*pos].pos, ErrorType::SemanticError, ErrorSubType::InvalidTableKeys); + let err = create_error(&format!("Table keys cannot be functions"), input[*pos].pos, ErrorType::SemanticError, ErrorSubType::InvalidTableKeys, ctx); print_error(&err, &ctx); process::exit(1); }, _ => {} } if input[*pos].typ != TokenType::SEPARATOR || input[*pos].value != "]" { - let err = create_error(&format!("Unexpected end of key"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd); + let err = create_error(&format!("Unexpected end of key"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd, ctx); print_error(&err, &ctx); process::exit(1); } *pos += 1; if input[*pos].typ != TokenType::SEPARATOR || input[*pos].value != "=" { - let err = create_error(&format!("Expected `=` after key"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::Expected); + let err = create_error(&format!("Expected `=` after key"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::Expected, ctx); print_error(&err, &ctx); process::exit(1); } @@ -443,7 +443,7 @@ fn read_table(input: &Vec, pos: &mut usize, ctx: &Context) -> ASTPart { *pos += 1; continue; } else { - let err = create_error(&format!("Unexpected end of table"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd); + let err = create_error(&format!("Unexpected end of table"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd, ctx); print_error(&err, &ctx); process::exit(1); } @@ -503,7 +503,7 @@ fn read_exp(pos: &mut usize, input: &Vec, ends: &Vec, parse_ends: let func = read_function(input, pos, true, ctx); expressions.push(func); } else { - let err = create_error(&format!("Unexpected `{:?}({})`", token.typ, token.value), token.pos, ErrorType::SyntaxError, ErrorSubType::Unexpected); + let err = create_error(&format!("Unexpected `{:?}({})`", token.typ, token.value), token.pos, ErrorType::SyntaxError, ErrorSubType::Unexpected, ctx); print_error(&err, &ctx); process::exit(1); } @@ -521,19 +521,19 @@ fn read_exp(pos: &mut usize, input: &Vec, ends: &Vec, parse_ends: let keyy = read_exp(pos, input, &key_ends, &key_ends, ctx); match keyy { ASTPart::Table(_) => { - let err = create_error(&format!("Table keys cannot be tables"), input[*pos].pos, ErrorType::SemanticError, ErrorSubType::InvalidTableKeys); + let err = create_error(&format!("Table keys cannot be tables"), input[*pos].pos, ErrorType::SemanticError, ErrorSubType::InvalidTableKeys, ctx); print_error(&err, &ctx); process::exit(1); }, ASTPart::Function(_) => { - let err = create_error(&format!("Table keys cannot be functions"), input[*pos].pos, ErrorType::SemanticError, ErrorSubType::InvalidTableKeys); + let err = create_error(&format!("Table keys cannot be functions"), input[*pos].pos, ErrorType::SemanticError, ErrorSubType::InvalidTableKeys, ctx); print_error(&err, &ctx); process::exit(1); }, _ => {} } if input[*pos].typ != TokenType::SEPARATOR || input[*pos].value != "]" { - let err = create_error(&format!("Unexpected end of key"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd); + let err = create_error(&format!("Unexpected end of key"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd, ctx); print_error(&err, &ctx); process::exit(1); } @@ -545,7 +545,7 @@ fn read_exp(pos: &mut usize, input: &Vec, ends: &Vec, parse_ends: *pos += 1; let keyy = &input[*pos]; if keyy.typ != TokenType::IDENTIFIER { - let err = create_error(&format!("Expected identifier after `.`"), keyy.pos, ErrorType::SyntaxError, ErrorSubType::Expected); + let err = create_error(&format!("Expected identifier after `.`"), keyy.pos, ErrorType::SyntaxError, ErrorSubType::Expected, ctx); print_error(&err, &ctx); process::exit(1); } @@ -567,7 +567,7 @@ fn read_exp(pos: &mut usize, input: &Vec, ends: &Vec, parse_ends: if input[*pos].typ == TokenType::SEPARATOR && input[*pos].value == ")" { *pos += 1; } else { - let err = create_error(&format!("Unclosed parenthesis"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::Unclosed); + let err = create_error(&format!("Unclosed parenthesis"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::Unclosed, ctx); print_error(&err, &ctx); process::exit(1); } @@ -576,12 +576,12 @@ fn read_exp(pos: &mut usize, input: &Vec, ends: &Vec, parse_ends: let tbl = read_table(input, pos, ctx); expressions.push(tbl); } else { - let err = create_error(&format!("Unexpected `{:?}({})`", token.typ, token.value), token.pos, ErrorType::SyntaxError, ErrorSubType::Unexpected); + let err = create_error(&format!("Unexpected `{:?}({})`", token.typ, token.value), token.pos, ErrorType::SyntaxError, ErrorSubType::Unexpected, ctx); print_error(&err, &ctx); process::exit(1); } } else { - let err = create_error(&format!("Unexpected `{:?}({})`", token.typ, token.value), token.pos, ErrorType::SyntaxError, ErrorSubType::Unexpected); + let err = create_error(&format!("Unexpected `{:?}({})`", token.typ, token.value), token.pos, ErrorType::SyntaxError, ErrorSubType::Unexpected, ctx); print_error(&err, &ctx); process::exit(1); } @@ -611,19 +611,19 @@ fn check_continue(pos: &mut usize, input: &Vec, prev: ASTPart, op_ends: & let keyy = read_exp(pos, input, &key_ends, &key_ends, ctx); match keyy { ASTPart::Table(_) => { - let err = create_error(&format!("Table keys cannot be tables"), input[*pos].pos, ErrorType::SemanticError, ErrorSubType::InvalidTableKeys); + let err = create_error(&format!("Table keys cannot be tables"), input[*pos].pos, ErrorType::SemanticError, ErrorSubType::InvalidTableKeys, ctx); print_error(&err, &ctx); process::exit(1); }, ASTPart::Function(_) => { - let err = create_error(&format!("Table keys cannot be functions"), input[*pos].pos, ErrorType::SemanticError, ErrorSubType::InvalidTableKeys); + let err = create_error(&format!("Table keys cannot be functions"), input[*pos].pos, ErrorType::SemanticError, ErrorSubType::InvalidTableKeys, ctx); print_error(&err, &ctx); process::exit(1); }, _ => {} } if input[*pos].typ != TokenType::SEPARATOR || input[*pos].value != "]" { - let err = create_error(&format!("Unexpected end of key"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd); + let err = create_error(&format!("Unexpected end of key"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd, ctx); print_error(&err, &ctx); process::exit(1); } @@ -635,7 +635,7 @@ fn check_continue(pos: &mut usize, input: &Vec, prev: ASTPart, op_ends: & *pos += 1; let keyy = &input[*pos]; if keyy.typ != TokenType::IDENTIFIER { - let err = create_error(&format!("Expected identifier after `.`"), keyy.pos, ErrorType::SyntaxError, ErrorSubType::Expected); + let err = create_error(&format!("Expected identifier after `.`"), keyy.pos, ErrorType::SyntaxError, ErrorSubType::Expected, ctx); print_error(&err, &ctx); process::exit(1); } @@ -668,7 +668,7 @@ fn next_operation(pos: &mut usize, input: &Vec, op_ends: &Vec, par let variable = &input[*pos]; *pos += 1; if variable.typ != TokenType::IDENTIFIER { - let err = create_error(&format!("Unexpected `{:?}`", variable.typ,), token.pos, ErrorType::SyntaxError, ErrorSubType::Unexpected); + let err = create_error(&format!("Unexpected `{:?}`", variable.typ,), token.pos, ErrorType::SyntaxError, ErrorSubType::Unexpected, ctx); print_error(&err, &ctx); process::exit(1); } @@ -680,7 +680,7 @@ fn next_operation(pos: &mut usize, input: &Vec, op_ends: &Vec, par return ASTPart::Assigment(AstAssigment { variable: variable.value.clone(), value: Box::new(value), pos: token.pos }); } else if token.value == "ha geny" { if next_token.typ != TokenType::SEPARATOR || next_token.value != "(" { - let err = create_error(&format!("Expected `(`"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected); + let err = create_error(&format!("Expected `(`"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected, ctx); print_error(&err, &ctx); process::exit(1); } @@ -690,7 +690,7 @@ fn next_operation(pos: &mut usize, input: &Vec, op_ends: &Vec, par ]; let condition = read_exp(pos, input, &condition_end, &condition_end, ctx); if input[*pos].typ != TokenType::SEPARATOR || input[*pos].value != ")" { - let err = create_error(&format!("Unexpected end of condition"), token.pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd); + let err = create_error(&format!("Unexpected end of condition"), token.pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd, ctx); print_error(&err, &ctx); process::exit(1); } @@ -699,7 +699,7 @@ fn next_operation(pos: &mut usize, input: &Vec, op_ends: &Vec, par let real_body = match body { ASTPart::Function(func) => func.body, _ => { - let err = create_error(&format!("Expected function body"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected); + let err = create_error(&format!("Expected function body"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected, ctx); print_error(&err, &ctx); process::exit(1); } @@ -707,7 +707,7 @@ fn next_operation(pos: &mut usize, input: &Vec, op_ends: &Vec, par return ASTPart::If(AstIf { condition: Box::new(condition), body: real_body, pos: token.pos }); } else if token.value == "amíg geny" { if next_token.typ != TokenType::SEPARATOR || next_token.value != "(" { - let err = create_error(&format!("Expected `(`"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected); + let err = create_error(&format!("Expected `(`"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected, ctx); print_error(&err, &ctx); process::exit(1); } @@ -717,7 +717,7 @@ fn next_operation(pos: &mut usize, input: &Vec, op_ends: &Vec, par ]; let condition = read_exp(pos, input, &condition_end, &condition_end, ctx); if input[*pos].typ != TokenType::SEPARATOR || input[*pos].value != ")" { - let err = create_error(&format!("Unexpected end of condition"), token.pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd); + let err = create_error(&format!("Unexpected end of condition"), token.pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd, ctx); print_error(&err, &ctx); process::exit(1); } @@ -726,7 +726,7 @@ fn next_operation(pos: &mut usize, input: &Vec, op_ends: &Vec, par let real_body = match body { ASTPart::Function(func) => func.body, _ => { - let err = create_error(&format!("Expected function body"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected); + let err = create_error(&format!("Expected function body"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected, ctx); print_error(&err, &ctx); process::exit(1); } @@ -736,7 +736,7 @@ fn next_operation(pos: &mut usize, input: &Vec, op_ends: &Vec, par return ASTPart::Break(AstBreak { pos: token.pos }); } else if token.value == "kopva" { if next_token.typ != TokenType::SEPARATOR || next_token.value != "(" { - let err = create_error(&format!("Expected `(`"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected); + let err = create_error(&format!("Expected `(`"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected, ctx); print_error(&err, &ctx); process::exit(1); } @@ -747,31 +747,31 @@ fn next_operation(pos: &mut usize, input: &Vec, op_ends: &Vec, par ]; let init = parse_internal(input, &ends, &ends, pos, ctx); if init.len() != 1 { - let err = create_error(&format!("Only one expression is expected for init"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected); + let err = create_error(&format!("Only one expression is expected for init"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected, ctx); print_error(&err, &ctx); process::exit(1); } if input[*pos].typ != TokenType::OPEND || input[*pos].value != ";" { - let err = create_error(&format!("Unexpected end of init"), token.pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd); + let err = create_error(&format!("Unexpected end of init"), token.pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd, ctx); print_error(&err, &ctx); process::exit(1); } *pos += 1; let condition = read_exp(pos, input, &ends, &ends, ctx); if input[*pos].typ != TokenType::OPEND || input[*pos].value != ";" { - let err = create_error(&format!("Unexpected end of condition"), token.pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd); + let err = create_error(&format!("Unexpected end of condition"), token.pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd, ctx); print_error(&err, &ctx); process::exit(1); } *pos += 1; let update = parse_internal(input, &ends, &ends, pos, ctx); if update.len() != 1 { - let err = create_error(&format!("Only one expression is expected for update"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected); + let err = create_error(&format!("Only one expression is expected for update"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected, ctx); print_error(&err, &ctx); process::exit(1); } if input[*pos].typ != TokenType::SEPARATOR || input[*pos].value != ")" { - let err = create_error(&format!("Unexpected end of update"), token.pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd); + let err = create_error(&format!("Unexpected end of update"), token.pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd, ctx); print_error(&err, &ctx); process::exit(1); } @@ -780,7 +780,7 @@ fn next_operation(pos: &mut usize, input: &Vec, op_ends: &Vec, par let real_body = match body { ASTPart::Function(func) => func.body, _ => { - let err = create_error(&format!("Expected function body"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected); + let err = create_error(&format!("Expected function body"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected, ctx); print_error(&err, &ctx); process::exit(1); } @@ -790,7 +790,7 @@ fn next_operation(pos: &mut usize, input: &Vec, op_ends: &Vec, par return ASTPart::Continue(AstContinue { pos: token.pos }); } else if token.value == "ha nem geny akkor geny" { if next_token.typ != TokenType::SEPARATOR || next_token.value != "(" { - let err = create_error(&format!("Expected `(`"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected); + let err = create_error(&format!("Expected `(`"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected, ctx); print_error(&err, &ctx); process::exit(1); } @@ -800,7 +800,7 @@ fn next_operation(pos: &mut usize, input: &Vec, op_ends: &Vec, par ]; let condition = read_exp(pos, input, &condition_end, &condition_end, ctx); if input[*pos].typ != TokenType::SEPARATOR || input[*pos].value != ")" { - let err = create_error(&format!("Unexpected end of condition"), token.pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd); + let err = create_error(&format!("Unexpected end of condition"), token.pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd, ctx); print_error(&err, &ctx); process::exit(1); } @@ -809,7 +809,7 @@ fn next_operation(pos: &mut usize, input: &Vec, op_ends: &Vec, par let real_body = match body { ASTPart::Function(func) => func.body, _ => { - let err = create_error(&format!("Expected function body"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected); + let err = create_error(&format!("Expected function body"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected, ctx); print_error(&err, &ctx); process::exit(1); } @@ -820,7 +820,7 @@ fn next_operation(pos: &mut usize, input: &Vec, op_ends: &Vec, par let real_body = match body { ASTPart::Function(func) => func.body, _ => { - let err = create_error(&format!("Expected function body"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected); + let err = create_error(&format!("Expected function body"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected, ctx); print_error(&err, &ctx); process::exit(1); } @@ -837,19 +837,19 @@ fn next_operation(pos: &mut usize, input: &Vec, op_ends: &Vec, par let var = &input[*pos]; *pos += 1; if var.typ != TokenType::IDENTIFIER { - let err = create_error(&format!("Expected identifier after hámozd"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected); + let err = create_error(&format!("Expected identifier after hámozd"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected, ctx); print_error(&err, &ctx); process::exit(1); } if input[*pos].typ != TokenType::KEYWORD || (input[*pos].value != "be" && input[*pos].value != "ba") { - let err = create_error(&format!("Expected `be`/`ba` after hámozd"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::Expected); + let err = create_error(&format!("Expected `be`/`ba` after hámozd"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::Expected, ctx); print_error(&err, &ctx); process::exit(1); } *pos += 1; let path = &input[*pos]; if path.typ != TokenType::STRING { - let err = create_error(&format!("Expected string for hámozd"), path.pos, ErrorType::SyntaxError, ErrorSubType::Expected); + let err = create_error(&format!("Expected string for hámozd"), path.pos, ErrorType::SyntaxError, ErrorSubType::Expected, ctx); print_error(&err, &ctx); process::exit(1); } @@ -869,13 +869,13 @@ fn next_operation(pos: &mut usize, input: &Vec, op_ends: &Vec, par let tryp = match func { ASTPart::Function(f) => f, _ => { - let err = create_error(&format!("Expected function body"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected); + let err = create_error(&format!("Expected function body"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected, ctx); print_error(&err, &ctx); process::exit(1); } }; if input[*pos].typ != TokenType::KEYWORD || input[*pos].value != "csecs" { - let err = create_error(&format!("Expected `csecs` after piszolj"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::Expected); + let err = create_error(&format!("Expected `csecs` after piszolj"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::Expected, ctx); print_error(&err, &ctx); process::exit(1); } @@ -884,14 +884,14 @@ fn next_operation(pos: &mut usize, input: &Vec, op_ends: &Vec, par let catchp = match func2 { ASTPart::Function(f) => f, _ => { - let err = create_error(&format!("Expected function body"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::Expected); + let err = create_error(&format!("Expected function body"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::Expected, ctx); print_error(&err, &ctx); process::exit(1); } }; return ASTPart::TryCatch(AstTryCatch { try_block: tryp, catch_block: catchp, pos: token.pos }); } else { - let err = create_error(&format!("Unexpected `{:?}({})`", token.typ, token.value), token.pos, ErrorType::SyntaxError, ErrorSubType::Unexpected); + let err = create_error(&format!("Unexpected `{:?}({})`", token.typ, token.value), token.pos, ErrorType::SyntaxError, ErrorSubType::Unexpected, ctx); print_error(&err, &ctx); process::exit(1); } @@ -905,7 +905,7 @@ fn next_operation(pos: &mut usize, input: &Vec, op_ends: &Vec, par *pos += 1; let keyy = &input[*pos]; if keyy.typ != TokenType::IDENTIFIER { - let err = create_error(&format!("Expected identifier after `.`"), keyy.pos, ErrorType::SyntaxError, ErrorSubType::Expected); + let err = create_error(&format!("Expected identifier after `.`"), keyy.pos, ErrorType::SyntaxError, ErrorSubType::Expected, ctx); print_error(&err, &ctx); process::exit(1); } @@ -920,19 +920,19 @@ fn next_operation(pos: &mut usize, input: &Vec, op_ends: &Vec, par let keyy = read_exp(pos, input, &key_ends, &key_ends, ctx); match keyy { ASTPart::Table(_) => { - let err = create_error(&format!("Table keys cannot be tables"), input[*pos].pos, ErrorType::SemanticError, ErrorSubType::InvalidTableKeys); + let err = create_error(&format!("Table keys cannot be tables"), input[*pos].pos, ErrorType::SemanticError, ErrorSubType::InvalidTableKeys, ctx); print_error(&err, &ctx); process::exit(1); }, ASTPart::Function(_) => { - let err = create_error(&format!("Table keys cannot be functions"), input[*pos].pos, ErrorType::SemanticError, ErrorSubType::InvalidTableKeys); + let err = create_error(&format!("Table keys cannot be functions"), input[*pos].pos, ErrorType::SemanticError, ErrorSubType::InvalidTableKeys, ctx); print_error(&err, &ctx); process::exit(1); }, _ => {} } if input[*pos].typ != TokenType::SEPARATOR || input[*pos].value != "]" { - let err = create_error(&format!("Unexpected end of key"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd); + let err = create_error(&format!("Unexpected end of key"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd, ctx); print_error(&err, &ctx); process::exit(1); } @@ -950,12 +950,12 @@ fn next_operation(pos: &mut usize, input: &Vec, op_ends: &Vec, par let value = read_exp(pos, input, op_ends, parse_ends, ctx); return ASTPart::VarUpdate(AstVarUpdate { variable: token.value.clone(), value: Box::new(value), pos: token.pos }); } else { - let err = create_error(&format!("Unexpected `{:?}({})`", token.typ, token.value), token.pos, ErrorType::SyntaxError, ErrorSubType::Unexpected); + let err = create_error(&format!("Unexpected `{:?}({})`", token.typ, token.value), token.pos, ErrorType::SyntaxError, ErrorSubType::Unexpected, ctx); print_error(&err, &ctx); process::exit(1); } } else { - let err = create_error(&format!("Unexpected `{:?}({})`", token.typ, token.value), token.pos, ErrorType::SyntaxError, ErrorSubType::Unexpected); + let err = create_error(&format!("Unexpected `{:?}({})`", token.typ, token.value), token.pos, ErrorType::SyntaxError, ErrorSubType::Unexpected, ctx); print_error(&err, &ctx); process::exit(1); } diff --git a/src/virtualmachine.rs b/src/virtualmachine.rs index 6ff9e46..c02206d 100644 --- a/src/virtualmachine.rs +++ b/src/virtualmachine.rs @@ -1,5 +1,5 @@ use std::{any::Any, collections::HashMap, process, vec}; -use crate::{decompiler::{operation_to_name, process, DecompiledFunction, DecompiledOperation}, enviroment, errors::{create_error, print_error, ErrorSubType, ErrorType}, Context}; +use crate::{decompiler::{operation_to_name, process, DecompiledFunction, DecompiledOperation}, enviroment, errors::{create_error, print_error, ASLError, ErrorSubType, ErrorType}, Context}; #[derive(Debug, Clone)] pub enum VMMemory { @@ -64,6 +64,14 @@ pub struct CallStack { pub pc: usize, } +#[derive(Debug, Clone)] +enum VMState { + Running, + Paused, + Finished, + Error(ASLError), +} + pub struct Machine { pub memory: Vec, functions: Vec, @@ -73,6 +81,7 @@ pub struct Machine { pub env: HashMap, pub ctx: Vec, pub storage: Vec>, + pub state: VMState, } fn get_register_by_id(registers: &Vec, id: u8) -> Option<&Register> { @@ -181,14 +190,14 @@ fn do_operation_operation(registers: &mut Vec, memory: &mut Vec= memory.len() || mem2 >= memory.len() || mem1 < 1 || mem2 < 1 { - let err = create_error(&format!("Memory location out of bounds `{}` or `{}`", mem1, mem2), operation.pos, ErrorType::MachineError, ErrorSubType::MemoryOutOfBounds); + let err = create_error(&format!("Memory location out of bounds `{}` or `{}`", mem1, mem2), operation.pos, ErrorType::MachineError, ErrorSubType::MemoryOutOfBounds, ctx); print_error(&err, &ctx); process::exit(1); } @@ -207,7 +216,7 @@ fn do_operation_operation(registers: &mut Vec, memory: &mut Vec { if num2.value == 0.0 { - let err = create_error(&format!("Division by zero"), operation.pos, ErrorType::MathError, ErrorSubType::DivisionByZero); + let err = create_error(&format!("Division by zero"), operation.pos, ErrorType::MathError, ErrorSubType::DivisionByZero, ctx); print_error(&err, &ctx); process::exit(1); } @@ -238,7 +247,7 @@ fn do_operation_operation(registers: &mut Vec, memory: &mut Vec { - let err = create_error(&format!("Unknown operation code for number operation: `{}`", operation.opcode), operation.pos, ErrorType::MachineError, ErrorSubType::UnknownOPCode); + let err = create_error(&format!("Unknown operation code for number operation: `{}`", operation.opcode), operation.pos, ErrorType::MachineError, ErrorSubType::UnknownOPCode, ctx); print_error(&err, &ctx); process::exit(1); } @@ -256,7 +265,7 @@ fn do_operation_operation(registers: &mut Vec, memory: &mut Vec { - let err = create_error(&format!("Unknown operation code for string operation: `{}`", operation.opcode), operation.pos, ErrorType::MachineError, ErrorSubType::UnknownOPCode); + let err = create_error(&format!("Unknown operation code for string operation: `{}`", operation.opcode), operation.pos, ErrorType::MachineError, ErrorSubType::UnknownOPCode, ctx); print_error(&err, &ctx); process::exit(1); } @@ -277,7 +286,7 @@ fn do_operation_operation(registers: &mut Vec, memory: &mut Vec { - let err = create_error(&format!("Unknown operation code for boolean operation: `{}`", operation.opcode), operation.pos, ErrorType::MachineError, ErrorSubType::UnknownOPCode); + let err = create_error(&format!("Unknown operation code for boolean operation: `{}`", operation.opcode), operation.pos, ErrorType::MachineError, ErrorSubType::UnknownOPCode, ctx); print_error(&err, &ctx); process::exit(1); } @@ -292,14 +301,14 @@ fn do_operation_operation(registers: &mut Vec, memory: &mut Vec { - let err = create_error(&format!("Unknown operation code for null operation: `{}`", operation.opcode), operation.pos, ErrorType::MachineError, ErrorSubType::UnknownOPCode); + let err = create_error(&format!("Unknown operation code for null operation: `{}`", operation.opcode), operation.pos, ErrorType::MachineError, ErrorSubType::UnknownOPCode, ctx); print_error(&err, &ctx); process::exit(1); } }; }, _ => { - let err = create_error(&format!("Wrong memory types for operation: `{}`, position: `{}` and `{}`", operation_to_name(operation.opcode), mem1, mem2), operation.pos, ErrorType::TypeError, ErrorSubType::WrongType); + let err = create_error(&format!("Wrong memory types for operation: `{}`, position: `{}` and `{}`", operation_to_name(operation.opcode), mem1, mem2), operation.pos, ErrorType::TypeError, ErrorSubType::WrongType, ctx); print_error(&err, &ctx); process::exit(1); } @@ -339,15 +348,23 @@ impl Machine { env: enviroment::generate(), ctx: ctx, storage: Vec::new(), + state: VMState::Finished }; } pub fn load(&mut self, data: &Vec) { let dec = process(data); self.functions = dec.functions; + self.state = VMState::Paused } - pub fn run(&mut self) { + pub fn resume(&mut self) { + match self.state { + VMState::Paused => {}, + _ => { + panic!("Unable to resume VM, current state is not paused"); + } + }; if self.call_stack.len() == 0 { return; } @@ -355,12 +372,19 @@ impl Machine { let executed_func = func_clone.get(self.call_stack[self.call_stack.len()-1].func); let mut executed_stack = self.call_stack.len()-1; if executed_func.is_none() { - let err = create_error(&format!("Current function not found"), 1, ErrorType::MachineError, ErrorSubType::UnknownFunction); + let err = create_error(&format!("Current function not found"), 1, ErrorType::MachineError, ErrorSubType::UnknownFunction, &self.ctx[self.call_stack[executed_stack].func].clone()); print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); process::exit(1); } let mut executed_func = executed_func.unwrap(); + self.state = VMState::Running; while self.call_stack[executed_stack].pc < executed_func.body.len() { + match self.state { + VMState::Running => {}, + _ => { + return; + } + }; let operation = &executed_func.body[self.call_stack[executed_stack].pc]; self.call_stack[executed_stack].pc += 1; match operation.opcode { @@ -372,7 +396,7 @@ impl Machine { //LDS let str = executed_func.strings.get(&(operation.arg2 as u32)); if str.is_none() { - let err = create_error(&format!("String with ID `{}` not found", operation.arg2), operation.pos, ErrorType::MachineError, ErrorSubType::UnknownString); + let err = create_error(&format!("String with ID `{}` not found", operation.arg2), operation.pos, ErrorType::MachineError, ErrorSubType::UnknownString, &self.ctx[self.call_stack[executed_stack].func].clone()); print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); process::exit(1); } @@ -384,13 +408,13 @@ impl Machine { //LDM let mem = get_mem_pos_by_var_id(&self.memory, operation.arg2 as u32); if mem.is_none() { - let err = create_error(&format!("Memory with variable ID `{}` not found", operation.arg2), operation.pos, ErrorType::MachineError, ErrorSubType::UnknownMemoryLocation); + let err = create_error(&format!("Memory with variable ID `{}` not found", operation.arg2), operation.pos, ErrorType::MachineError, ErrorSubType::UnknownMemoryLocation, &self.ctx[self.call_stack[executed_stack].func].clone()); print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); process::exit(1); } let mem = mem.unwrap(); if mem >= self.memory.len() || mem < 1 { - let err = create_error(&format!("Memory location out of bounds for variable ID `{}`", operation.arg2), operation.pos, ErrorType::MachineError, ErrorSubType::MemoryOutOfBounds); + let err = create_error(&format!("Memory location out of bounds for variable ID `{}`", operation.arg2), operation.pos, ErrorType::MachineError, ErrorSubType::MemoryOutOfBounds, &self.ctx[self.call_stack[executed_stack].func].clone()); print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); process::exit(1); } @@ -435,14 +459,14 @@ impl Machine { //LDF let func_pos = executed_func.functions.get(&(operation.arg2 as u32)); if func_pos.is_none() { - let err = create_error(&format!("Function with ID `{}` not found", operation.arg2), operation.pos, ErrorType::MachineError, ErrorSubType::UnknownFunction); + let err = create_error(&format!("Function with ID `{}` not found", operation.arg2), operation.pos, ErrorType::MachineError, ErrorSubType::UnknownFunction, &self.ctx[self.call_stack[executed_stack].func].clone()); print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); process::exit(1); } let func_pos = func_pos.unwrap(); let func = self.functions.get(*func_pos as usize); if func.is_none() { - let err = create_error(&format!("Function with position `{}` not found", func_pos), operation.pos, ErrorType::MachineError, ErrorSubType::UnknownFunction); + let err = create_error(&format!("Function with position `{}` not found", func_pos), operation.pos, ErrorType::MachineError, ErrorSubType::UnknownFunction, &self.ctx[self.call_stack[executed_stack].func].clone()); print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); process::exit(1); } @@ -466,13 +490,13 @@ impl Machine { //ASS let reg = get_register_by_id(&self.registers, operation.arg1); if reg.is_none() { - let err = create_error(&format!("Register `{}` not found", operation.arg1), operation.pos, ErrorType::MachineError, ErrorSubType::RegisterNotFound); + let err = create_error(&format!("Register `{}` not found", operation.arg1), operation.pos, ErrorType::MachineError, ErrorSubType::RegisterNotFound, &self.ctx[self.call_stack[executed_stack].func].clone()); print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); process::exit(1); } let reg = reg.unwrap(); if reg.pointer >= self.memory.len() || reg.pointer < 1 { - let err = create_error(&format!("Register `{}` points to an invalid memory location", operation.arg1), operation.pos, ErrorType::MachineError, ErrorSubType::MemoryOutOfBounds); + let err = create_error(&format!("Register `{}` points to an invalid memory location", operation.arg1), operation.pos, ErrorType::MachineError, ErrorSubType::MemoryOutOfBounds, &self.ctx[self.call_stack[executed_stack].func].clone()); print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); process::exit(1); } @@ -491,7 +515,7 @@ impl Machine { let temp_regs = self.registers.clone(); let reg1 = get_register_by_id(&temp_regs, operation.arg1); if reg1.is_none() { - let err = create_error(&format!("Register `{}` not found", operation.arg1), operation.pos, ErrorType::MachineError, ErrorSubType::RegisterNotFound); + let err = create_error(&format!("Register `{}` not found", operation.arg1), operation.pos, ErrorType::MachineError, ErrorSubType::RegisterNotFound, &self.ctx[self.call_stack[executed_stack].func].clone()); print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); process::exit(1); } @@ -507,13 +531,13 @@ impl Machine { let reg1 = get_register_by_id(®_clone, operation.arg1); let reg2 = get_register_by_id(®_clone, operation.arg2 as u8); if reg1.is_none() || reg2.is_none() { - let err = create_error(&format!("Register `{}` or `{}` not found", operation.arg1, operation.arg2), operation.pos, ErrorType::MachineError, ErrorSubType::RegisterNotFound); + let err = create_error(&format!("Register `{}` or `{}` not found", operation.arg1, operation.arg2), operation.pos, ErrorType::MachineError, ErrorSubType::RegisterNotFound, &self.ctx[self.call_stack[executed_stack].func].clone()); print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); process::exit(1); } let mem1 = reg1.unwrap().pointer; if mem1 >= self.memory.len() || mem1 < 1 { - let err = create_error(&format!("Memory location out of bounds for register `{}`", operation.arg1), operation.pos, ErrorType::MachineError, ErrorSubType::MemoryOutOfBounds); + let err = create_error(&format!("Memory location out of bounds for register `{}`", operation.arg1), operation.pos, ErrorType::MachineError, ErrorSubType::MemoryOutOfBounds, &self.ctx[self.call_stack[executed_stack].func].clone()); print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); process::exit(1); } @@ -523,7 +547,7 @@ impl Machine { result = VMMemory::Boolean(VMMemoryBoolean { value: !bool.value, variable_id: 0 }); }, _ => { - let err = create_error(&format!("Wrong memory type for NOT operation, position: `{}`", mem1), operation.pos, ErrorType::TypeError, ErrorSubType::WrongType); + let err = create_error(&format!("Wrong memory type for NOT operation, position: `{}`", mem1), operation.pos, ErrorType::TypeError, ErrorSubType::WrongType, &self.ctx[self.call_stack[executed_stack].func].clone()); print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); process::exit(1); } @@ -546,14 +570,14 @@ impl Machine { //CJP let reg = get_register_by_id(&self.registers, operation.arg1); if reg.is_none() { - let err = create_error(&format!("Register `{}` not found", operation.arg1), operation.pos, ErrorType::MachineError, ErrorSubType::RegisterNotFound); + let err = create_error(&format!("Register `{}` not found", operation.arg1), operation.pos, ErrorType::MachineError, ErrorSubType::RegisterNotFound, &self.ctx[self.call_stack[executed_stack].func].clone()); print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); process::exit(1); } let reg = reg.unwrap(); let mem = self.memory.get(reg.pointer); if mem.is_none() { - let err = create_error(&format!("Memory location not found for register `{}`", operation.arg1), operation.pos, ErrorType::MachineError, ErrorSubType::UnknownMemoryLocation); + let err = create_error(&format!("Memory location not found for register `{}`", operation.arg1), operation.pos, ErrorType::MachineError, ErrorSubType::UnknownMemoryLocation, &self.ctx[self.call_stack[executed_stack].func].clone()); print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); process::exit(1); } @@ -565,7 +589,7 @@ impl Machine { } } _ => { - let err = create_error(&format!("Wrong memory type for CJP operation, position: `{}`", reg.pointer), operation.pos, ErrorType::TypeError, ErrorSubType::WrongType); + let err = create_error(&format!("Wrong memory type for CJP operation, position: `{}`", reg.pointer), operation.pos, ErrorType::TypeError, ErrorSubType::WrongType, &self.ctx[self.call_stack[executed_stack].func].clone()); print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); process::exit(1); }, @@ -575,14 +599,14 @@ impl Machine { //CAL let reg = get_register_by_id(&self.registers, operation.arg1); if reg.is_none() { - let err = create_error(&format!("Register `{}` not found", operation.arg1), operation.pos, ErrorType::MachineError, ErrorSubType::RegisterNotFound); + let err = create_error(&format!("Register `{}` not found", operation.arg1), operation.pos, ErrorType::MachineError, ErrorSubType::RegisterNotFound, &self.ctx[self.call_stack[executed_stack].func].clone()); print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); process::exit(1); } let reg = reg.unwrap(); let mem = self.memory.get(reg.pointer); if mem.is_none() { - let err = create_error(&format!("Memory location not found for register `{}`", operation.arg1), operation.pos, ErrorType::MachineError, ErrorSubType::UnknownMemoryLocation); + let err = create_error(&format!("Memory location not found for register `{}`", operation.arg1), operation.pos, ErrorType::MachineError, ErrorSubType::UnknownMemoryLocation, &self.ctx[self.call_stack[executed_stack].func].clone()); print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); process::exit(1); } @@ -593,7 +617,7 @@ impl Machine { for i in &self.stack { let mut new_mem = i.clone(); if self.functions[func.id].variables.len() <= arg || self.functions[func.id].variables[arg].start != 0 { - let err = create_error(&format!("Too many arguments supplied for function: `{}`", func.id), operation.pos, ErrorType::SemanticError, ErrorSubType::TooManyArguments); + let err = create_error(&format!("Too many arguments supplied for function: `{}`", func.id), operation.pos, ErrorType::SemanticError, ErrorSubType::TooManyArguments, &self.ctx[self.call_stack[executed_stack].func].clone()); print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); process::exit(1); } @@ -610,7 +634,7 @@ impl Machine { 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); + let err = create_error(&format!("Register `{}` not found", operation.arg2), operation.pos, ErrorType::MachineError, ErrorSubType::RegisterNotFound, &self.ctx[self.call_stack[executed_stack].func].clone()); print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); process::exit(1); } @@ -627,7 +651,7 @@ impl Machine { self.stack.clear(); }, _ => { - let err = create_error(&format!("Unable to call non-function type"), operation.pos, ErrorType::MachineError, ErrorSubType::NonFunctionCall); + let err = create_error(&format!("Unable to call non-function type"), operation.pos, ErrorType::MachineError, ErrorSubType::NonFunctionCall, &self.ctx[self.call_stack[executed_stack].func].clone()); print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); process::exit(1); } @@ -637,14 +661,14 @@ impl Machine { //PSH let reg = get_register_by_id(&self.registers, operation.arg1); if reg.is_none() { - let err = create_error(&format!("Register `{}` not found", operation.arg1), operation.pos, ErrorType::MachineError, ErrorSubType::RegisterNotFound); + let err = create_error(&format!("Register `{}` not found", operation.arg1), operation.pos, ErrorType::MachineError, ErrorSubType::RegisterNotFound, &self.ctx[self.call_stack[executed_stack].func].clone()); print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); process::exit(1); } let reg = reg.unwrap(); let mem = self.memory.get(reg.pointer); if mem.is_none() { - let err = create_error(&format!("Memory location not found for register `{}`", operation.arg1), operation.pos, ErrorType::MachineError, ErrorSubType::MemoryOutOfBounds); + let err = create_error(&format!("Memory location not found for register `{}`", operation.arg1), operation.pos, ErrorType::MachineError, ErrorSubType::MemoryOutOfBounds, &self.ctx[self.call_stack[executed_stack].func].clone()); print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); process::exit(1); } @@ -656,13 +680,13 @@ impl Machine { let target_reg = get_register_by_id(&self.registers, self.call_stack[executed_stack].return_reg as u8); let ret_reg = get_register_by_id(&self.registers, operation.arg1); if target_reg.is_none() || ret_reg.is_none() { - let err = create_error(&format!("Register `{}` or `{}` not found", self.call_stack[executed_stack].return_reg, operation.arg1), operation.pos, ErrorType::MachineError, ErrorSubType::RegisterNotFound); + let err = create_error(&format!("Register `{}` or `{}` not found", self.call_stack[executed_stack].return_reg, operation.arg1), operation.pos, ErrorType::MachineError, ErrorSubType::RegisterNotFound, &self.ctx[self.call_stack[executed_stack].func].clone()); print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); process::exit(1); } let ret_mem = self.memory.get(ret_reg.unwrap().pointer); if ret_mem.is_none() { - let err = create_error(&format!("Memory location not found for register `{}`", operation.arg1), operation.pos, ErrorType::MachineError, ErrorSubType::MemoryOutOfBounds); + let err = create_error(&format!("Memory location not found for register `{}`", operation.arg1), operation.pos, ErrorType::MachineError, ErrorSubType::MemoryOutOfBounds, &self.ctx[self.call_stack[executed_stack].func].clone()); print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); process::exit(1); } @@ -686,13 +710,13 @@ impl Machine { let reg2 = get_register_by_id(®_clone, operation.arg2 as u8); let reg3 = get_register_by_id(®_clone, operation.arg3); if reg2.is_none() || reg3.is_none() { - let err = create_error(&format!("Register `{}` or `{}` not found", operation.arg2, operation.arg3), operation.pos, ErrorType::MachineError, ErrorSubType::RegisterNotFound); + let err = create_error(&format!("Register `{}` or `{}` not found", operation.arg2, operation.arg3), operation.pos, ErrorType::MachineError, ErrorSubType::RegisterNotFound, &self.ctx[self.call_stack[executed_stack].func].clone()); print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); process::exit(1); } let mem2 = self.memory.get(reg2.unwrap().pointer); if mem2.is_none() { - let err = create_error(&format!("Memory location out of bounds for register `{}`", operation.arg2), operation.pos, ErrorType::MachineError, ErrorSubType::MemoryOutOfBounds); + let err = create_error(&format!("Memory location out of bounds for register `{}`", operation.arg2), operation.pos, ErrorType::MachineError, ErrorSubType::MemoryOutOfBounds, &self.ctx[self.call_stack[executed_stack].func].clone()); print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); process::exit(1); } @@ -708,7 +732,7 @@ impl Machine { } }, _ => { - let err = create_error(&format!("Only string keys are allowed for GET enviroment"), operation.pos, ErrorType::TypeError, ErrorSubType::WrongType); + let err = create_error(&format!("Only string keys are allowed for GET enviroment"), operation.pos, ErrorType::TypeError, ErrorSubType::WrongType, &self.ctx[self.call_stack[executed_stack].func].clone()); print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); process::exit(1); } @@ -728,14 +752,14 @@ impl Machine { let reg2 = get_register_by_id(®_clone, operation.arg2 as u8); let reg3 = get_register_by_id(®_clone, operation.arg3); if reg.is_none() || reg2.is_none() || reg3.is_none() { - let err = create_error(&format!("Register `{}` or `{}` or `{}` not found", operation.arg1, operation.arg2, operation.arg3), operation.pos, ErrorType::MachineError, ErrorSubType::RegisterNotFound); + let err = create_error(&format!("Register `{}` or `{}` or `{}` not found", operation.arg1, operation.arg2, operation.arg3), operation.pos, ErrorType::MachineError, ErrorSubType::RegisterNotFound, &self.ctx[self.call_stack[executed_stack].func].clone()); print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); process::exit(1); } let mem1 = self.memory.get(reg.unwrap().pointer); let mem2 = self.memory.get(reg2.unwrap().pointer); if mem1.is_none() || mem2.is_none() { - let err = create_error(&format!("Memory location not found for register `{}` or `{}`", operation.arg1, operation.arg2), operation.pos, ErrorType::MachineError, ErrorSubType::MemoryOutOfBounds); + let err = create_error(&format!("Memory location not found for register `{}` or `{}`", operation.arg1, operation.arg2), operation.pos, ErrorType::MachineError, ErrorSubType::MemoryOutOfBounds, &self.ctx[self.call_stack[executed_stack].func].clone()); print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); process::exit(1); } @@ -752,7 +776,7 @@ impl Machine { } }, _ => { - let err = create_error(&format!("Wrong memory type for GET operation, position: `{}`", reg.unwrap().pointer), operation.pos, ErrorType::TypeError, ErrorSubType::WrongType); + let err = create_error(&format!("Wrong memory type for GET operation, position: `{}`", reg.unwrap().pointer), operation.pos, ErrorType::TypeError, ErrorSubType::WrongType, &self.ctx[self.call_stack[executed_stack].func].clone()); print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); process::exit(1); } @@ -773,7 +797,7 @@ impl Machine { let reg2 = get_register_by_id(&self.registers, operation.arg2 as u8); let reg3 = get_register_by_id(&self.registers, operation.arg3); if reg.is_none() || reg2.is_none() || reg3.is_none() { - let err = create_error(&format!("Register `{}` or `{}` or `{}` not found", operation.arg1, operation.arg2, operation.arg3), operation.pos, ErrorType::MachineError, ErrorSubType::RegisterNotFound); + let err = create_error(&format!("Register `{}` or `{}` or `{}` not found", operation.arg1, operation.arg2, operation.arg3), operation.pos, ErrorType::MachineError, ErrorSubType::RegisterNotFound, &self.ctx[self.call_stack[executed_stack].func].clone()); print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); process::exit(1); } @@ -781,7 +805,7 @@ impl Machine { let mem2 = self.memory.get(reg2.unwrap().pointer); let mem3 = self.memory.get(reg3.unwrap().pointer); if mem1.is_none() || mem2.is_none() || mem3.is_none() { - let err = create_error(&format!("Memory location not found for register `{}` or `{}` or `{}`", operation.arg1, operation.arg2, operation.arg3), operation.pos, ErrorType::MachineError, ErrorSubType::MemoryOutOfBounds); + let err = create_error(&format!("Memory location not found for register `{}` or `{}` or `{}`", operation.arg1, operation.arg2, operation.arg3), operation.pos, ErrorType::MachineError, ErrorSubType::MemoryOutOfBounds, &self.ctx[self.call_stack[executed_stack].func].clone()); print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); process::exit(1); } @@ -793,18 +817,19 @@ impl Machine { set_mem_tbl_val(tbl, mem2, mem3); }, _ => { - let err = create_error(&format!("Wrong memory type for SET operation, position: `{}`", reg.unwrap().pointer), operation.pos, ErrorType::TypeError, ErrorSubType::WrongType); + let err = create_error(&format!("Wrong memory type for SET operation, position: `{}`", reg.unwrap().pointer), operation.pos, ErrorType::TypeError, ErrorSubType::WrongType, &self.ctx[self.call_stack[executed_stack].func].clone()); print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); process::exit(1); } } }, _ => { - let err = create_error(&format!("Unknown operation code: `{}`", operation.opcode), operation.pos, ErrorType::MachineError, ErrorSubType::UnknownOPCode); + let err = create_error(&format!("Unknown operation code: `{}`", operation.opcode), operation.pos, ErrorType::MachineError, ErrorSubType::UnknownOPCode, &self.ctx[self.call_stack[executed_stack].func].clone()); print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); process::exit(1); } } } + self.state = VMState::Finished; } } \ No newline at end of file From 6fe93958175bb6d773409319dae93e52a074b73f Mon Sep 17 00:00:00 2001 From: afonya Date: Wed, 18 Jun 2025 14:21:31 +0200 Subject: [PATCH 09/19] finished try/catch --- src/compiler.rs | 8 +- src/errors.rs | 4 +- src/main.rs | 4 +- src/virtualmachine.rs | 500 ++++++++++++++++++++++++++++++++++-------- test.asl | 7 +- 5 files changed, 424 insertions(+), 99 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index a0b3b02..45425fb 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -679,8 +679,12 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec, va } }, ASTPart::TryCatch(tc) => { - let catch_f = compile_function(tc.catch_block.body, None, registers, next_var_id, ctx, traceback, None); - let mut try_f = compile_function(tc.try_block.body, None, registers, next_var_id, ctx, traceback, Some(0)); + let self_tb = PrevFunc { + variables: variables.clone(), + previous: Some(Box::new(traceback.clone())), + }; + let catch_f = compile_function(tc.catch_block.body, Some(tc.catch_block.args), registers, next_var_id, ctx, &self_tb, None); + let mut try_f = compile_function(tc.try_block.body, None, registers, next_var_id, ctx, &self_tb, Some(0)); let mut nextt_f = 1; for (fid, _) in &try_f.functions { if fid >= &nextt_f { diff --git a/src/errors.rs b/src/errors.rs index c77071c..1fe38ad 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -54,7 +54,7 @@ pub struct ASLError { pub code: String, } -fn convert_types_to_string(typ: &ErrorType) -> String { +pub fn convert_types_to_string(typ: &ErrorType) -> String { match typ { ErrorType::SyntaxError => String::from("Syntax Error: "), ErrorType::TypeError => String::from("Type Error: "), @@ -85,7 +85,7 @@ pub fn reverse_type_short(str: String) -> ErrorType { _ => panic!("Unknown error type short: {}", str), } } -fn convert_subtypes_to_string(stype: &ErrorSubType) -> String { +pub fn convert_subtypes_to_string(stype: &ErrorSubType) -> String { match stype { ErrorSubType::UnexpectedEnd => String::from("Unexpected end"), ErrorSubType::UnexpectedOperation => String::from("Unexpected operation"), diff --git a/src/main.rs b/src/main.rs index 7ead5cd..00e2567 100644 --- a/src/main.rs +++ b/src/main.rs @@ -143,11 +143,11 @@ fn main() { println!("Build successful. Took: {}ms", ntime.as_millis()); let decompiled = process(&compiled); let errcode_data: Vec<&str> = args[3].split(":").collect(); - if decompiled.func_count <= errcode_data[3].parse().unwrap() { + if decompiled.func_count <= errcode_data[2].parse().unwrap() { println!("Error code {} is invalid for this file.", args[3]); return; } - let func_ctx = contexts[errcode_data[3].parse::().unwrap()].clone(); + let func_ctx = contexts[errcode_data[2].parse::().unwrap()].clone(); let error = create_error("", errcode_data[3].parse().unwrap(), reverse_type_short(errcode_data[0].to_string()), reverse_subtype_short(errcode_data[1].to_string()), &func_ctx); print_error(&error, &func_ctx); return; diff --git a/src/virtualmachine.rs b/src/virtualmachine.rs index c02206d..34484fe 100644 --- a/src/virtualmachine.rs +++ b/src/virtualmachine.rs @@ -1,5 +1,5 @@ -use std::{any::Any, collections::HashMap, process, vec}; -use crate::{decompiler::{operation_to_name, process, DecompiledFunction, DecompiledOperation}, enviroment, errors::{create_error, print_error, ASLError, ErrorSubType, ErrorType}, Context}; +use std::{any::Any, collections::HashMap, vec}; +use crate::{decompiler::{operation_to_name, process, DecompiledFunction, DecompiledOperation}, enviroment, errors::{convert_subtypes_to_string, convert_types_to_string, create_error, print_error, ASLError, ErrorSubType, ErrorType}, Context}; #[derive(Debug, Clone)] pub enum VMMemory { @@ -184,22 +184,81 @@ fn set_var_id(var: &mut VMMemory, target: u32) { } } -fn do_operation_operation(registers: &mut Vec, memory: &mut Vec, operation: &DecompiledOperation, ctx: &Context) { - let reg_clone = registers.clone(); +fn fallback_to_catch(memory: &mut Vec, state: &mut VMState, functions: &mut Vec, call_stack: &mut Vec, executed_stack: &mut usize, executed_func: &DecompiledFunction, err: ASLError) { + call_stack.pop(); + if call_stack.len() < 1 { + *state = VMState::Finished; + return; + } + let catchf = match executed_func.functions.get(&executed_func.try_catch) { + Some(f) => f, + None => { + panic!("Try/Catch function not found!"); + } + }; + call_stack.push(CallStack { func: *catchf as usize, return_reg: 0, pc: 0 }); + *executed_stack = call_stack.len() - 1; + let func = &functions[*catchf as usize]; + let err_tbl: Vec = vec![ + TableValue { + key: VMMemory::String(VMMemoryString { value: String::from("message"), variable_id: 0 }), + value: VMMemory::String(VMMemoryString { value: err.message, variable_id: 0 }) + }, + TableValue { + key: VMMemory::String(VMMemoryString { value: String::from("position"), variable_id: 0 }), + value: VMMemory::Number(VMMemoryNumber { value: err.position as f64, variable_id: 0 }) + }, + TableValue { + key: VMMemory::String(VMMemoryString { value: String::from("type"), variable_id: 0 }), + value: VMMemory::String(VMMemoryString { value: convert_types_to_string(&err.typ), variable_id: 0 }) + }, + TableValue { + key: VMMemory::String(VMMemoryString { value: String::from("subtype"), variable_id: 0 }), + value: VMMemory::String(VMMemoryString { value: convert_subtypes_to_string(&err.subtype), variable_id: 0 }) + }, + TableValue { + key: VMMemory::String(VMMemoryString { value: String::from("code"), variable_id: 0 }), + value: VMMemory::String(VMMemoryString { value: err.code, variable_id: 0 }) + }, + ]; + if func.variables.len() < 1 || func.variables[0].start != 0 { + return; + } + memory.push(VMMemory::Table(VMMemoryTable { values: err_tbl, variable_id: func.variables[0].id })); +} + +fn do_operation_operation(machine: &mut Machine, operation: &DecompiledOperation, executed_stack: &mut usize, executed_func: &DecompiledFunction) { + let registers = &mut machine.registers; + let memory = &mut machine.memory; + let ctx = &machine.ctx[machine.call_stack[*executed_stack].func].clone(); + let func = machine.functions[machine.call_stack[*executed_stack].func].clone(); + let reg_clone: Vec = registers.clone(); let reg1 = get_register_by_id(®_clone, operation.arg1); let reg2 = get_register_by_id(®_clone, operation.arg2 as u8); let reg3 = get_register_by_id(®_clone, operation.arg3); if reg1.is_none() || reg2.is_none() || reg3.is_none() { let err = create_error(&format!("One or more registers not found for operation"), operation.pos, ErrorType::MachineError, ErrorSubType::RegisterNotFound, ctx); - print_error(&err, &ctx); - process::exit(1); + if func.try_catch > 0 { + fallback_to_catch(memory, &mut machine.state, &mut machine.functions, &mut machine.call_stack, executed_stack, executed_func, err); + return; + } else { + print_error(&err, &ctx); + machine.state = VMState::Error(err); + return; + } } let mem1 = reg1.unwrap().pointer; let mem2 = reg2.unwrap().pointer; if mem1 >= memory.len() || mem2 >= memory.len() || mem1 < 1 || mem2 < 1 { let err = create_error(&format!("Memory location out of bounds `{}` or `{}`", mem1, mem2), operation.pos, ErrorType::MachineError, ErrorSubType::MemoryOutOfBounds, ctx); - print_error(&err, &ctx); - process::exit(1); + if func.try_catch > 0 { + fallback_to_catch(memory, &mut machine.state, &mut machine.functions, &mut machine.call_stack, executed_stack, executed_func, err); + return; + } else { + print_error(&err, &ctx); + machine.state = VMState::Error(err); + return; + } } let mut result: VMMemory; match (&memory[mem1], &memory[mem2]) { @@ -217,8 +276,14 @@ fn do_operation_operation(registers: &mut Vec, memory: &mut Vec { if num2.value == 0.0 { let err = create_error(&format!("Division by zero"), operation.pos, ErrorType::MathError, ErrorSubType::DivisionByZero, ctx); - print_error(&err, &ctx); - process::exit(1); + if func.try_catch > 0 { + fallback_to_catch(memory, &mut machine.state, &mut machine.functions, &mut machine.call_stack, executed_stack, executed_func, err); + return; + } else { + print_error(&err, &ctx); + machine.state = VMState::Error(err); + return; + } } result = VMMemory::Number(VMMemoryNumber { value: num1.value / num2.value, variable_id: 0 }); }, @@ -248,8 +313,14 @@ fn do_operation_operation(registers: &mut Vec, memory: &mut Vec { let err = create_error(&format!("Unknown operation code for number operation: `{}`", operation.opcode), operation.pos, ErrorType::MachineError, ErrorSubType::UnknownOPCode, ctx); - print_error(&err, &ctx); - process::exit(1); + if func.try_catch > 0 { + fallback_to_catch(memory, &mut machine.state, &mut machine.functions, &mut machine.call_stack, executed_stack, executed_func, err); + return; + } else { + print_error(&err, &ctx); + machine.state = VMState::Error(err); + return; + } } }; }, @@ -266,8 +337,14 @@ fn do_operation_operation(registers: &mut Vec, memory: &mut Vec { let err = create_error(&format!("Unknown operation code for string operation: `{}`", operation.opcode), operation.pos, ErrorType::MachineError, ErrorSubType::UnknownOPCode, ctx); - print_error(&err, &ctx); - process::exit(1); + if func.try_catch > 0 { + fallback_to_catch(memory, &mut machine.state, &mut machine.functions, &mut machine.call_stack, executed_stack, executed_func, err); + return; + } else { + print_error(&err, &ctx); + machine.state = VMState::Error(err); + return; + } } }; }, @@ -287,8 +364,14 @@ fn do_operation_operation(registers: &mut Vec, memory: &mut Vec { let err = create_error(&format!("Unknown operation code for boolean operation: `{}`", operation.opcode), operation.pos, ErrorType::MachineError, ErrorSubType::UnknownOPCode, ctx); - print_error(&err, &ctx); - process::exit(1); + if func.try_catch > 0 { + fallback_to_catch(memory, &mut machine.state, &mut machine.functions, &mut machine.call_stack, executed_stack, executed_func, err); + return; + } else { + print_error(&err, &ctx); + machine.state = VMState::Error(err); + return; + } } }; }, @@ -302,15 +385,27 @@ fn do_operation_operation(registers: &mut Vec, memory: &mut Vec { let err = create_error(&format!("Unknown operation code for null operation: `{}`", operation.opcode), operation.pos, ErrorType::MachineError, ErrorSubType::UnknownOPCode, ctx); - print_error(&err, &ctx); - process::exit(1); + if func.try_catch > 0 { + fallback_to_catch(memory, &mut machine.state, &mut machine.functions, &mut machine.call_stack, executed_stack, executed_func, err); + return; + } else { + print_error(&err, &ctx); + machine.state = VMState::Error(err); + return; + } } }; }, _ => { let err = create_error(&format!("Wrong memory types for operation: `{}`, position: `{}` and `{}`", operation_to_name(operation.opcode), mem1, mem2), operation.pos, ErrorType::TypeError, ErrorSubType::WrongType, ctx); - print_error(&err, &ctx); - process::exit(1); + if func.try_catch > 0 { + fallback_to_catch(memory, &mut machine.state, &mut machine.functions, &mut machine.call_stack, executed_stack, executed_func, err); + return; + } else { + print_error(&err, &ctx); + machine.state = VMState::Error(err); + return; + } } } let mut reg3_pointer = reg3.unwrap().pointer; @@ -372,9 +467,7 @@ impl Machine { let executed_func = func_clone.get(self.call_stack[self.call_stack.len()-1].func); let mut executed_stack = self.call_stack.len()-1; if executed_func.is_none() { - let err = create_error(&format!("Current function not found"), 1, ErrorType::MachineError, ErrorSubType::UnknownFunction, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + panic!("Unable to resume VM, current function not found in function list"); } let mut executed_func = executed_func.unwrap(); self.state = VMState::Running; @@ -390,6 +483,7 @@ impl Machine { match operation.opcode { 0 => { //HLT + self.state = VMState::Finished; return; }, 1 => { @@ -397,8 +491,15 @@ impl Machine { let str = executed_func.strings.get(&(operation.arg2 as u32)); if str.is_none() { let err = create_error(&format!("String with ID `{}` not found", operation.arg2), operation.pos, ErrorType::MachineError, ErrorSubType::UnknownString, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } let str = str.unwrap(); self.memory.push(VMMemory::String(VMMemoryString { value: str.clone(), variable_id: 0 })); @@ -409,14 +510,28 @@ impl Machine { let mem = get_mem_pos_by_var_id(&self.memory, operation.arg2 as u32); if mem.is_none() { let err = create_error(&format!("Memory with variable ID `{}` not found", operation.arg2), operation.pos, ErrorType::MachineError, ErrorSubType::UnknownMemoryLocation, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } let mem = mem.unwrap(); if mem >= self.memory.len() || mem < 1 { let err = create_error(&format!("Memory location out of bounds for variable ID `{}`", operation.arg2), operation.pos, ErrorType::MachineError, ErrorSubType::MemoryOutOfBounds, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } let mut nmem = self.memory[mem].clone(); match &mut nmem { @@ -460,15 +575,29 @@ impl Machine { let func_pos = executed_func.functions.get(&(operation.arg2 as u32)); if func_pos.is_none() { let err = create_error(&format!("Function with ID `{}` not found", operation.arg2), operation.pos, ErrorType::MachineError, ErrorSubType::UnknownFunction, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } let func_pos = func_pos.unwrap(); let func = self.functions.get(*func_pos as usize); if func.is_none() { let err = create_error(&format!("Function with position `{}` not found", func_pos), operation.pos, ErrorType::MachineError, ErrorSubType::UnknownFunction, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } self.memory.push(VMMemory::Function(VMMemoryFunction { id: *func_pos as usize, @@ -491,14 +620,28 @@ impl Machine { let reg = get_register_by_id(&self.registers, operation.arg1); if reg.is_none() { let err = create_error(&format!("Register `{}` not found", operation.arg1), operation.pos, ErrorType::MachineError, ErrorSubType::RegisterNotFound, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } let reg = reg.unwrap(); if reg.pointer >= self.memory.len() || reg.pointer < 1 { let err = create_error(&format!("Register `{}` points to an invalid memory location", operation.arg1), operation.pos, ErrorType::MachineError, ErrorSubType::MemoryOutOfBounds, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } let used_var = get_mem_pos_by_var_id(&self.memory, operation.arg2 as u32); if let Some(pos) = used_var { @@ -516,14 +659,22 @@ impl Machine { let reg1 = get_register_by_id(&temp_regs, operation.arg1); if reg1.is_none() { let err = create_error(&format!("Register `{}` not found", operation.arg1), operation.pos, ErrorType::MachineError, ErrorSubType::RegisterNotFound, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } let reg1 = reg1.unwrap(); set_register(&mut self.registers, Register { id: operation.arg2 as u8, pointer: reg1.pointer }); }, 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 => { - do_operation_operation(&mut self.registers, &mut self.memory, operation, &self.ctx[self.call_stack[executed_stack].func].clone()); + do_operation_operation(self, operation, &mut executed_stack, executed_func); + executed_func = &func_clone[self.call_stack[executed_stack].func]; }, 24 => { //NOT @@ -532,14 +683,28 @@ impl Machine { let reg2 = get_register_by_id(®_clone, operation.arg2 as u8); if reg1.is_none() || reg2.is_none() { let err = create_error(&format!("Register `{}` or `{}` not found", operation.arg1, operation.arg2), operation.pos, ErrorType::MachineError, ErrorSubType::RegisterNotFound, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } let mem1 = reg1.unwrap().pointer; if mem1 >= self.memory.len() || mem1 < 1 { let err = create_error(&format!("Memory location out of bounds for register `{}`", operation.arg1), operation.pos, ErrorType::MachineError, ErrorSubType::MemoryOutOfBounds, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } let mut result: VMMemory; match &self.memory[mem1] { @@ -548,8 +713,15 @@ impl Machine { }, _ => { let err = create_error(&format!("Wrong memory type for NOT operation, position: `{}`", mem1), operation.pos, ErrorType::TypeError, ErrorSubType::WrongType, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } } let mut reg2_pointer = reg2.unwrap().pointer; @@ -571,15 +743,29 @@ impl Machine { let reg = get_register_by_id(&self.registers, operation.arg1); if reg.is_none() { let err = create_error(&format!("Register `{}` not found", operation.arg1), operation.pos, ErrorType::MachineError, ErrorSubType::RegisterNotFound, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } let reg = reg.unwrap(); let mem = self.memory.get(reg.pointer); if mem.is_none() { let err = create_error(&format!("Memory location not found for register `{}`", operation.arg1), operation.pos, ErrorType::MachineError, ErrorSubType::UnknownMemoryLocation, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } let mem = mem.unwrap(); match &mem { @@ -590,8 +776,15 @@ impl Machine { } _ => { let err = create_error(&format!("Wrong memory type for CJP operation, position: `{}`", reg.pointer), operation.pos, ErrorType::TypeError, ErrorSubType::WrongType, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } }, } }, @@ -600,15 +793,29 @@ impl Machine { let reg = get_register_by_id(&self.registers, operation.arg1); if reg.is_none() { let err = create_error(&format!("Register `{}` not found", operation.arg1), operation.pos, ErrorType::MachineError, ErrorSubType::RegisterNotFound, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } let reg = reg.unwrap(); let mem = self.memory.get(reg.pointer); if mem.is_none() { let err = create_error(&format!("Memory location not found for register `{}`", operation.arg1), operation.pos, ErrorType::MachineError, ErrorSubType::UnknownMemoryLocation, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } let mem = mem.unwrap().clone(); match mem { @@ -617,9 +824,7 @@ impl Machine { for i in &self.stack { let mut new_mem = i.clone(); if self.functions[func.id].variables.len() <= arg || self.functions[func.id].variables[arg].start != 0 { - let err = create_error(&format!("Too many arguments supplied for function: `{}`", func.id), operation.pos, ErrorType::SemanticError, ErrorSubType::TooManyArguments, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + break; } set_var_id(&mut new_mem, self.functions[func.id].variables[arg].id); self.memory.push(new_mem); @@ -635,8 +840,15 @@ impl Machine { 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, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } let mut ret_pointer = ret_reg.unwrap().pointer; if ret_pointer >= self.memory.len() || ret_pointer < 1 { @@ -652,8 +864,15 @@ impl Machine { }, _ => { let err = create_error(&format!("Unable to call non-function type"), operation.pos, ErrorType::MachineError, ErrorSubType::NonFunctionCall, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } } }, @@ -662,15 +881,29 @@ impl Machine { let reg = get_register_by_id(&self.registers, operation.arg1); if reg.is_none() { let err = create_error(&format!("Register `{}` not found", operation.arg1), operation.pos, ErrorType::MachineError, ErrorSubType::RegisterNotFound, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } let reg = reg.unwrap(); let mem = self.memory.get(reg.pointer); if mem.is_none() { let err = create_error(&format!("Memory location not found for register `{}`", operation.arg1), operation.pos, ErrorType::MachineError, ErrorSubType::MemoryOutOfBounds, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } let mem = mem.unwrap(); self.stack.push(mem.clone()); @@ -681,14 +914,28 @@ impl Machine { let ret_reg = get_register_by_id(&self.registers, operation.arg1); if target_reg.is_none() || ret_reg.is_none() { let err = create_error(&format!("Register `{}` or `{}` not found", self.call_stack[executed_stack].return_reg, operation.arg1), operation.pos, ErrorType::MachineError, ErrorSubType::RegisterNotFound, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } let ret_mem = self.memory.get(ret_reg.unwrap().pointer); if ret_mem.is_none() { let err = create_error(&format!("Memory location not found for register `{}`", operation.arg1), operation.pos, ErrorType::MachineError, ErrorSubType::MemoryOutOfBounds, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } let return_value = ret_mem.unwrap().clone(); let target_reg_pointer = self.memory.len(); @@ -697,6 +944,7 @@ impl Machine { self.memory[target_reg_pointer] = return_value; self.call_stack.pop(); if self.call_stack.len() < 1 { + self.state = VMState::Finished; return; } executed_stack = self.call_stack.len() - 1; @@ -711,14 +959,28 @@ impl Machine { let reg3 = get_register_by_id(®_clone, operation.arg3); if reg2.is_none() || reg3.is_none() { let err = create_error(&format!("Register `{}` or `{}` not found", operation.arg2, operation.arg3), operation.pos, ErrorType::MachineError, ErrorSubType::RegisterNotFound, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } let mem2 = self.memory.get(reg2.unwrap().pointer); if mem2.is_none() { let err = create_error(&format!("Memory location out of bounds for register `{}`", operation.arg2), operation.pos, ErrorType::MachineError, ErrorSubType::MemoryOutOfBounds, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } let mem2 = mem2.unwrap().clone(); let mut result: VMMemory; @@ -733,8 +995,15 @@ impl Machine { }, _ => { let err = create_error(&format!("Only string keys are allowed for GET enviroment"), operation.pos, ErrorType::TypeError, ErrorSubType::WrongType, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } } let mut reg3_pointer = reg3.unwrap().pointer; @@ -753,15 +1022,29 @@ impl Machine { let reg3 = get_register_by_id(®_clone, operation.arg3); if reg.is_none() || reg2.is_none() || reg3.is_none() { let err = create_error(&format!("Register `{}` or `{}` or `{}` not found", operation.arg1, operation.arg2, operation.arg3), operation.pos, ErrorType::MachineError, ErrorSubType::RegisterNotFound, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } let mem1 = self.memory.get(reg.unwrap().pointer); let mem2 = self.memory.get(reg2.unwrap().pointer); if mem1.is_none() || mem2.is_none() { let err = create_error(&format!("Memory location not found for register `{}` or `{}`", operation.arg1, operation.arg2), operation.pos, ErrorType::MachineError, ErrorSubType::MemoryOutOfBounds, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } let mem1 = mem1.unwrap().clone(); let mem2 = mem2.unwrap().clone(); @@ -777,8 +1060,15 @@ impl Machine { }, _ => { let err = create_error(&format!("Wrong memory type for GET operation, position: `{}`", reg.unwrap().pointer), operation.pos, ErrorType::TypeError, ErrorSubType::WrongType, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } } let mut reg3_pointer = reg3.unwrap().pointer; @@ -798,16 +1088,30 @@ impl Machine { let reg3 = get_register_by_id(&self.registers, operation.arg3); if reg.is_none() || reg2.is_none() || reg3.is_none() { let err = create_error(&format!("Register `{}` or `{}` or `{}` not found", operation.arg1, operation.arg2, operation.arg3), operation.pos, ErrorType::MachineError, ErrorSubType::RegisterNotFound, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } let mem1 = self.memory.get(reg.unwrap().pointer); let mem2 = self.memory.get(reg2.unwrap().pointer); let mem3 = self.memory.get(reg3.unwrap().pointer); if mem1.is_none() || mem2.is_none() || mem3.is_none() { let err = create_error(&format!("Memory location not found for register `{}` or `{}` or `{}`", operation.arg1, operation.arg2, operation.arg3), operation.pos, ErrorType::MachineError, ErrorSubType::MemoryOutOfBounds, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } let mem2 = mem2.unwrap().clone(); let mem3 = mem3.unwrap().clone(); @@ -818,15 +1122,29 @@ impl Machine { }, _ => { let err = create_error(&format!("Wrong memory type for SET operation, position: `{}`", reg.unwrap().pointer), operation.pos, ErrorType::TypeError, ErrorSubType::WrongType, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } } }, _ => { let err = create_error(&format!("Unknown operation code: `{}`", operation.opcode), operation.pos, ErrorType::MachineError, ErrorSubType::UnknownOPCode, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } } } diff --git a/test.asl b/test.asl index 60adf39..008de33 100644 --- a/test.asl +++ b/test.asl @@ -1,5 +1,8 @@ +gethelj a = 1 piszolj { + ugass(a) gethelj test = szaft"a"szaft+1 } csecs(err) { - ugass(szaft"Hibás bemb"szaft) -} \ No newline at end of file + ugass(szaft"Hibás bemb"szaft, err) +} +ugass(test) \ No newline at end of file From e583e3622eaa25a61b9a2e22dc2742a119199c76 Mon Sep 17 00:00:00 2001 From: afonya Date: Wed, 18 Jun 2025 14:31:30 +0200 Subject: [PATCH 10/19] added function argument errors back --- src/errors.rs | 4 ++++ src/virtualmachine.rs | 37 ++++++++++++++++++++++++++++++++++++- test.asl | 14 +++++++------- 3 files changed, 47 insertions(+), 8 deletions(-) diff --git a/src/errors.rs b/src/errors.rs index 1fe38ad..8238889 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -27,6 +27,7 @@ pub enum ErrorSubType { VariableAlreadyExists, ArgumentDuplication, TooManyArguments, + NotEnoughArguments, NoExpression, //Machine errors RegisterNotFound, @@ -112,6 +113,7 @@ pub fn convert_subtypes_to_string(stype: &ErrorSubType) -> String { ErrorSubType::FileError => String::from("File error"), ErrorSubType::RuntimeError => String::from("Runtime error"), ErrorSubType::NoExpression => String::from("No expression found"), + ErrorSubType::NotEnoughArguments => String::from("Not enough arguments"), } } fn convert_subtypes_to_short(stype: &ErrorSubType) -> String { @@ -141,6 +143,7 @@ fn convert_subtypes_to_short(stype: &ErrorSubType) -> String { ErrorSubType::FileError => String::from("FE:"), ErrorSubType::RuntimeError => String::from("RE:"), ErrorSubType::NoExpression => String::from("NE:"), + ErrorSubType::NotEnoughArguments => String::from("NA:"), } } pub fn reverse_subtype_short(str: String) -> ErrorSubType { @@ -170,6 +173,7 @@ pub fn reverse_subtype_short(str: String) -> ErrorSubType { "FE" => ErrorSubType::FileError, "RE" => ErrorSubType::RuntimeError, "NE" => ErrorSubType::NoExpression, + "NA" => ErrorSubType::NotEnoughArguments, _ => panic!("Unknown error subtype short: {}", str), } } diff --git a/src/virtualmachine.rs b/src/virtualmachine.rs index 34484fe..757dcc3 100644 --- a/src/virtualmachine.rs +++ b/src/virtualmachine.rs @@ -821,15 +821,50 @@ impl Machine { match mem { VMMemory::Function(func) => { let arg = 0; + let mut nocon = false; for i in &self.stack { let mut new_mem = i.clone(); if self.functions[func.id].variables.len() <= arg || self.functions[func.id].variables[arg].start != 0 { - break; + let err = create_error(&format!("Too many arguments supplied for function: `{}`", func.id), operation.pos, ErrorType::SemanticError, ErrorSubType::TooManyArguments, &self.ctx[self.call_stack[executed_stack].func].clone()); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + nocon = true; + break; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } set_var_id(&mut new_mem, self.functions[func.id].variables[arg].id); self.memory.push(new_mem); } + for arg in &self.functions[func.id].variables { + if arg.start != 0 { + break; + } + match get_mem_pos_by_var_id(&self.memory, arg.id) { + None => { + let err = create_error(&format!("Not enough arguments supplied for function: `{}`", func.id), operation.pos, ErrorType::SemanticError, ErrorSubType::NotEnoughArguments, &self.ctx[self.call_stack[executed_stack].func].clone()); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + nocon = true; + break; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } + }, + _ => {} + } + } self.stack.clear(); + if nocon { + continue; + } self.call_stack.push(CallStack { func: func.id, return_reg: operation.arg2 as usize, pc: 0 }); executed_func = &func_clone[func.id]; diff --git a/test.asl b/test.asl index 008de33..451416f 100644 --- a/test.asl +++ b/test.asl @@ -1,8 +1,8 @@ -gethelj a = 1 -piszolj { - ugass(a) - gethelj test = szaft"a"szaft+1 -} csecs(err) { - ugass(szaft"Hibás bemb"szaft, err) +lőcsve test(a,b) { + ugass(a,b) } -ugass(test) \ No newline at end of file +piszolj { + test(0) +} csecs (e) { + ugass(e) +} \ No newline at end of file From c626af7cd4e34dc5643b4639e2103aa716598d0b Mon Sep 17 00:00:00 2001 From: afonya Date: Wed, 18 Jun 2025 14:34:57 +0200 Subject: [PATCH 11/19] Update the documentation --- docs/docs/langfunctions.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/docs/docs/langfunctions.md b/docs/docs/langfunctions.md index 13562ad..72244b1 100644 --- a/docs/docs/langfunctions.md +++ b/docs/docs/langfunctions.md @@ -275,4 +275,27 @@ gethelj a = {1,2,3} ugass(a[0]) // 1 a[0] = 12 ugass(a[0]) // 12 +``` + +--- + +## Try/Catch (Próbáld ki) +Kulcsszó: `piszolj, csecs` + +Használat: `piszolj {amit ki kell próbálni} csecs (error) {ha hiba}` + +:::warning + +A catch rész itt nem rakható bárhova, nem úgy mint az if-nél! + +::: + +Példa: +```asl title="example.asl" +piszolj { + gethelj test = szaft"a"szaft+1 +} csecs (e) { + //Ez akkor fog lefutni, mikor hiba van + ugass(e) +} ``` \ No newline at end of file From 17ffb11f344735377acb51733c77a21ad2e043e5 Mon Sep 17 00:00:00 2001 From: afonya Date: Wed, 18 Jun 2025 14:46:59 +0200 Subject: [PATCH 12/19] prepare for coroutine --- src/compiler.rs | 18 +++---- src/enviroment.rs | 2 +- src/errors.rs | 12 +++-- src/lexer.rs | 4 +- src/main.rs | 34 +++++++++++-- src/parser.rs | 112 +++++++++++++++++++++--------------------- src/virtualmachine.rs | 46 +---------------- test.asl | 9 +--- 8 files changed, 107 insertions(+), 130 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index 45425fb..82508a3 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -310,7 +310,7 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec, va ASTPart::Else(else_part) => { if get_variable_by_name(variables, "__LASTIF", ops.len(), traceback).is_none() { let err = create_error(&format!("Else used without an if statement before it"), else_part.pos, ErrorType::SemanticError, ErrorSubType::ElseWithoutIf, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); } let reg = get_register_by_variable(registers, get_variable_by_name(variables, "__LASTIF", ops.len(), traceback).expect("__LASTIF should exist").clone()); @@ -358,7 +358,7 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec, va ASTPart::ElseIf(elseif_part) => { if get_variable_by_name(variables, "__LASTIF", ops.len(), traceback).is_none() { let err = create_error(&format!("Else if used without an if statement before it"), elseif_part.pos, ErrorType::SemanticError, ErrorSubType::ElseWithoutIf, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); } let reg = get_register_by_variable(registers, get_variable_by_name(variables, "__LASTIF", ops.len(), traceback).expect("__LASTIF should exist").clone()); @@ -472,12 +472,12 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec, va }, ASTPart::Break(brk) => { let err = create_error(&format!("Unexpected break outside of loop"), brk.pos, ErrorType::SemanticError, ErrorSubType::BreakContinueWithoutLoop, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); }, ASTPart::Continue(cont) => { let err = create_error(&format!("Unexpected continue outside of loop"), cont.pos, ErrorType::SemanticError, ErrorSubType::BreakContinueWithoutLoop, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); }, ASTPart::For(for_part) => { @@ -575,7 +575,7 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec, va }, _ => { let err = create_error(&format!("Unknown operator `{}`", op.operator), op.pos, ErrorType::SyntaxError, ErrorSubType::UnknownOperation, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); }, }; @@ -586,7 +586,7 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec, va ASTPart::VarUpdate(upd) => { if get_variable_by_name(variables, &upd.variable, ops.len(), traceback).is_none() { let err = create_error(&format!("Variable `{}` does not exist", upd.variable), upd.pos, ErrorType::SemanticError, ErrorSubType::VariableNotFound, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); } 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, traceback); @@ -602,7 +602,7 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec, va ASTPart::Assigment(asign) => { if get_variable_by_name(variables, &asign.variable, ops.len(), traceback).is_some() { let err = create_error(&format!("Variable `{}` already exists", asign.variable), asign.pos, ErrorType::SemanticError, ErrorSubType::VariableAlreadyExists, ctx); - print_error(&err, &ctx); + print_error(&err); 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, ctx, traceback); @@ -673,7 +673,7 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec, va }, Err(e) => { let err = create_error(&format!("Failed to read file `{}`: {}", impr.path, e), impr.pos, ErrorType::IOError, ErrorSubType::FileError, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); } } @@ -727,7 +727,7 @@ fn compile_function(ast: Vec, args: Option>, registers: &mu for arg in arg_list { if get_variable_by_name(&variables, &arg, 0, &empty_tb).is_some() { let err = create_error(&format!("Argument `{}` already exists", arg), 0, ErrorType::SemanticError, ErrorSubType::ArgumentDuplication, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); } variables.push( Variable { name: arg, id: *next_var_id, start: 0, end: 0, no_end: true }); diff --git a/src/enviroment.rs b/src/enviroment.rs index 57a2488..c33fff6 100644 --- a/src/enviroment.rs +++ b/src/enviroment.rs @@ -61,7 +61,7 @@ fn error(msg: String, machine: &Machine, op: &DecompiledOperation) { let curr = machine.call_stack.len()-1; let func = machine.call_stack[curr].func; let err = create_error(&msg, op.pos, ErrorType::MachineError, ErrorSubType::RuntimeError, &machine.ctx[func]); - print_error(&err, &machine.ctx[func]); + print_error(&err); process::exit(1); } fn set_mem_tbl_val(tbl: &mut VMMemoryTable, key: VMMemory, value: VMMemory) { diff --git a/src/errors.rs b/src/errors.rs index 8238889..30b51d6 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -53,6 +53,7 @@ pub struct ASLError { pub typ: ErrorType, pub subtype: ErrorSubType, pub code: String, + ctx: Context } pub fn convert_types_to_string(typ: &ErrorType) -> String { @@ -190,6 +191,7 @@ pub fn create_error(message: &str, position: usize, typ: ErrorType, stype: Error typ, subtype: stype, code, + ctx: ctx.clone() } } @@ -232,7 +234,7 @@ fn get_sorrunding_lines(file: &String, line: usize) -> (String, String, String) (before, current, after) } -pub fn print_error(error: &ASLError, ctx: &Context) { +pub fn print_error(error: &ASLError) { let mut out = String::new(); out.push_str(&convert_types_to_string(&error.typ)); if error.message.len() < 1 { @@ -241,18 +243,18 @@ pub fn print_error(error: &ASLError, ctx: &Context) { out.push_str(&error.message); } - if ctx.known { + if error.ctx.known { out.push_str(" at position "); - let (line, column) = get_exact_pos(&ctx.raw_file, error.position); - out.push_str(&ctx.file); + let (line, column) = get_exact_pos(&error.ctx.raw_file, error.position); + out.push_str(&error.ctx.file); out.push_str(":"); out.push_str(&line.to_string()); out.push_str(":"); out.push_str(&column.to_string()); out.push_str("\n"); - let (before, current, after) = get_sorrunding_lines(&ctx.raw_file, line); + let (before, current, after) = get_sorrunding_lines(&error.ctx.raw_file, line); if line > 1 { out.push_str(&(line-1).to_string()); out.push_str(" | "); diff --git a/src/lexer.rs b/src/lexer.rs index 5fbd48e..22fb976 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -71,7 +71,7 @@ fn read_string(splitted: &Vec<&str>, pos: &mut usize, out: &mut Vec, ctx: } if !success { let err = create_error("Unexpected end of string", *pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); } *pos += 5; @@ -95,7 +95,7 @@ fn read_comment(splitted: &Vec<&str>, pos: &mut usize, is_multiline: bool, ctx: } if !success { let err = create_error("Unexpected end of comment", *pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); } *pos += 1; diff --git a/src/main.rs b/src/main.rs index 00e2567..4d14a0b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,6 @@ use std::{env, fs, time::Instant}; use virtualmachine::Machine; -use crate::{decompiler::{operation_to_name, process}, errors::{create_error, print_error, reverse_subtype_short, reverse_type_short}}; +use crate::{decompiler::{operation_to_name, process}, errors::{create_error, print_error, reverse_subtype_short, reverse_type_short}, virtualmachine::VMState}; mod lexer; mod parser; @@ -12,7 +12,7 @@ mod decompiler; const CLIVER: [u8; 3] = [0, 3, 0]; -#[derive(Clone)] +#[derive(Debug, Clone)] struct Context { file: String, raw_file: String, @@ -59,7 +59,19 @@ fn main() { println!("Build successful. Took: {}ms", ntime.as_millis()); let mut vm = Machine::new(contexts); vm.load(&compiled); - vm.resume(); + while let VMState::Paused = vm.state { + vm.resume(); + } + match vm.state { + VMState::Finished => { + println!("Execution finished successfully."); + }, + VMState::Error(err) => { + print_error(&err); + panic!("Execution failed with an error."); + }, + _ => {} + } }, Result::Err(err) => { panic!("Can't read file: {}", err); @@ -76,7 +88,19 @@ fn main() { } let mut vm = Machine::new(contexts); vm.load(&data); - vm.resume(); + while let VMState::Paused = vm.state { + vm.resume(); + } + match vm.state { + VMState::Finished => { + println!("Execution finished successfully."); + }, + VMState::Error(err) => { + print_error(&err); + panic!("Execution failed with an error."); + }, + _ => {} + } }, Result::Err(err) => { panic!("Can't read file: {}", err); @@ -149,7 +173,7 @@ fn main() { } let func_ctx = contexts[errcode_data[2].parse::().unwrap()].clone(); let error = create_error("", errcode_data[3].parse().unwrap(), reverse_type_short(errcode_data[0].to_string()), reverse_subtype_short(errcode_data[1].to_string()), &func_ctx); - print_error(&error, &func_ctx); + print_error(&error); return; }, Result::Err(err) => { diff --git a/src/parser.rs b/src/parser.rs index e312670..e52fee6 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -278,7 +278,7 @@ fn shunt(input: Vec, ctx: &Context) -> ASTPart { println!("{:?}", output); if i < 1 { let err = create_error(&format!("Unexpected operation `{}`", op.operator), op.pos, ErrorType::SemanticError, ErrorSubType::UnexpectedOperation, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); } let left = output[i-1].clone(); @@ -292,7 +292,7 @@ fn shunt(input: Vec, ctx: &Context) -> ASTPart { } else { if i < 2 { let err = create_error(&format!("Unexpected operation `{}`", op.operator), op.pos, ErrorType::SemanticError, ErrorSubType::UnexpectedOperation, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); } let left = output[i-2].clone(); @@ -315,7 +315,7 @@ fn shunt(input: Vec, ctx: &Context) -> ASTPart { } if output.len() == 0 { let err = create_error(&format!("No expressions found after applying order of operations"), 0, ErrorType::SemanticError, ErrorSubType::NoExpression, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); } return output[0].clone(); @@ -326,7 +326,7 @@ fn read_function(input: &Vec, pos: &mut usize, with_args: bool, ctx: &Con if with_args { if input[*pos].typ != TokenType::SEPARATOR || input[*pos].value != "(" { let err = create_error(&format!("Expected `(`"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::Expected, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); } *pos += 1; @@ -343,20 +343,20 @@ fn read_function(input: &Vec, pos: &mut usize, with_args: bool, ctx: &Con args.push(token.value.clone()); } else { let err = create_error(&format!("Unexpected `{:?}({})`", token.typ, token.value), token.pos, ErrorType::SyntaxError, ErrorSubType::Unexpected, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); } } if input[*pos].typ != TokenType::SEPARATOR || input[*pos].value != ")" { let err = create_error(&format!("Unexpected end of arguments"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); } *pos += 1; } if input[*pos].typ != TokenType::SEPARATOR || input[*pos].value != "{" { let err = create_error(&format!("Expected {{"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::Expected, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); } *pos += 1; @@ -371,7 +371,7 @@ fn read_function(input: &Vec, pos: &mut usize, with_args: bool, ctx: &Con let body = parse_internal(input, &op_ends, &parse_ends, pos, ctx); if input[*pos].typ != TokenType::SEPARATOR || input[*pos].value != "}" { let err = create_error(&format!("Unexpected end of function"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); } *pos += 1; @@ -404,25 +404,25 @@ fn read_table(input: &Vec, pos: &mut usize, ctx: &Context) -> ASTPart { match keyy { ASTPart::Table(_) => { let err = create_error(&format!("Table keys cannot be tables"), input[*pos].pos, ErrorType::SemanticError, ErrorSubType::InvalidTableKeys, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); }, ASTPart::Function(_) => { let err = create_error(&format!("Table keys cannot be functions"), input[*pos].pos, ErrorType::SemanticError, ErrorSubType::InvalidTableKeys, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); }, _ => {} } if input[*pos].typ != TokenType::SEPARATOR || input[*pos].value != "]" { let err = create_error(&format!("Unexpected end of key"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); } *pos += 1; if input[*pos].typ != TokenType::SEPARATOR || input[*pos].value != "=" { let err = create_error(&format!("Expected `=` after key"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::Expected, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); } *pos += 1; @@ -444,7 +444,7 @@ fn read_table(input: &Vec, pos: &mut usize, ctx: &Context) -> ASTPart { continue; } else { let err = create_error(&format!("Unexpected end of table"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); } } @@ -504,7 +504,7 @@ fn read_exp(pos: &mut usize, input: &Vec, ends: &Vec, parse_ends: expressions.push(func); } else { let err = create_error(&format!("Unexpected `{:?}({})`", token.typ, token.value), token.pos, ErrorType::SyntaxError, ErrorSubType::Unexpected, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); } } else if token.typ == TokenType::IDENTIFIER { @@ -522,19 +522,19 @@ fn read_exp(pos: &mut usize, input: &Vec, ends: &Vec, parse_ends: match keyy { ASTPart::Table(_) => { let err = create_error(&format!("Table keys cannot be tables"), input[*pos].pos, ErrorType::SemanticError, ErrorSubType::InvalidTableKeys, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); }, ASTPart::Function(_) => { let err = create_error(&format!("Table keys cannot be functions"), input[*pos].pos, ErrorType::SemanticError, ErrorSubType::InvalidTableKeys, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); }, _ => {} } if input[*pos].typ != TokenType::SEPARATOR || input[*pos].value != "]" { let err = create_error(&format!("Unexpected end of key"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); } *pos += 1; @@ -546,7 +546,7 @@ fn read_exp(pos: &mut usize, input: &Vec, ends: &Vec, parse_ends: let keyy = &input[*pos]; if keyy.typ != TokenType::IDENTIFIER { let err = create_error(&format!("Expected identifier after `.`"), keyy.pos, ErrorType::SyntaxError, ErrorSubType::Expected, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); } *pos += 1; @@ -568,7 +568,7 @@ fn read_exp(pos: &mut usize, input: &Vec, ends: &Vec, parse_ends: *pos += 1; } else { let err = create_error(&format!("Unclosed parenthesis"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::Unclosed, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); } expressions.push(exp); @@ -577,12 +577,12 @@ fn read_exp(pos: &mut usize, input: &Vec, ends: &Vec, parse_ends: expressions.push(tbl); } else { let err = create_error(&format!("Unexpected `{:?}({})`", token.typ, token.value), token.pos, ErrorType::SyntaxError, ErrorSubType::Unexpected, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); } } else { let err = create_error(&format!("Unexpected `{:?}({})`", token.typ, token.value), token.pos, ErrorType::SyntaxError, ErrorSubType::Unexpected, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); } } @@ -612,19 +612,19 @@ fn check_continue(pos: &mut usize, input: &Vec, prev: ASTPart, op_ends: & match keyy { ASTPart::Table(_) => { let err = create_error(&format!("Table keys cannot be tables"), input[*pos].pos, ErrorType::SemanticError, ErrorSubType::InvalidTableKeys, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); }, ASTPart::Function(_) => { let err = create_error(&format!("Table keys cannot be functions"), input[*pos].pos, ErrorType::SemanticError, ErrorSubType::InvalidTableKeys, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); }, _ => {} } if input[*pos].typ != TokenType::SEPARATOR || input[*pos].value != "]" { let err = create_error(&format!("Unexpected end of key"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); } *pos += 1; @@ -636,7 +636,7 @@ fn check_continue(pos: &mut usize, input: &Vec, prev: ASTPart, op_ends: & let keyy = &input[*pos]; if keyy.typ != TokenType::IDENTIFIER { let err = create_error(&format!("Expected identifier after `.`"), keyy.pos, ErrorType::SyntaxError, ErrorSubType::Expected, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); } *pos += 1; @@ -669,7 +669,7 @@ fn next_operation(pos: &mut usize, input: &Vec, op_ends: &Vec, par *pos += 1; if variable.typ != TokenType::IDENTIFIER { let err = create_error(&format!("Unexpected `{:?}`", variable.typ,), token.pos, ErrorType::SyntaxError, ErrorSubType::Unexpected, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); } let eq = &input[*pos]; @@ -681,7 +681,7 @@ fn next_operation(pos: &mut usize, input: &Vec, op_ends: &Vec, par } else if token.value == "ha geny" { if next_token.typ != TokenType::SEPARATOR || next_token.value != "(" { let err = create_error(&format!("Expected `(`"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); } *pos += 1; @@ -691,7 +691,7 @@ fn next_operation(pos: &mut usize, input: &Vec, op_ends: &Vec, par let condition = read_exp(pos, input, &condition_end, &condition_end, ctx); if input[*pos].typ != TokenType::SEPARATOR || input[*pos].value != ")" { let err = create_error(&format!("Unexpected end of condition"), token.pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); } *pos += 1; @@ -700,7 +700,7 @@ fn next_operation(pos: &mut usize, input: &Vec, op_ends: &Vec, par ASTPart::Function(func) => func.body, _ => { let err = create_error(&format!("Expected function body"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); } }; @@ -708,7 +708,7 @@ fn next_operation(pos: &mut usize, input: &Vec, op_ends: &Vec, par } else if token.value == "amíg geny" { if next_token.typ != TokenType::SEPARATOR || next_token.value != "(" { let err = create_error(&format!("Expected `(`"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); } *pos += 1; @@ -718,7 +718,7 @@ fn next_operation(pos: &mut usize, input: &Vec, op_ends: &Vec, par let condition = read_exp(pos, input, &condition_end, &condition_end, ctx); if input[*pos].typ != TokenType::SEPARATOR || input[*pos].value != ")" { let err = create_error(&format!("Unexpected end of condition"), token.pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); } *pos += 1; @@ -727,7 +727,7 @@ fn next_operation(pos: &mut usize, input: &Vec, op_ends: &Vec, par ASTPart::Function(func) => func.body, _ => { let err = create_error(&format!("Expected function body"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); } }; @@ -737,7 +737,7 @@ fn next_operation(pos: &mut usize, input: &Vec, op_ends: &Vec, par } else if token.value == "kopva" { if next_token.typ != TokenType::SEPARATOR || next_token.value != "(" { let err = create_error(&format!("Expected `(`"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); } *pos += 1; @@ -748,31 +748,31 @@ fn next_operation(pos: &mut usize, input: &Vec, op_ends: &Vec, par let init = parse_internal(input, &ends, &ends, pos, ctx); if init.len() != 1 { let err = create_error(&format!("Only one expression is expected for init"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); } if input[*pos].typ != TokenType::OPEND || input[*pos].value != ";" { let err = create_error(&format!("Unexpected end of init"), token.pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); } *pos += 1; let condition = read_exp(pos, input, &ends, &ends, ctx); if input[*pos].typ != TokenType::OPEND || input[*pos].value != ";" { let err = create_error(&format!("Unexpected end of condition"), token.pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); } *pos += 1; let update = parse_internal(input, &ends, &ends, pos, ctx); if update.len() != 1 { let err = create_error(&format!("Only one expression is expected for update"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); } if input[*pos].typ != TokenType::SEPARATOR || input[*pos].value != ")" { let err = create_error(&format!("Unexpected end of update"), token.pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); } *pos += 1; @@ -781,7 +781,7 @@ fn next_operation(pos: &mut usize, input: &Vec, op_ends: &Vec, par ASTPart::Function(func) => func.body, _ => { let err = create_error(&format!("Expected function body"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); } }; @@ -791,7 +791,7 @@ fn next_operation(pos: &mut usize, input: &Vec, op_ends: &Vec, par } else if token.value == "ha nem geny akkor geny" { if next_token.typ != TokenType::SEPARATOR || next_token.value != "(" { let err = create_error(&format!("Expected `(`"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); } *pos += 1; @@ -801,7 +801,7 @@ fn next_operation(pos: &mut usize, input: &Vec, op_ends: &Vec, par let condition = read_exp(pos, input, &condition_end, &condition_end, ctx); if input[*pos].typ != TokenType::SEPARATOR || input[*pos].value != ")" { let err = create_error(&format!("Unexpected end of condition"), token.pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); } *pos += 1; @@ -810,7 +810,7 @@ fn next_operation(pos: &mut usize, input: &Vec, op_ends: &Vec, par ASTPart::Function(func) => func.body, _ => { let err = create_error(&format!("Expected function body"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); } }; @@ -821,7 +821,7 @@ fn next_operation(pos: &mut usize, input: &Vec, op_ends: &Vec, par ASTPart::Function(func) => func.body, _ => { let err = create_error(&format!("Expected function body"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); } }; @@ -838,19 +838,19 @@ fn next_operation(pos: &mut usize, input: &Vec, op_ends: &Vec, par *pos += 1; if var.typ != TokenType::IDENTIFIER { let err = create_error(&format!("Expected identifier after hámozd"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); } if input[*pos].typ != TokenType::KEYWORD || (input[*pos].value != "be" && input[*pos].value != "ba") { let err = create_error(&format!("Expected `be`/`ba` after hámozd"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::Expected, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); } *pos += 1; let path = &input[*pos]; if path.typ != TokenType::STRING { let err = create_error(&format!("Expected string for hámozd"), path.pos, ErrorType::SyntaxError, ErrorSubType::Expected, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); } *pos += 1; @@ -870,13 +870,13 @@ fn next_operation(pos: &mut usize, input: &Vec, op_ends: &Vec, par ASTPart::Function(f) => f, _ => { let err = create_error(&format!("Expected function body"), token.pos, ErrorType::SyntaxError, ErrorSubType::Expected, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); } }; if input[*pos].typ != TokenType::KEYWORD || input[*pos].value != "csecs" { let err = create_error(&format!("Expected `csecs` after piszolj"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::Expected, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); } *pos += 1; @@ -885,14 +885,14 @@ fn next_operation(pos: &mut usize, input: &Vec, op_ends: &Vec, par ASTPart::Function(f) => f, _ => { let err = create_error(&format!("Expected function body"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::Expected, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); } }; return ASTPart::TryCatch(AstTryCatch { try_block: tryp, catch_block: catchp, pos: token.pos }); } else { let err = create_error(&format!("Unexpected `{:?}({})`", token.typ, token.value), token.pos, ErrorType::SyntaxError, ErrorSubType::Unexpected, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); } } else if token.typ == TokenType::IDENTIFIER { @@ -906,7 +906,7 @@ fn next_operation(pos: &mut usize, input: &Vec, op_ends: &Vec, par let keyy = &input[*pos]; if keyy.typ != TokenType::IDENTIFIER { let err = create_error(&format!("Expected identifier after `.`"), keyy.pos, ErrorType::SyntaxError, ErrorSubType::Expected, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); } *pos += 1; @@ -921,19 +921,19 @@ fn next_operation(pos: &mut usize, input: &Vec, op_ends: &Vec, par match keyy { ASTPart::Table(_) => { let err = create_error(&format!("Table keys cannot be tables"), input[*pos].pos, ErrorType::SemanticError, ErrorSubType::InvalidTableKeys, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); }, ASTPart::Function(_) => { let err = create_error(&format!("Table keys cannot be functions"), input[*pos].pos, ErrorType::SemanticError, ErrorSubType::InvalidTableKeys, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); }, _ => {} } if input[*pos].typ != TokenType::SEPARATOR || input[*pos].value != "]" { let err = create_error(&format!("Unexpected end of key"), input[*pos].pos, ErrorType::SyntaxError, ErrorSubType::UnexpectedEnd, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); } *pos += 1; @@ -951,12 +951,12 @@ fn next_operation(pos: &mut usize, input: &Vec, op_ends: &Vec, par return ASTPart::VarUpdate(AstVarUpdate { variable: token.value.clone(), value: Box::new(value), pos: token.pos }); } else { let err = create_error(&format!("Unexpected `{:?}({})`", token.typ, token.value), token.pos, ErrorType::SyntaxError, ErrorSubType::Unexpected, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); } } else { let err = create_error(&format!("Unexpected `{:?}({})`", token.typ, token.value), token.pos, ErrorType::SyntaxError, ErrorSubType::Unexpected, ctx); - print_error(&err, &ctx); + print_error(&err); process::exit(1); } } diff --git a/src/virtualmachine.rs b/src/virtualmachine.rs index 757dcc3..efbb4aa 100644 --- a/src/virtualmachine.rs +++ b/src/virtualmachine.rs @@ -1,5 +1,5 @@ use std::{any::Any, collections::HashMap, vec}; -use crate::{decompiler::{operation_to_name, process, DecompiledFunction, DecompiledOperation}, enviroment, errors::{convert_subtypes_to_string, convert_types_to_string, create_error, print_error, ASLError, ErrorSubType, ErrorType}, Context}; +use crate::{decompiler::{operation_to_name, process, DecompiledFunction, DecompiledOperation}, enviroment, errors::{convert_subtypes_to_string, convert_types_to_string, create_error, ASLError, ErrorSubType, ErrorType}, Context}; #[derive(Debug, Clone)] pub enum VMMemory { @@ -65,7 +65,7 @@ pub struct CallStack { } #[derive(Debug, Clone)] -enum VMState { +pub enum VMState { Running, Paused, Finished, @@ -242,7 +242,6 @@ fn do_operation_operation(machine: &mut Machine, operation: &DecompiledOperation fallback_to_catch(memory, &mut machine.state, &mut machine.functions, &mut machine.call_stack, executed_stack, executed_func, err); return; } else { - print_error(&err, &ctx); machine.state = VMState::Error(err); return; } @@ -255,7 +254,6 @@ fn do_operation_operation(machine: &mut Machine, operation: &DecompiledOperation fallback_to_catch(memory, &mut machine.state, &mut machine.functions, &mut machine.call_stack, executed_stack, executed_func, err); return; } else { - print_error(&err, &ctx); machine.state = VMState::Error(err); return; } @@ -280,7 +278,6 @@ fn do_operation_operation(machine: &mut Machine, operation: &DecompiledOperation fallback_to_catch(memory, &mut machine.state, &mut machine.functions, &mut machine.call_stack, executed_stack, executed_func, err); return; } else { - print_error(&err, &ctx); machine.state = VMState::Error(err); return; } @@ -317,7 +314,6 @@ fn do_operation_operation(machine: &mut Machine, operation: &DecompiledOperation fallback_to_catch(memory, &mut machine.state, &mut machine.functions, &mut machine.call_stack, executed_stack, executed_func, err); return; } else { - print_error(&err, &ctx); machine.state = VMState::Error(err); return; } @@ -341,7 +337,6 @@ fn do_operation_operation(machine: &mut Machine, operation: &DecompiledOperation fallback_to_catch(memory, &mut machine.state, &mut machine.functions, &mut machine.call_stack, executed_stack, executed_func, err); return; } else { - print_error(&err, &ctx); machine.state = VMState::Error(err); return; } @@ -368,7 +363,6 @@ fn do_operation_operation(machine: &mut Machine, operation: &DecompiledOperation fallback_to_catch(memory, &mut machine.state, &mut machine.functions, &mut machine.call_stack, executed_stack, executed_func, err); return; } else { - print_error(&err, &ctx); machine.state = VMState::Error(err); return; } @@ -389,7 +383,6 @@ fn do_operation_operation(machine: &mut Machine, operation: &DecompiledOperation fallback_to_catch(memory, &mut machine.state, &mut machine.functions, &mut machine.call_stack, executed_stack, executed_func, err); return; } else { - print_error(&err, &ctx); machine.state = VMState::Error(err); return; } @@ -402,7 +395,6 @@ fn do_operation_operation(machine: &mut Machine, operation: &DecompiledOperation fallback_to_catch(memory, &mut machine.state, &mut machine.functions, &mut machine.call_stack, executed_stack, executed_func, err); return; } else { - print_error(&err, &ctx); machine.state = VMState::Error(err); return; } @@ -496,7 +488,6 @@ impl Machine { executed_func = &func_clone[self.call_stack[executed_stack].func]; continue; } else { - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); self.state = VMState::Error(err); return; } @@ -515,7 +506,6 @@ impl Machine { executed_func = &func_clone[self.call_stack[executed_stack].func]; continue; } else { - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); self.state = VMState::Error(err); return; } @@ -528,7 +518,6 @@ impl Machine { executed_func = &func_clone[self.call_stack[executed_stack].func]; continue; } else { - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); self.state = VMState::Error(err); return; } @@ -580,7 +569,6 @@ impl Machine { executed_func = &func_clone[self.call_stack[executed_stack].func]; continue; } else { - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); self.state = VMState::Error(err); return; } @@ -594,7 +582,6 @@ impl Machine { executed_func = &func_clone[self.call_stack[executed_stack].func]; continue; } else { - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); self.state = VMState::Error(err); return; } @@ -625,7 +612,6 @@ impl Machine { executed_func = &func_clone[self.call_stack[executed_stack].func]; continue; } else { - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); self.state = VMState::Error(err); return; } @@ -638,7 +624,6 @@ impl Machine { executed_func = &func_clone[self.call_stack[executed_stack].func]; continue; } else { - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); self.state = VMState::Error(err); return; } @@ -664,7 +649,6 @@ impl Machine { executed_func = &func_clone[self.call_stack[executed_stack].func]; continue; } else { - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); self.state = VMState::Error(err); return; } @@ -688,7 +672,6 @@ impl Machine { executed_func = &func_clone[self.call_stack[executed_stack].func]; continue; } else { - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); self.state = VMState::Error(err); return; } @@ -701,7 +684,6 @@ impl Machine { executed_func = &func_clone[self.call_stack[executed_stack].func]; continue; } else { - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); self.state = VMState::Error(err); return; } @@ -718,7 +700,6 @@ impl Machine { executed_func = &func_clone[self.call_stack[executed_stack].func]; continue; } else { - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); self.state = VMState::Error(err); return; } @@ -748,7 +729,6 @@ impl Machine { executed_func = &func_clone[self.call_stack[executed_stack].func]; continue; } else { - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); self.state = VMState::Error(err); return; } @@ -762,7 +742,6 @@ impl Machine { executed_func = &func_clone[self.call_stack[executed_stack].func]; continue; } else { - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); self.state = VMState::Error(err); return; } @@ -781,7 +760,6 @@ impl Machine { executed_func = &func_clone[self.call_stack[executed_stack].func]; continue; } else { - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); self.state = VMState::Error(err); return; } @@ -798,7 +776,6 @@ impl Machine { executed_func = &func_clone[self.call_stack[executed_stack].func]; continue; } else { - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); self.state = VMState::Error(err); return; } @@ -812,7 +789,6 @@ impl Machine { executed_func = &func_clone[self.call_stack[executed_stack].func]; continue; } else { - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); self.state = VMState::Error(err); return; } @@ -832,7 +808,6 @@ impl Machine { nocon = true; break; } else { - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); self.state = VMState::Error(err); return; } @@ -853,7 +828,6 @@ impl Machine { nocon = true; break; } else { - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); self.state = VMState::Error(err); return; } @@ -880,7 +854,6 @@ impl Machine { executed_func = &func_clone[self.call_stack[executed_stack].func]; continue; } else { - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); self.state = VMState::Error(err); return; } @@ -904,7 +877,6 @@ impl Machine { executed_func = &func_clone[self.call_stack[executed_stack].func]; continue; } else { - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); self.state = VMState::Error(err); return; } @@ -921,7 +893,6 @@ impl Machine { executed_func = &func_clone[self.call_stack[executed_stack].func]; continue; } else { - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); self.state = VMState::Error(err); return; } @@ -935,7 +906,6 @@ impl Machine { executed_func = &func_clone[self.call_stack[executed_stack].func]; continue; } else { - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); self.state = VMState::Error(err); return; } @@ -954,7 +924,6 @@ impl Machine { executed_func = &func_clone[self.call_stack[executed_stack].func]; continue; } else { - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); self.state = VMState::Error(err); return; } @@ -967,7 +936,6 @@ impl Machine { executed_func = &func_clone[self.call_stack[executed_stack].func]; continue; } else { - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); self.state = VMState::Error(err); return; } @@ -999,7 +967,6 @@ impl Machine { executed_func = &func_clone[self.call_stack[executed_stack].func]; continue; } else { - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); self.state = VMState::Error(err); return; } @@ -1012,7 +979,6 @@ impl Machine { executed_func = &func_clone[self.call_stack[executed_stack].func]; continue; } else { - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); self.state = VMState::Error(err); return; } @@ -1035,7 +1001,6 @@ impl Machine { executed_func = &func_clone[self.call_stack[executed_stack].func]; continue; } else { - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); self.state = VMState::Error(err); return; } @@ -1062,7 +1027,6 @@ impl Machine { executed_func = &func_clone[self.call_stack[executed_stack].func]; continue; } else { - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); self.state = VMState::Error(err); return; } @@ -1076,7 +1040,6 @@ impl Machine { executed_func = &func_clone[self.call_stack[executed_stack].func]; continue; } else { - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); self.state = VMState::Error(err); return; } @@ -1100,7 +1063,6 @@ impl Machine { executed_func = &func_clone[self.call_stack[executed_stack].func]; continue; } else { - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); self.state = VMState::Error(err); return; } @@ -1128,7 +1090,6 @@ impl Machine { executed_func = &func_clone[self.call_stack[executed_stack].func]; continue; } else { - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); self.state = VMState::Error(err); return; } @@ -1143,7 +1104,6 @@ impl Machine { executed_func = &func_clone[self.call_stack[executed_stack].func]; continue; } else { - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); self.state = VMState::Error(err); return; } @@ -1162,7 +1122,6 @@ impl Machine { executed_func = &func_clone[self.call_stack[executed_stack].func]; continue; } else { - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); self.state = VMState::Error(err); return; } @@ -1176,7 +1135,6 @@ impl Machine { executed_func = &func_clone[self.call_stack[executed_stack].func]; continue; } else { - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); self.state = VMState::Error(err); return; } diff --git a/test.asl b/test.asl index 451416f..dfffe62 100644 --- a/test.asl +++ b/test.asl @@ -1,8 +1 @@ -lőcsve test(a,b) { - ugass(a,b) -} -piszolj { - test(0) -} csecs (e) { - ugass(e) -} \ No newline at end of file +gethelj test = szaft"a"szaft \ No newline at end of file From e09a4fc2d440c654db9020e37a3a63eec2e67abf Mon Sep 17 00:00:00 2001 From: afonya Date: Wed, 18 Jun 2025 15:13:50 +0200 Subject: [PATCH 13/19] begin coroutine --- src/enviroment.rs | 51 ++++++++++++++++++++++++++++++++++++++++++- src/virtualmachine.rs | 7 +++++- test.asl | 9 +++++++- 3 files changed, 64 insertions(+), 3 deletions(-) diff --git a/src/enviroment.rs b/src/enviroment.rs index c33fff6..29af7e2 100644 --- a/src/enviroment.rs +++ b/src/enviroment.rs @@ -1,6 +1,6 @@ use std::{collections::HashMap, fs, io::{stdin, BufReader, Read, Write}, net::{self, TcpListener, TcpStream}, process, thread::sleep, time::{Duration, UNIX_EPOCH}, vec}; -use crate::{decompiler::DecompiledOperation, errors::{create_error, print_error, ErrorSubType, ErrorType}, virtualmachine::{Machine, TableValue, VMMemory, VMMemoryBoolean, VMMemoryNativeFunction, VMMemoryNull, VMMemoryNumber, VMMemoryString, VMMemoryTable}}; +use crate::{decompiler::{DecompiledFunction, DecompiledOperation}, errors::{create_error, print_error, ErrorSubType, ErrorType}, virtualmachine::{Machine, TableValue, VMMemory, VMMemoryBoolean, VMMemoryNativeFunction, VMMemoryNull, VMMemoryNumber, VMMemoryString, VMMemoryTable, VMState}, Context}; fn get_string_from_vmmem(mem: &VMMemory) -> String { let mut out = String::new(); @@ -967,6 +967,43 @@ fn intezo_irj(machine: &mut Machine, op: &DecompiledOperation, args: Vec) -> VMMemory { + machine.state = VMState::Paused; + return VMMemory::Null(VMMemoryNull { variable_id: 0 }); +} +fn add_func(n_funcs: &mut Vec, n_ctx: &mut Vec, machine: &mut Machine, func: usize, pos: &mut usize) { + let mut exe_func = machine.functions[func].clone(); + let func_clone = machine.functions.clone(); + n_ctx.push(machine.ctx[func].clone()); + for (fid, fpos) in &func_clone[func].functions { + *pos += 1; + add_func(n_funcs, n_ctx, machine, *fpos as usize, pos); + exe_func.functions.insert(*fid, *pos as u32); + } + n_funcs.push(exe_func); +} +fn krumpli_letrehoz(machine: &mut Machine, op: &DecompiledOperation, args: Vec) -> VMMemory { + arg_expect(&args, 0, "function", machine, op); + let func = match &args[0] { + VMMemory::Function(func) => func.clone(), + _ => { + error(String::from("Expected a function"), machine, op); + return VMMemory::Null(VMMemoryNull { variable_id: 0 }); + } + }; + let mut n_funcs: Vec = vec![]; + let mut n_ctx: Vec = vec![]; + add_func(&mut n_funcs, &mut n_ctx, machine, func.id, &mut 0); + println!("{:?}", n_funcs); + println!("{:?}", n_ctx); + let mut vm = Machine::new(n_ctx); + vm.load_functions(n_funcs); + vm.memory = machine.memory.clone(); + let cor_id = machine.storage.len(); + machine.storage.push(Box::new(vm)); + return VMMemory::Number(VMMemoryNumber { value: cor_id as f64, variable_id: 0 }); +} + pub fn generate() -> HashMap { let mut mem: HashMap = HashMap::new(); @@ -1134,5 +1171,17 @@ pub fn generate() -> HashMap { ]; mem.insert(String::from("intéző"), VMMemory::Table(VMMemoryTable { values: intezo, variable_id: 0 })); + let krumpli: Vec = vec![ + TableValue { + key: VMMemory::String(VMMemoryString { value: String::from("várj"), variable_id: 0 }), + value: VMMemory::NativeFunction(VMMemoryNativeFunction { func: krumpli_varj, variable_id: 0 }), + }, + TableValue { + key: VMMemory::String(VMMemoryString { value: String::from("létrehoz"), variable_id: 0 }), + value: VMMemory::NativeFunction(VMMemoryNativeFunction { func: krumpli_letrehoz, variable_id: 0 }), + }, + ]; + mem.insert(String::from("krumpli"), VMMemory::Table(VMMemoryTable { values: krumpli, variable_id: 0 })); + return mem; } \ No newline at end of file diff --git a/src/virtualmachine.rs b/src/virtualmachine.rs index efbb4aa..d49a882 100644 --- a/src/virtualmachine.rs +++ b/src/virtualmachine.rs @@ -74,7 +74,7 @@ pub enum VMState { pub struct Machine { pub memory: Vec, - functions: Vec, + pub functions: Vec, pub stack: Vec, pub registers: Vec, pub call_stack: Vec, @@ -445,6 +445,11 @@ impl Machine { self.state = VMState::Paused } + pub fn load_functions(&mut self, functions: Vec) { + self.functions = functions; + self.state = VMState::Paused; + } + pub fn resume(&mut self) { match self.state { VMState::Paused => {}, diff --git a/test.asl b/test.asl index dfffe62..8dfd253 100644 --- a/test.asl +++ b/test.asl @@ -1 +1,8 @@ -gethelj test = szaft"a"szaft \ No newline at end of file +lőcsve test() { + lőcsve toast() { + ugass(2) + } + toast() + ugass(1) +} +krumpli.létrehoz(test) \ No newline at end of file From e245fdee73bf97153940c9762e93a7888a9ed80c Mon Sep 17 00:00:00 2001 From: afonya Date: Wed, 18 Jun 2025 16:36:15 +0200 Subject: [PATCH 14/19] finished coroutine --- src/enviroment.rs | 121 ++++++++++++++++++++++++++++++++++++++++++++-- test.asl | 5 +- 2 files changed, 120 insertions(+), 6 deletions(-) diff --git a/src/enviroment.rs b/src/enviroment.rs index 29af7e2..b0db0d6 100644 --- a/src/enviroment.rs +++ b/src/enviroment.rs @@ -1,6 +1,6 @@ use std::{collections::HashMap, fs, io::{stdin, BufReader, Read, Write}, net::{self, TcpListener, TcpStream}, process, thread::sleep, time::{Duration, UNIX_EPOCH}, vec}; -use crate::{decompiler::{DecompiledFunction, DecompiledOperation}, errors::{create_error, print_error, ErrorSubType, ErrorType}, virtualmachine::{Machine, TableValue, VMMemory, VMMemoryBoolean, VMMemoryNativeFunction, VMMemoryNull, VMMemoryNumber, VMMemoryString, VMMemoryTable, VMState}, Context}; +use crate::{decompiler::{DecompiledFunction, DecompiledOperation}, errors::{convert_subtypes_to_string, convert_types_to_string, create_error, print_error, ErrorSubType, ErrorType}, virtualmachine::{Machine, TableValue, VMMemory, VMMemoryBoolean, VMMemoryNativeFunction, VMMemoryNull, VMMemoryNumber, VMMemoryString, VMMemoryTable, VMState}, Context}; fn get_string_from_vmmem(mem: &VMMemory) -> String { let mut out = String::new(); @@ -975,12 +975,13 @@ fn add_func(n_funcs: &mut Vec, n_ctx: &mut Vec, mac let mut exe_func = machine.functions[func].clone(); let func_clone = machine.functions.clone(); n_ctx.push(machine.ctx[func].clone()); + let start = n_funcs.len(); for (fid, fpos) in &func_clone[func].functions { *pos += 1; add_func(n_funcs, n_ctx, machine, *fpos as usize, pos); exe_func.functions.insert(*fid, *pos as u32); } - n_funcs.push(exe_func); + n_funcs.insert(start, exe_func); } fn krumpli_letrehoz(machine: &mut Machine, op: &DecompiledOperation, args: Vec) -> VMMemory { arg_expect(&args, 0, "function", machine, op); @@ -994,15 +995,117 @@ fn krumpli_letrehoz(machine: &mut Machine, op: &DecompiledOperation, args: Vec = vec![]; let mut n_ctx: Vec = vec![]; add_func(&mut n_funcs, &mut n_ctx, machine, func.id, &mut 0); - println!("{:?}", n_funcs); - println!("{:?}", n_ctx); let mut vm = Machine::new(n_ctx); vm.load_functions(n_funcs); - vm.memory = machine.memory.clone(); let cor_id = machine.storage.len(); machine.storage.push(Box::new(vm)); return VMMemory::Number(VMMemoryNumber { value: cor_id as f64, variable_id: 0 }); } +fn krumpli_folytat(machine: &mut Machine, op: &DecompiledOperation, args: Vec) -> VMMemory { + arg_expect(&args, 0, "number", machine, op); + let num = match &args[0] { + VMMemory::Number(n) => n.value as usize, + _ => { + error(String::from("Expected a number"), machine, op); + return VMMemory::Null(VMMemoryNull { variable_id: 0 }); + } + }; + let vm = machine.storage.get_mut(num); + if vm.is_none() { + error(String::from("Coroutine not found"), machine, op); + return VMMemory::Null(VMMemoryNull { variable_id: 0 }); + } + let boxed_vm = vm.unwrap(); + let vm = boxed_vm.downcast_mut::(); + if vm.is_none() { + error(String::from("Coroutine is not a VM"), machine, op); + return VMMemory::Null(VMMemoryNull { variable_id: 0 }); + } + let vm = vm.unwrap(); + println!("{:?}", vm.functions); + match vm.state { + VMState::Paused => { + vm.memory = machine.memory.clone(); + vm.registers = machine.registers.clone(); + vm.resume(); + machine.memory = vm.memory.clone(); + machine.registers = vm.registers.clone(); + }, + _ => { + error(String::from("Coroutine is not paused"), machine, op); + return VMMemory::Null(VMMemoryNull { variable_id: 0 }); + } + } + return VMMemory::Null(VMMemoryNull { variable_id: 0 }); +} +fn krumpli_status(machine: &mut Machine, op: &DecompiledOperation, args: Vec) -> VMMemory { + arg_expect(&args, 0, "number", machine, op); + let num = match &args[0] { + VMMemory::Number(n) => n.value as usize, + _ => { + error(String::from("Expected a number"), machine, op); + return VMMemory::Null(VMMemoryNull { variable_id: 0 }); + } + }; + let vm = machine.storage.get_mut(num); + if vm.is_none() { + error(String::from("Coroutine not found"), machine, op); + return VMMemory::Null(VMMemoryNull { variable_id: 0 }); + } + let boxed_vm = vm.unwrap(); + let vm = boxed_vm.downcast_ref::(); + if vm.is_none() { + error(String::from("Coroutine is not a VM"), machine, op); + return VMMemory::Null(VMMemoryNull { variable_id: 0 }); + } + let vm = vm.unwrap(); + + let mut to_tbl: HashMap = HashMap::new(); + let stat = match vm.state { + VMState::Running => String::from("running"), + VMState::Paused => String::from("paused"), + VMState::Finished => String::from("finished"), + VMState::Error(_) => String::from("error"), + }; + let err = match &vm.state { + VMState::Error(e) => Some(e.clone()), + _ => None + }; + if let Some(e) = err { + let err_tbl: Vec = vec![ + TableValue { + key: VMMemory::String(VMMemoryString { value: String::from("message"), variable_id: 0 }), + value: VMMemory::String(VMMemoryString { value: e.message, variable_id: 0 }) + }, + TableValue { + key: VMMemory::String(VMMemoryString { value: String::from("position"), variable_id: 0 }), + value: VMMemory::Number(VMMemoryNumber { value: e.position as f64, variable_id: 0 }) + }, + TableValue { + key: VMMemory::String(VMMemoryString { value: String::from("type"), variable_id: 0 }), + value: VMMemory::String(VMMemoryString { value: convert_types_to_string(&e.typ), variable_id: 0 }) + }, + TableValue { + key: VMMemory::String(VMMemoryString { value: String::from("subtype"), variable_id: 0 }), + value: VMMemory::String(VMMemoryString { value: convert_subtypes_to_string(&e.subtype), variable_id: 0 }) + }, + TableValue { + key: VMMemory::String(VMMemoryString { value: String::from("code"), variable_id: 0 }), + value: VMMemory::String(VMMemoryString { value: e.code, variable_id: 0 }) + }, + ]; + to_tbl.insert(String::from("error"), VMMemory::Table(VMMemoryTable { values: err_tbl, variable_id: 0 })); + } + to_tbl.insert(String::from("status"), VMMemory::String(VMMemoryString { value: stat, variable_id: 0 })); + let mut res_tbl = VMMemoryTable { + values: vec![], + variable_id: 0, + }; + for (k, v) in to_tbl { + set_mem_tbl_val(&mut res_tbl, VMMemory::String(VMMemoryString { value: k, variable_id: 0 }), v); + } + return VMMemory::Table(res_tbl); +} pub fn generate() -> HashMap { let mut mem: HashMap = HashMap::new(); @@ -1180,6 +1283,14 @@ pub fn generate() -> HashMap { key: VMMemory::String(VMMemoryString { value: String::from("létrehoz"), variable_id: 0 }), value: VMMemory::NativeFunction(VMMemoryNativeFunction { func: krumpli_letrehoz, variable_id: 0 }), }, + TableValue { + key: VMMemory::String(VMMemoryString { value: String::from("folytat"), variable_id: 0 }), + value: VMMemory::NativeFunction(VMMemoryNativeFunction { func: krumpli_folytat, variable_id: 0 }), + }, + TableValue { + key: VMMemory::String(VMMemoryString { value: String::from("státusz"), variable_id: 0 }), + value: VMMemory::NativeFunction(VMMemoryNativeFunction { func: krumpli_status, variable_id: 0 }), + }, ]; mem.insert(String::from("krumpli"), VMMemory::Table(VMMemoryTable { values: krumpli, variable_id: 0 })); diff --git a/test.asl b/test.asl index 8dfd253..5b5aa9a 100644 --- a/test.asl +++ b/test.asl @@ -5,4 +5,7 @@ lőcsve test() { toast() ugass(1) } -krumpli.létrehoz(test) \ No newline at end of file +gethelj k = krumpli.létrehoz(test) +ugass(krumpli.státusz(k)) +krumpli.folytat(k) +ugass(krumpli.státusz(k)) \ No newline at end of file From 048f5079aef164fe97c3d94eb52537c17739a0b7 Mon Sep 17 00:00:00 2001 From: afonya Date: Wed, 18 Jun 2025 16:44:35 +0200 Subject: [PATCH 15/19] update everything to 1.0 --- docs/docs/enviroment.md | 20 +++++++++++++++++++- extension/index.js | 8 ++++++-- src/compiler.rs | 2 +- src/decompiler.rs | 2 +- src/enviroment.rs | 1 - src/main.rs | 2 +- 6 files changed, 28 insertions(+), 7 deletions(-) diff --git a/docs/docs/enviroment.md b/docs/docs/enviroment.md index fc4860d..54e6b31 100644 --- a/docs/docs/enviroment.md +++ b/docs/docs/enviroment.md @@ -164,4 +164,22 @@ A fájl írása felülírja a már fájlban lévő adatokat! |mappát töröl|Kitöröl egy mappát.|`mappát töröl(path: string)`|`mappát töröl(szaft"test1/"szaft)`| |fájlt töröl|Kitöröl egy fájlt.|`fájlt töröl(path: string)`|`fájlt töröl(szaft"compiled.asx"szaft)`| |olvass|Beolvas egy fájlt.|`olvass(path: string): string`|`olvass(szaft"test.asl"szaft)`| -|írj|Beleírja egy fájlba a kapott adatokat.|`írj(path: string, data: string)`|`írj(szaft"test.txt"szaft, szaft"Hello from ASL!"szaft)`| \ No newline at end of file +|írj|Beleírja egy fájlba a kapott adatokat.|`írj(path: string, data: string)`|`írj(szaft"test.txt"szaft, szaft"Hello from ASL!"szaft)`| + +--- + +## Krumpli (Coroutine) +Multi-tasking funkciók +:::tip + +A példák elé kell írni a kulcsszót: `krumpli` + +Példa: `krumpli.várj` + +::: +|Név|Leírás|Használat|Példa| +|---|---|---|---| +|várj|Visszaadja a futást az előző thread-nak.|`várj()`|`várj()`| +|létrehoz|Létrehoz egy új thread-et.|`létrehoz(f: function): coroutine`|`létrehoz(lőcsve() { ugass(7) })`| +|folytat|Folytatja a thread-et.|`folytat(c: coroutine)`|`folytat(c)`| +|státusz|Visszaadja a thread státuszát.|`folytat(c: coroutine)`|`folytat(c)`| \ No newline at end of file diff --git a/extension/index.js b/extension/index.js index 9f69f5b..e9adb88 100644 --- a/extension/index.js +++ b/extension/index.js @@ -36,6 +36,7 @@ vscode.languages.registerCompletionItemProvider('astrolang', { "mennyi az idő", "joink", "intéző", + "krumpli", "abs", "kerek", @@ -75,8 +76,11 @@ vscode.languages.registerCompletionItemProvider('astrolang', { "mappít", "mappát töröl", "fájlt töröl", - "olvass", - "írj" + + "várj", + "létrehoz", + "folytat", + "státusz" ] let out = [] for (let i = 0; i < words.length; i++) { diff --git a/src/compiler.rs b/src/compiler.rs index 82508a3..d30d014 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -1,7 +1,7 @@ use std::{collections::HashMap, fs, process, vec}; use crate::{errors::{create_error, print_error, ErrorSubType, ErrorType}, lexer::lex, parser::{parse, ASTPart}, Context}; -const ASXVERSION: [u8; 3] = [0,2,0]; +const ASXVERSION: [u8; 3] = [1,0,0]; #[derive(Debug, Clone)] pub struct Operation { diff --git a/src/decompiler.rs b/src/decompiler.rs index f572519..924feaf 100644 --- a/src/decompiler.rs +++ b/src/decompiler.rs @@ -1,6 +1,6 @@ use std::collections::HashMap; -const ASXVERSION: [u8; 3] = [0,2,0]; +const ASXVERSION: [u8; 3] = [1,0,0]; #[derive(Debug, Clone)] pub struct DecompiledFunction { diff --git a/src/enviroment.rs b/src/enviroment.rs index b0db0d6..40cfb12 100644 --- a/src/enviroment.rs +++ b/src/enviroment.rs @@ -1022,7 +1022,6 @@ fn krumpli_folytat(machine: &mut Machine, op: &DecompiledOperation, args: Vec { vm.memory = machine.memory.clone(); diff --git a/src/main.rs b/src/main.rs index 4d14a0b..3de6c12 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,7 +10,7 @@ mod virtualmachine; mod errors; mod decompiler; -const CLIVER: [u8; 3] = [0, 3, 0]; +const CLIVER: [u8; 3] = [1,0,0]; #[derive(Debug, Clone)] struct Context { From 1ccc95517f49098987cf69eff546742ec8d71fc3 Mon Sep 17 00:00:00 2001 From: afonya Date: Wed, 18 Jun 2025 17:01:55 +0200 Subject: [PATCH 16/19] made everything deployable, added license, added readme --- LICENSE | 7 + README.md | 26 ++ docs/versioned_docs/version-1.0.0/asx.md | 110 +++++++ .../version-1.0.0/enviroment.md | 185 +++++++++++ docs/versioned_docs/version-1.0.0/intro.md | 23 ++ .../version-1.0.0/langfunctions.md | 301 ++++++++++++++++++ docs/versioned_docs/version-1.0.0/syntax.md | 49 +++ .../version-1.0.0-sidebars.json | 8 + docs/versions.json | 1 + extension/asl.png | Bin 0 -> 14226 bytes extension/astrolang-extension-1.0.0.vsix | Bin 0 -> 17625 bytes extension/package.json | 7 +- 12 files changed, 715 insertions(+), 2 deletions(-) create mode 100644 LICENSE create mode 100644 README.md create mode 100644 docs/versioned_docs/version-1.0.0/asx.md create mode 100644 docs/versioned_docs/version-1.0.0/enviroment.md create mode 100644 docs/versioned_docs/version-1.0.0/intro.md create mode 100644 docs/versioned_docs/version-1.0.0/langfunctions.md create mode 100644 docs/versioned_docs/version-1.0.0/syntax.md create mode 100644 docs/versioned_sidebars/version-1.0.0-sidebars.json create mode 100644 extension/asl.png create mode 100644 extension/astrolang-extension-1.0.0.vsix diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..e66f844 --- /dev/null +++ b/LICENSE @@ -0,0 +1,7 @@ +Copyright 2025 Afonya + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..c215016 --- /dev/null +++ b/README.md @@ -0,0 +1,26 @@ +# Astro Lang +Egy magyar + GenZ programozási nyelv + +--- + +## Miben jobb: +- többszavas változók +- magyar kulcsszavak +- teljes értékű dokumentáció +- Rustban írt + +--- + +## Példa: +```asl +gethelj a = 10 +ugass(a) +``` + +--- + +Weboldal és dokumentáció: [itt](https://astrolang.afonyanet.hu) + +Kiadások: [itt](https://git.afonyanet.hu/afonya/AstroLang/releases) + +Licensz: MIT \ No newline at end of file diff --git a/docs/versioned_docs/version-1.0.0/asx.md b/docs/versioned_docs/version-1.0.0/asx.md new file mode 100644 index 0000000..7062399 --- /dev/null +++ b/docs/versioned_docs/version-1.0.0/asx.md @@ -0,0 +1,110 @@ +--- +sidebar_position: 5 +description: Az ASX fájl leírása +--- + +# ASX (Astro Lang Executable) fájl + +--- + +:::info + +ASX Verzió: `0.2.0` + +::: + +:::info + +Ezt megtudod nézni a `ASL viewx ` parancs használatával. + +::: + +## Fájl felépítése: +|Név|Leírás|Méret| +|---|---|---| +|Doctype: ASX|Elmondja a fájlról, hogy tényleg ASX.|3 bytes| +|Verzió|Elmondja a fájl ASX verzióját. (byte.byte.byte)|3 bytes| +|Funkciók száma|Elmondja, hogy mennyi funkció van a fájlban.|4 bytes| +|Funkciók|Lásd: [Funkciók](#funkciók)|| + +## Funkciók: +|Név|Leírás|Méret| +|---|---|---| +|Változók száma|Elmondja, hogy a funkcióban mennyi változó van.|4 bytes| +|Változók|Lásd: [Változók](#változók)|| +|Szövegek száma|Elmondja, hogy a funkcióban mennyi szöveg van.|4 bytes| +|Szövegek|Lásd: [Szövegek](#szövegek)|| +|Funkciók száma|Elmondja, hogy a funkcióban mennyi funkció meghívás van.|4 bytes| +|Funkciók|Lásd: [Funkció meghívások](#funkció-meghívások)|| +|Catch pos|Megmutatja a catch funkció helyzetét, csak try-ban. Normál funkciók esetén 0|4 bytes| +|Instrukciók száma|Elmondja, hogy a funkcióban mennyi instrukció van.|4 bytes| +|Instukciók|Lásd: [Instrukciók](#instrukciók)|| + +## Változók: +|Név|Méret| +|---|---| +|Változó nevének hossza|4 bytes| +|Változó neve|| +|Változó ID-je|3 bytes| +|Változó kezdő ponja|4 bytes| +|Változó végpontja|4 bytes| + +## Szövegek: +|Név|Méret| +|---|---| +|Szöveg ID-je|3 bytes| +|A szöveg hossza|4 bytes| +|A szöveg|| + +## Funkció meghívások: +|Név|Méret| +|---|---| +|A meghívás ID-je|3 bytes| +|A meghívott funkció pozíciója|4 bytes| + +## Instrukciók: +:::info + +Minden instrukció végére hozzáadunk még 3 bit-et, így összesen 10 byte-ba belefér minden instrukció. + +::: +|OP Code - 5 bits|Rövid név|Leírás|Arg1 - 4 bits|Arg2 - 64 bits|Arg3 - 4 bits| +|---|---|---|---|---|---| +|0|HLT|Befejezi a program futtatását|||| +|1|LDS|Betölt egy szöveget a regiszterbe|R(A)|Szöveg ID|| +|2|LDM|Betölti a változót a memóriából|R(A)|Változó ID|| +|3|LDI|Betölt egy számot a regiszterbe|R(A)|Szám|| +|4|LDB|Betölt egy logikai értéket a regiszterbe|R(A)|Logikai érték|| +|5|LDF|Betölt egy funkciót a regiszterbe|R(A)|Funkció ID|| +|6|LDN|Betölt egy null-t/táblát a regiszterbe|R(A)|Ez egy tábla?|| +|7|ASS|Hozzáad egy változó ID-t a regiszerhez|R(A)|Változó ID|| +|8|UNB|Leválaszja a regiszterről a változót|R(A)||| +|9|MOV|Átmásolja R(A) pointerjét R(B)-be|R(A)|R(B)|| +|10|ADD|`R(C) = R(A) + R(B)`|R(A)|R(B)|R(C)| +|11|SUB|`R(C) = R(A) - R(B)`|R(A)|R(B)|R(C)| +|12|MUL|`R(C) = R(A) * R(B)`|R(A)|R(B)|R(C)| +|13|DIV|`R(C) = R(A) / R(B)`|R(A)|R(B)|R(C)| +|14|POW|`R(C) = R(A) ^ R(B)`|R(A)|R(B)|R(C)| +|15|MOD|`R(C) = R(A) % R(B)`|R(A)|R(B)|R(C)| +|16|AND|`R(C) = R(A) && R(B)`|R(A)|R(B)|R(C)| +|17|OR|`R(C) = R(A) \|\| R(B)`|R(A)|R(B)|R(C)| +|18|EQ|`R(C) = R(A) == R(B)`|R(A)|R(B)|R(C)| +|19|NEQ|`R(C) = R(A) != R(B)`|R(A)|R(B)|R(C)| +|20|GRE|`R(C) = R(A) > R(B)`|R(A)|R(B)|R(C)| +|21|GRQ|`R(C) = R(A) >= R(B)`|R(A)|R(B)|R(C)| +|22|LES|`R(C) = R(A) < R(B)`|R(A)|R(B)|R(C)| +|23|LEQ|`R(C) = R(A) <= R(B)`|R(A)|R(B)|R(C)| +|24|NOT|`R(B) = !R(A)`|R(A)|R(B)|| +|25|JMP|Oda ugrik a kódban||Hely|| +|26|CJP|Oda ugrik a kódban, ha a regiszter igaz|R(A)|Hely|| +|27|CAL|Meghív egy funkciót, majd a kimenetet elmenti R(B)-be|R(A)|R(B)|| +|28|PSH|Egy értéket belerak a következő funkció bemeneteihez|R(A)||| +|29|RET|Visszad egy értéket|R(A)||| +|30|GET|Lekér egy értéket a táblából `R(C) = R(A)[R(B)]`|R(A)|R(B)|R(C)| +|31|SET|Beállít egy értéket a táblának `R(A)[R(B)] = R(C)`|R(A)|R(B)|R(C)| + +:::tip + +Ha az ENV-ből szeretnénk lekérni valamit akkor a `GET`-et kell használni, úgy, hogy `R(A) = 0`! + +::: \ No newline at end of file diff --git a/docs/versioned_docs/version-1.0.0/enviroment.md b/docs/versioned_docs/version-1.0.0/enviroment.md new file mode 100644 index 0000000..54e6b31 --- /dev/null +++ b/docs/versioned_docs/version-1.0.0/enviroment.md @@ -0,0 +1,185 @@ +--- +sidebar_position: 4 +description: Az Astro Lang környezete +--- + +# Környezet + +--- + +## Alapfunkciók +|Név|Leírás|Használat|Példa| +|---|---|---|---| +|ugass|Kíírja a megadott értékeket.|`ugass(...)`|`ugass(6,7,szaft"test"szaft)`| +|bimba|Várakozik adott ideig (miliszekundum-ban).|`ugass(ms: number)`|`bimba(1000)`| +|csömör|Hibával befejezi a programot.|`csömör(error: string)`|`csömör(szaft"Sikertelen: Sikeresen befejezve!"szaft)`| +|tarh|Kíírja, hogy a megadott érték milyen típusú.|`tarh(object: any): string`|`tarh(82)`| +|bimbabemb|Átalakítja a megadott érétk típusát, ha lehetséges.|`bimbabemb(object: any, target: string): any`|`bimbabemb(7,szaft"string"szaft)`| +|mennyi az idő|Visszaadja a pillanatnyi UNIX időt milisec-ben.|`mennyi az idő(): number`|`mennyi az idő()`| +|joink|Bekér egy szöveget a terminálból.|`joink(): string`|`joink()`| + +--- + +## Nerd (Math) +Matematikai funkciók +:::tip + +A példák elé kell írni a kulcsszót: `nerd` + +Példa: `nerd.abs` + +::: +|Név|Leírás|Használat|Példa| +|---|---|---|---| +|abs|Visszaadja a megadott érték abszolút értékét.|`abs(n: number): number`|`abs(-2)`| +|kerek|Visszaadja a megadott érték kerekített értékét. Irányok: `fel, le, közel`|`kerek(n: number, direction: string): number`|`kerek(1.2, szaft"fel"szaft)`| +|sin|Visszaadja a megadott érték szinusz értékét.|`sin(n: number): number`|`sin(0)`| +|cos|Visszaadja a megadott érték koszinusz értékét.|`cos(n: number): number`|`cos(90)`| +|tan|Visszaadja a megadott érték tangens értékét.|`tan(n: number): number`|`tan(0)`| +|sqrt|Visszaadja a megadott érték gyökét.|`sqrt(n: number): number`|`sqrt(-2)`| +|legnagyobb|Visszaadja a megadott értékek közül a legnagyobbat.|`legnagyobb(...: number): number`|`legnagyobb(1,2,3)`| +|legkisebb|Visszaadja a megadott értékek közül a legkisebbet.|`legkisebb(...: number): number`|`legkisebb(1,2,3)`| +|pi|A pi értékét tárolja.|`pi: number`|`pi`| + +--- + +## Szaft (String) +Szöveggel lévő funkciók +:::tip + +A példák elé kell írni a kulcsszót: `szaft` + +Példa: `szaft.csemerd fel` + +::: +|Név|Leírás|Használat|Példa| +|---|---|---|---| +|csemerd fel|Visszaadja a megadott szöveget végig nagy betűkkel.|`csemerd fel(s: string): string`|`csemerd fel(szaft"TeSt"szaft)`| +|csemerd le|Visszaadja a megadott szöveget végig kis betűkkel.|`csemerd le(s: string): string`|`csemerd le(szaft"TeSt"szaft)`| +|hossz|Visszaadja a megadott szöveg hosszát.|`hossz(s: string): number`|`hossz(szaft"test"szaft)`| +|ismételd|A megadott szöveget `n` szer ismételve adja vissza.|`ismételd(s: string, n: number): string`|`ismételd(szaft"test"szaft, 3)`| +|uno reverse|A megadott szöveget fordítva adja vissza.|`uno reverse(s: string): string`|`uno reverse(szaft"test"szaft)`| +|darabos|Visszaadja a megadott szöveg egy darabját.|`darabos(s: string, start: number, end: number): string`|`darabos(szaft"test"szaft, 0, 1)`| +|keres|Megnézi, hogy a megadott szövegben megtalálható-e a másik szöveg.|`keres(s: string, find: string): boolean`|`keres(szaft"test"szaft,szaft"st"szaft)`| +|átrak|A megadott szövegben kicseréli a másik szöveget egy harmadikkal.|`átrak(s: string, from: string, to: string): string`|`átrak(szaft"test"szaft,szaft"st"szaft,szaft"bemb"szaft)`| +|számmá|A megadott szövegben az `n`-edik karakter szám megfelelőjét adja vissza.|`számmá(s: string, n: number): number`|`számmá(szaft"test"szaft,0)`| +|betűvé|A megadott szám betű megfelelőjét adja vissza.|`átrak(n: number): string`|`átrak(65)`| + +--- + +## Tábla (Table) +Táblákkal lévő funkciók +:::tip + +A példák elé kell írni a kulcsszót: `tábla` + +Példa: `tábla.hozzáad` + +::: +:::warning + +A funkciók végeredményét ajánlott beleírni a táblába, mert ez nem történik meg alapból. + +Példa: `a = tábla.hozzáad(a, 7)` + +::: +|Név|Leírás|Használat|Példa| +|---|---|---|---| +|hozzáad|Hozzáad egy értéket egy táblához.|`hozzáad(t: table, value: any): table`|`hozzáad({1,2,3}, 7)`| +|töröl|Töröl egy értéket a táblából.|`töröl(t: table, n: number): table`|`töröl({1,2,3}, 0)`| +|kulcsok|Visszaadja a tábla kulcsait egy másik táblában.|`kulcsok(t: table): table`|`kulcsok({1,2,3})`| +|hossz|Visszaadja a tábla hosszát.|`hossz(t: table): number`|`hozzáad({1,2,3})`| + +--- + +## Szenvedés (Process) +A feladattal kapcsolatos funkciók +:::tip + +A példák elé kell írni a kulcsszót: `szenvedés` + +Példa: `szenvedés.vége` + +::: +|Név|Leírás|Használat|Példa| +|---|---|---|---| +|vége|Befejezi a programot egy kilépő kóddal.|`vége(n: number)`|`vége(0)`| + +--- + +## Kábel (Net) +A nettel kapcsolatos funkciót +:::tip + +A példák elé kell írni a kulcsszót: `kábel` + +Példa: `kábel.halgass` + +::: +|Név|Leírás|Használat|Példa| +|---|---|---|---| +|halgass|Hallgat egy porton.|`halgass(host: string, port: number): halgató`|`halgass(szaft"0.0.0.0"szaft,1010)`| + +:::warning + +Ezek a funkciók kérik, hogy az első értékük a szülő táblájuk legyen + +::: + +### Halgató: +|Név|Leírás|Használat|Példa| +|---|---|---|---| +|kérés|Várakozik egy kérésre, majd visszaadja azt.|`kérés(listener: halgató): kapcsolat`|`kérés(listener)`| + +### Kapcsolat: +|Név|Leírás|Használat|Példa| +|---|---|---|---| +|olvass|Beleolvas a kapcsolatba.|`olvass(stream: kapcsolat, len: number): string`|`olvass(stream, 1024)`| +|írj|Beleír a kapcsolatba.|`írj(stream: kapcsolat, data: string)`|`írj(stream, szaft"Hello from ASL!"szaft)`| +|zár|Bezárja a kapcsolatot.|`zár(stream: kapcsolat)`|`zár(stream)`| + +--- + +## Intéző (Filesystem) +Fájlokkal lévő funkciók +:::tip + +A példák elé kell írni a kulcsszót: `intéző` + +Példa: `intéző.létezik` + +::: +:::warning + +A fájlok, helyét bárhogy megadhatod, viszont a törlésnél légy óvatos! + +A fájl írása felülírja a már fájlban lévő adatokat! + +::: +|Név|Leírás|Használat|Példa| +|---|---|---|---| +|létezik|Megnézi, hogy létezik-e az elérési út.|`létezik(path: string): boolean`|`létezik(szaft"test.asl"szaft)`| +|infó|Lekéri a metaadatokat az adott elérési útból.|`infó(path: string): table`|`infó(szaft"test.asl"szaft)`| +|mappít|Létrehozza a mappákat, hogy elérje az elérési útat.|`mappít(path: string)`|`mappít(szaft"test1/test2/"szaft)`| +|mappát töröl|Kitöröl egy mappát.|`mappát töröl(path: string)`|`mappát töröl(szaft"test1/"szaft)`| +|fájlt töröl|Kitöröl egy fájlt.|`fájlt töröl(path: string)`|`fájlt töröl(szaft"compiled.asx"szaft)`| +|olvass|Beolvas egy fájlt.|`olvass(path: string): string`|`olvass(szaft"test.asl"szaft)`| +|írj|Beleírja egy fájlba a kapott adatokat.|`írj(path: string, data: string)`|`írj(szaft"test.txt"szaft, szaft"Hello from ASL!"szaft)`| + +--- + +## Krumpli (Coroutine) +Multi-tasking funkciók +:::tip + +A példák elé kell írni a kulcsszót: `krumpli` + +Példa: `krumpli.várj` + +::: +|Név|Leírás|Használat|Példa| +|---|---|---|---| +|várj|Visszaadja a futást az előző thread-nak.|`várj()`|`várj()`| +|létrehoz|Létrehoz egy új thread-et.|`létrehoz(f: function): coroutine`|`létrehoz(lőcsve() { ugass(7) })`| +|folytat|Folytatja a thread-et.|`folytat(c: coroutine)`|`folytat(c)`| +|státusz|Visszaadja a thread státuszát.|`folytat(c: coroutine)`|`folytat(c)`| \ No newline at end of file diff --git a/docs/versioned_docs/version-1.0.0/intro.md b/docs/versioned_docs/version-1.0.0/intro.md new file mode 100644 index 0000000..90445fd --- /dev/null +++ b/docs/versioned_docs/version-1.0.0/intro.md @@ -0,0 +1,23 @@ +--- +sidebar_position: 1 +description: Az Astro Lang bemutatása +--- + +# Astro Lang +Egy magyar + GenZ programozási nyelv + +--- + +Miben jobb: +- többszavas változók +- magyar kulcsszavak +- teljes értékű dokumentáció +- Rustban írt + +--- + +Példa: +```asl title="example.asl" +gethelj a = 10 +ugass(a) +``` \ No newline at end of file diff --git a/docs/versioned_docs/version-1.0.0/langfunctions.md b/docs/versioned_docs/version-1.0.0/langfunctions.md new file mode 100644 index 0000000..72244b1 --- /dev/null +++ b/docs/versioned_docs/version-1.0.0/langfunctions.md @@ -0,0 +1,301 @@ +--- +sidebar_position: 3 +description: Az Astro Lang fukciói +--- + +# Nyelvi funkciók + +--- + +## Assignment (Változó beállítás) +Kucsszó: `gethelj` + +Használat: `gethelj változó = érték` + +Példa: +```asl title="example.asl" +gethelj test = 17 +``` + +--- + +## Var read (Változó olvasás) +Kucsszó: `-` + +Használat: `változó` + +Példa: +```asl title="example.asl" +gethelj test = 17 +ugass(test) +``` + +--- + +## Var update (Változó frissítés) +Kucsszó: `-` + +Használat: `változó = érték` + +Példa: +```asl title="example.asl" +gethelj test = 17 +ugass(test) +test = 18 +ugass(test) +``` + +--- + +## Function (Funkció) +Kucsszó: `lőcsve` + +Használat: `lőcsve változó(változók) {lefutatott kód}` + +Példa: +```asl title="example.asl" +lőcsve test(a) { + //Ez akkor fut le mikor meghívod a funkciót +} +test(8) //így tudsz meghívni egy funkciót, ebben az esetben az "a" 8 lesz +``` + +--- + +## If (Ha) +Kulcsszó: `ha geny` + +Használat: `ha geny(feltétel) {ha igaz}` + +Példa: +```asl title="example.asl" +ha geny(piszv) { + //Ez akkor fut le, ha a feltétel igaz + //Ebben az esetben mindig +} +``` + +--- + +## Else (Különben) +Kulcsszó: `ha nem geny` + +Használat: `ha nem geny {ha hamis}` + +Példa: +```asl title="example.asl" +ha geny(nem piszv) { + //Ez akkor fut le, ha a feltétel igaz + //Ebben az esetben soha +} ha nem geny { + //Ez akkor fut le, ha a feltétel hamis + //Ebben az esetben mindig +} +``` + +:::tip + +Nem kötelező egyből a ha után rakni, a kódban bárhol elfogadható és az előzőleg lefutott if-t veszi figyelembe. + +::: + +--- + +## Else if (Különben-Ha) +Kulcsszó: `ha nem geny akkor geny` + +Használat: `ha nem geny akkor geny(feltétel) {ha igaz}` + +Példa: +```asl title="example.asl" +ha geny(nem piszv) { + //Ez akkor fut le, ha a feltétel igaz + //Ebben az esetben soha +} ha nem geny akkor geny(piszv) { + //Ez akkor fut le, ha az előző if feltétele hamis és a feltétel igaz + //Ebben az esetben mindig +} +``` + +:::tip + +Nem kötelező egyből a ha után rakni, a kódban bárhol elfogadható és az előzőleg lefutott if-t veszi figyelembe. + +::: + +--- + +## While (Amíg) +Kulcsszó: `amíg geny` + +Használat: `amíg geny(feltétel) {amíg igaz}` + +Példa: +```asl title="example.asl" +amíg geny(piszv) { + //Ez addig fut le, amíg a feltétel igaz + //Ebben az esetben örökké fog futni +} +``` + +--- + +## For (Változós amíg) +Kulcsszó: `kopva` + +Használat: `kopva(beállítás;feltétel;frissítés) {amíg igaz}` + +:::info + +A beállítás első futás előtt fut le, csak 1 utasítást tartalmazhat. + +A frissítés minden futás után fut le, csak 1 utasítást tartalmazhat. + +::: + +Példa: +```asl title="example.asl" +kopva(gethelj i = 0; i < 10; i = i + 1) { + //Ez addig fut le, amíg a feltétel igaz +} +``` + +--- + +## Break (Törés) +Kulcsszó: `kraf` + +Használat: `kraf` + +Példa: +```asl title="example.asl" +kopva(gethelj i = 0; i < 10; i = i + 1) { + kraf //Ez az első futásnál be fogja fejezni az amíg-ot +} +``` + +--- + +## Continue (Folytasd) +Kulcsszó: `szard le` + +Használat: `szard le` + +Példa: +```asl title="example.asl" +kopva(gethelj i = 0; i < 10; i = i + 1) { + ugass(i) + szard le + ugass(78) //Ez soha nem fog lefutni, mert át lesz ugorva +} +``` + +--- + +## Return (Funkció visszadása) +Kulcsszó: `reti` + +Használat: `reti [változó]` + +Példa: +```asl title="example.asl" +lőcsve test(a) { + reti a +} +gethelj a = test(8) //Az "a" értéke "8" lesz, mert azt adja vissza. +``` + +--- + +## Import (Betöltés) +Kulcsszó: `hámozd, be/ba` + +Használat: `hámozd változó be/ba` + +:::tip + +Ez egyből létrehoz egy változót. +Pontos fájlnevet tudsz megadni! + +::: + +Példa: +```asl title="example.asl" +hámozd test be szaft"test.asl"szaft +``` + +--- + +## Table (Tábla) + +:::tip + +A kulcs bármilyen érték típus lehet, kivéve: funkció, tábla. + +::: + +### Létrehozás +Használat: `{érték,érték}, {[kulcs]=érték}` + +Példa: +```asl title="example.asl" +gethelj a = {1,2,3} +``` + +### Lekérés +Használat: `tábla[kulcs]` + +Példa: +```asl title="example.asl" +gethelj a = {1,2,3} +ugass(a[0]) // 1 +``` + +### Gyors lekérés +Használat: `tábla.kulcs` + +:::warning + +Csak a szöveges kulcsokkal működik, viszont több szót is támogat! + +::: + +Példa: +```asl title="example.asl" +gethelj a = {1,2,3,[szaft"test"szaft]=73} +ugass(a.test) // 73 +``` + +### Beállítás +Használat: `tábla[kulcs] = érték` + +Példa: +```asl title="example.asl" +gethelj a = {1,2,3} +ugass(a[0]) // 1 +a[0] = 12 +ugass(a[0]) // 12 +``` + +--- + +## Try/Catch (Próbáld ki) +Kulcsszó: `piszolj, csecs` + +Használat: `piszolj {amit ki kell próbálni} csecs (error) {ha hiba}` + +:::warning + +A catch rész itt nem rakható bárhova, nem úgy mint az if-nél! + +::: + +Példa: +```asl title="example.asl" +piszolj { + gethelj test = szaft"a"szaft+1 +} csecs (e) { + //Ez akkor fog lefutni, mikor hiba van + ugass(e) +} +``` \ No newline at end of file diff --git a/docs/versioned_docs/version-1.0.0/syntax.md b/docs/versioned_docs/version-1.0.0/syntax.md new file mode 100644 index 0000000..794b9b3 --- /dev/null +++ b/docs/versioned_docs/version-1.0.0/syntax.md @@ -0,0 +1,49 @@ +--- +sidebar_position: 2 +description: Az Astro Lang synatx bemutatása +--- + +# Syntax + +--- + +## Típusok: +|Típus neve|Magyar neve|Leírása|Példa| +|---|---|---|---| +|String|Szöveg|Minden ami szöveg.|`szaft"test"szaft`| +|Number|Szám|Minden ami szám.|`2, 3.14, -5`| +|Identifier|Azonosító|A változók, dolgok neve/azonosítója, több szót is támogat. Fontos: szám nem lehet a szavak elején, mert az már számnak számít!|`teszt, több szót is támogat, ez is jo72`| +|Operator|Művelet|Minden ami művelet.|`+, -, *`| +|Keyword|Kulcsszó|Azok az azonosítók amelyek valamilyen funkciót látnak el a programnyelben.|`gethelj, lőcsve, ha geny`| +|Separator|Elválasztó|Olyan karakterek, melyek elválaszják a többi típust egymástól.|`=, (, {`| + +Példa: +```asl +gethelj a = 15 + 2 +^ ^ ^ ^ ^ ^ Number +| | | | | Operator +| | | | Number +| | | Separator +| | Identifier +| Keyword +``` + +## Egyéb: +### Komment: +Ezek nem befolyásolják a kód futását, csak leírást adnak arról, hogy mi mit csinál. +- Egysoros kommentet így tudsz létrehozni: `//komment` +- Többsoros kommentet pedig így: `/*komment*/` +### Logikai érték: +:::info + +A nyelv ezeket kulcsszóként kezeli! + +::: +Igaz (piszv) vagy hamis (nem piszv) +### Semmi: +:::info + +A nyelv ezt is kulcsszóként kezeli! + +::: +Null (nincs hám) \ No newline at end of file diff --git a/docs/versioned_sidebars/version-1.0.0-sidebars.json b/docs/versioned_sidebars/version-1.0.0-sidebars.json new file mode 100644 index 0000000..2782dc0 --- /dev/null +++ b/docs/versioned_sidebars/version-1.0.0-sidebars.json @@ -0,0 +1,8 @@ +{ + "sidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/docs/versions.json b/docs/versions.json index 3145067..25a2ff2 100644 --- a/docs/versions.json +++ b/docs/versions.json @@ -1,3 +1,4 @@ [ + "1.0.0", "0.2.0" ] diff --git a/extension/asl.png b/extension/asl.png new file mode 100644 index 0000000000000000000000000000000000000000..cbed5a6ad4297e3a16e7ea39f353dc23380ad45b GIT binary patch literal 14226 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 e5^B55UTQjIXZSTo(>-M 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 vWQS}daygA`2B Date: Wed, 18 Jun 2025 17:36:03 +0200 Subject: [PATCH 17/19] add a readme and a license to the extension and the docs --- docs/LICENSE | 7 ++++++ docs/README.md | 26 +++++++++++++++++++++++ extension/.gitignore | 1 + extension/LICENSE | 7 ++++++ extension/README.md | 26 +++++++++++++++++++++++ extension/astrolang-extension-1.0.0.vsix | Bin 17625 -> 0 bytes extension/package.json | 2 +- 7 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 docs/LICENSE create mode 100644 docs/README.md create mode 100644 extension/.gitignore create mode 100644 extension/LICENSE create mode 100644 extension/README.md delete mode 100644 extension/astrolang-extension-1.0.0.vsix diff --git a/docs/LICENSE b/docs/LICENSE new file mode 100644 index 0000000..e66f844 --- /dev/null +++ b/docs/LICENSE @@ -0,0 +1,7 @@ +Copyright 2025 Afonya + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..da94e10 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,26 @@ +# Astro Lang Docs +Egy magyar + GenZ programozási nyelv + +--- + +## Miben jobb: +- többszavas változók +- magyar kulcsszavak +- teljes értékű dokumentáció +- Rustban írt + +--- + +## Példa: +```asl +gethelj a = 10 +ugass(a) +``` + +--- + +Weboldal és dokumentáció: [itt](https://astrolang.afonyanet.hu) + +Kiadások: [itt](https://git.afonyanet.hu/afonya/AstroLang/releases) + +Licensz: MIT \ No newline at end of file diff --git a/extension/.gitignore b/extension/.gitignore new file mode 100644 index 0000000..d163863 --- /dev/null +++ b/extension/.gitignore @@ -0,0 +1 @@ +build/ \ No newline at end of file diff --git a/extension/LICENSE b/extension/LICENSE new file mode 100644 index 0000000..e66f844 --- /dev/null +++ b/extension/LICENSE @@ -0,0 +1,7 @@ +Copyright 2025 Afonya + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/extension/README.md b/extension/README.md new file mode 100644 index 0000000..7ddfcf8 --- /dev/null +++ b/extension/README.md @@ -0,0 +1,26 @@ +# Astro Lang Extension +Egy magyar + GenZ programozási nyelv + +--- + +## Miben jobb: +- többszavas változók +- magyar kulcsszavak +- teljes értékű dokumentáció +- Rustban írt + +--- + +## Példa: +```asl +gethelj a = 10 +ugass(a) +``` + +--- + +Weboldal és dokumentáció: [itt](https://astrolang.afonyanet.hu) + +Kiadások: [itt](https://git.afonyanet.hu/afonya/AstroLang/releases) + +Licensz: MIT \ No newline at end of file diff --git a/extension/astrolang-extension-1.0.0.vsix b/extension/astrolang-extension-1.0.0.vsix deleted file mode 100644 index 6170be4ff79a6102d2c608feaebff5944f86283d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17625 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 vWQS}daygA`2B Date: Wed, 18 Jun 2025 18:00:46 +0200 Subject: [PATCH 18/19] added a way to create a network connection --- docs/docs/enviroment.md | 1 + .../version-1.0.0/enviroment.md | 1 + extension/astrolang-extension-1.0.2.vsix | Bin 0 -> 19002 bytes extension/index.js | 1 + extension/package.json | 2 +- src/enviroment.rs | 42 +++++++++++++++++- src/main.rs | 2 +- test.asl | 19 ++++---- 8 files changed, 53 insertions(+), 15 deletions(-) create mode 100644 extension/astrolang-extension-1.0.2.vsix diff --git a/docs/docs/enviroment.md b/docs/docs/enviroment.md index 54e6b31..893e3fc 100644 --- a/docs/docs/enviroment.md +++ b/docs/docs/enviroment.md @@ -119,6 +119,7 @@ Példa: `kábel.halgass` |Név|Leírás|Használat|Példa| |---|---|---|---| |halgass|Hallgat egy porton.|`halgass(host: string, port: number): halgató`|`halgass(szaft"0.0.0.0"szaft,1010)`| +|kapcsolódj|Rákapcsolódik egy célra.|`kapcsolódj(target: string): kapcsolat`|`kapcsolódj(szaft"example.com:80"szaft)`| :::warning diff --git a/docs/versioned_docs/version-1.0.0/enviroment.md b/docs/versioned_docs/version-1.0.0/enviroment.md index 54e6b31..893e3fc 100644 --- a/docs/versioned_docs/version-1.0.0/enviroment.md +++ b/docs/versioned_docs/version-1.0.0/enviroment.md @@ -119,6 +119,7 @@ Példa: `kábel.halgass` |Név|Leírás|Használat|Példa| |---|---|---|---| |halgass|Hallgat egy porton.|`halgass(host: string, port: number): halgató`|`halgass(szaft"0.0.0.0"szaft,1010)`| +|kapcsolódj|Rákapcsolódik egy célra.|`kapcsolódj(target: string): kapcsolat`|`kapcsolódj(szaft"example.com:80"szaft)`| :::warning diff --git a/extension/astrolang-extension-1.0.2.vsix b/extension/astrolang-extension-1.0.2.vsix new file mode 100644 index 0000000000000000000000000000000000000000..0651d87085c128a8db11c2728c4cad420dfe251b GIT binary patch literal 19002 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 s.value.clone(), _ => String::new() }; - match listener.write_all(write.as_bytes()) { + match stream.write_all(write.as_bytes()) { Ok(_) => {}, Err(e) => { error(format!("Failed to write to stream: {}", e), machine, op); @@ -540,6 +540,40 @@ fn kabel_keres(machine: &mut Machine, op: &DecompiledOperation, args: Vec) -> VMMemory { + arg_expect(&args, 0, "string", machine, op); + let str = match &args[0] { + VMMemory::String(s) => s.value.clone(), + _ => String::new() + }; + let stream = match TcpStream::connect(&str) { + Ok(s) => s, + Err(err) => { + error(format!("Failed to connect to {}: {}", str, err), machine, op); + return VMMemory::Null(VMMemoryNull { variable_id: 0 }); + } + }; + machine.storage.push(Box::new(stream)); + let ret_table: Vec = vec![ + TableValue { + key: VMMemory::String(VMMemoryString { value: String::from("olvass"), variable_id: 0 }), + value: VMMemory::NativeFunction(VMMemoryNativeFunction { func: kabel_olvass, variable_id: 0 }), + }, + TableValue { + key: VMMemory::String(VMMemoryString { value: String::from("írj"), variable_id: 0 }), + value: VMMemory::NativeFunction(VMMemoryNativeFunction { func: kabel_irj, variable_id: 0 }), + }, + TableValue { + key: VMMemory::String(VMMemoryString { value: String::from("zár"), variable_id: 0 }), + value: VMMemory::NativeFunction(VMMemoryNativeFunction { func: kabel_zar, variable_id: 0 }), + }, + TableValue { + key: VMMemory::String(VMMemoryString { value: String::from("id"), variable_id: 0 }), + value: VMMemory::Number(VMMemoryNumber { value: (machine.storage.len()-1) as f64, variable_id: 0 }), + } + ]; + return VMMemory::Table(VMMemoryTable { values: ret_table, variable_id: 0 }); +} fn kabel_halgass(machine: &mut Machine, op: &DecompiledOperation, args: Vec) -> VMMemory { arg_expect(&args, 0, "string", machine, op); arg_expect(&args, 1, "number", machine, op); @@ -1161,6 +1195,10 @@ pub fn generate() -> HashMap { TableValue { key: VMMemory::String(VMMemoryString { value: String::from("halgass"), variable_id: 0 }), value: VMMemory::NativeFunction(VMMemoryNativeFunction { func: kabel_halgass, variable_id: 0 }), + }, + TableValue { + key: VMMemory::String(VMMemoryString { value: String::from("kapcsolódj"), variable_id: 0 }), + value: VMMemory::NativeFunction(VMMemoryNativeFunction { func: kabel_kapcsolodj, variable_id: 0 }), } ]; mem.insert(String::from("kábel"), VMMemory::Table(VMMemoryTable { values: kabel, variable_id: 0 })); diff --git a/src/main.rs b/src/main.rs index 3de6c12..291e975 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,7 +10,7 @@ mod virtualmachine; mod errors; mod decompiler; -const CLIVER: [u8; 3] = [1,0,0]; +const CLIVER: [u8; 3] = [1,0,1]; #[derive(Debug, Clone)] struct Context { diff --git a/test.asl b/test.asl index 5b5aa9a..c56098e 100644 --- a/test.asl +++ b/test.asl @@ -1,11 +1,8 @@ -lőcsve test() { - lőcsve toast() { - ugass(2) - } - toast() - ugass(1) -} -gethelj k = krumpli.létrehoz(test) -ugass(krumpli.státusz(k)) -krumpli.folytat(k) -ugass(krumpli.státusz(k)) \ No newline at end of file +gethelj con = kábel.kapcsolódj(szaft"example.com:80"szaft) +con.írj(con, szaft"GET / HTTP/1.1 +User-Agent: Astro Lang +Host: example.com + +"szaft) +ugass(con.olvass(con, 5120)) +con.zár(con) \ No newline at end of file From 60ce82e68bebcb842b417fba440b96b5a12720eb Mon Sep 17 00:00:00 2001 From: afonya Date: Wed, 18 Jun 2025 19:37:47 +0200 Subject: [PATCH 19/19] fixed multi file error messages --- src/compiler.rs | 8 +++++--- src/main.rs | 2 +- test.asl | 10 ++-------- 3 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index d30d014..49110e5 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -32,7 +32,8 @@ struct Compiled { variables: Vec, strings: HashMap, functions: HashMap, - try_catch: Option + try_catch: Option, + ctx: Context } #[derive(Debug, Clone)] @@ -753,7 +754,8 @@ fn compile_function(ast: Vec, args: Option>, registers: &mu variables, strings, functions, - try_catch + try_catch, + ctx: ctx.clone(), }; } @@ -825,7 +827,7 @@ fn compile_body(compiled: Compiled, fpos: &mut usize, ctx: &Context) -> (Vec *fpos += 1; append_be_num(&mut output, 3, *funcs as usize); append_be_num(&mut output, 4, *fpos); - let (compiled, mut context) = compile_body(compiled.functions[funcs].clone(), fpos, ctx); + let (compiled, mut context) = compile_body(compiled.functions[funcs].clone(), fpos, &compiled.functions[funcs].ctx); for c in &mut context { c.c_funcid = *fpos } diff --git a/src/main.rs b/src/main.rs index 291e975..0b758b0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,7 +10,7 @@ mod virtualmachine; mod errors; mod decompiler; -const CLIVER: [u8; 3] = [1,0,1]; +const CLIVER: [u8; 3] = [1,0,2]; #[derive(Debug, Clone)] struct Context { diff --git a/test.asl b/test.asl index c56098e..3324140 100644 --- a/test.asl +++ b/test.asl @@ -1,8 +1,2 @@ -gethelj con = kábel.kapcsolódj(szaft"example.com:80"szaft) -con.írj(con, szaft"GET / HTTP/1.1 -User-Agent: Astro Lang -Host: example.com - -"szaft) -ugass(con.olvass(con, 5120)) -con.zár(con) \ No newline at end of file +hámozd test be szaft"test2.asl"szaft +gethelj a = szaft"asd"szaft+1 \ No newline at end of file