1335 lines
No EOL
56 KiB
Rust
1335 lines
No EOL
56 KiB
Rust
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::{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();
|
|
match mem {
|
|
VMMemory::String(s) => out.push_str(&s.value),
|
|
VMMemory::Number(n) => out.push_str(&n.value.to_string()),
|
|
VMMemory::Boolean(b) => out.push_str(if b.value { "true" } else { "false" }),
|
|
VMMemory::Null(_) => out.push_str("null"),
|
|
VMMemory::Table(tbl) => {
|
|
out.push_str("{");
|
|
for val in &tbl.values {
|
|
out.push_str(&get_string_from_vmmem(&val.key.clone()));
|
|
out.push_str("=");
|
|
out.push_str(&get_string_from_vmmem(&val.value.clone()));
|
|
out.push_str(", ");
|
|
}
|
|
out.pop();
|
|
out.pop();
|
|
out.push_str("}");
|
|
},
|
|
VMMemory::Function(func) => {
|
|
out.push_str("|function: ");
|
|
out.push_str(&func.id.to_string());
|
|
out.push_str("|");
|
|
},
|
|
VMMemory::NativeFunction(_) => {
|
|
out.push_str("|native function|");
|
|
},
|
|
}
|
|
return out;
|
|
}
|
|
fn get_type_str(mem: &VMMemory) -> String {
|
|
match mem {
|
|
VMMemory::String(_) => "string".to_string(),
|
|
VMMemory::Number(_) => "number".to_string(),
|
|
VMMemory::Boolean(_) => "boolean".to_string(),
|
|
VMMemory::Null(_) => "null".to_string(),
|
|
VMMemory::Table(_) => "table".to_string(),
|
|
VMMemory::Function(_) => "function".to_string(),
|
|
VMMemory::NativeFunction(_) => "native_function".to_string(),
|
|
}
|
|
}
|
|
fn arg_expect(args: &Vec<VMMemory>, pos: usize, expected_type: &str, machine: &Machine, op: &DecompiledOperation) {
|
|
if args.len() <= pos {
|
|
let err_str = format!("#{} expected {}, got nil", pos + 1, expected_type);
|
|
error(err_str, machine, op);
|
|
}
|
|
let err_str = format!("#{} expected {}, got {}", pos + 1, expected_type, get_type_str(&args[pos]));
|
|
if args.len() <= pos {
|
|
error(err_str.clone(), machine, op);
|
|
}
|
|
let actual_type = get_type_str(&args[pos]);
|
|
if actual_type != expected_type {
|
|
error(err_str, machine, op);
|
|
}
|
|
}
|
|
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);
|
|
process::exit(1);
|
|
}
|
|
fn set_mem_tbl_val(tbl: &mut VMMemoryTable, key: VMMemory, value: VMMemory) {
|
|
for i in 0..tbl.values.len() {
|
|
let found = match (&tbl.values[i].key, &key) {
|
|
(VMMemory::Number(num1), VMMemory::Number(num2)) => num1.value == num2.value,
|
|
(VMMemory::String(str1), VMMemory::String(str2)) => str1.value == str2.value,
|
|
(VMMemory::Boolean(bool1), VMMemory::Boolean(bool2)) => bool1.value == bool2.value,
|
|
(VMMemory::Null(_), VMMemory::Null(_)) => true,
|
|
(VMMemory::Function(_), VMMemory::Function(_)) => false,
|
|
(VMMemory::Table(_), VMMemory::Table(_)) => false,
|
|
(VMMemory::NativeFunction(_), VMMemory::NativeFunction(_)) => false,
|
|
_ => false,
|
|
};
|
|
if found {
|
|
tbl.values[i].value = value;
|
|
return;
|
|
}
|
|
}
|
|
tbl.values.push(TableValue { key, value });
|
|
}
|
|
fn get_mem_tbl_val(tbl: &VMMemoryTable, key: VMMemory) -> Option<&VMMemory> {
|
|
for i in 0..tbl.values.len() {
|
|
let found = match (&tbl.values[i].key, &key) {
|
|
(VMMemory::Number(num1), VMMemory::Number(num2)) => num1.value == num2.value,
|
|
(VMMemory::String(str1), VMMemory::String(str2)) => str1.value == str2.value,
|
|
(VMMemory::Boolean(bool1), VMMemory::Boolean(bool2)) => bool1.value == bool2.value,
|
|
(VMMemory::Null(_), VMMemory::Null(_)) => true,
|
|
(VMMemory::Function(_), VMMemory::Function(_)) => false,
|
|
(VMMemory::Table(_), VMMemory::Table(_)) => false,
|
|
(VMMemory::NativeFunction(_), VMMemory::NativeFunction(_)) => false,
|
|
_ => false,
|
|
};
|
|
if found {
|
|
return Some(&tbl.values[i].value);
|
|
}
|
|
}
|
|
None
|
|
}
|
|
fn convert_type(mem: &VMMemory, target_type: &str) -> VMMemory {
|
|
match (mem, target_type) {
|
|
(VMMemory::String(s), "string") => {
|
|
VMMemory::String(VMMemoryString { value: s.value.clone(), variable_id: 0 })
|
|
},
|
|
(VMMemory::String(s), "number") => {
|
|
match s.value.parse::<f64>() {
|
|
Ok(num) => VMMemory::Number(VMMemoryNumber { value: num, variable_id: 0 }),
|
|
Err(_) => VMMemory::Null(VMMemoryNull { variable_id: 0 }),
|
|
}
|
|
},
|
|
(VMMemory::String(s), "boolean") => {
|
|
if s.value.to_lowercase() == "true" {
|
|
VMMemory::Boolean(VMMemoryBoolean { value: true, variable_id: 0 })
|
|
} else if s.value.to_lowercase() == "false" {
|
|
VMMemory::Boolean(VMMemoryBoolean { value: false, variable_id: 0 })
|
|
} else {
|
|
VMMemory::Null(VMMemoryNull { variable_id: 0 })
|
|
}
|
|
},
|
|
(VMMemory::Number(n), "string") => {
|
|
VMMemory::String(VMMemoryString { value: n.value.to_string(), variable_id: 0 })
|
|
},
|
|
(VMMemory::Number(n), "number") => {
|
|
VMMemory::Number(VMMemoryNumber { value: n.value, variable_id: 0 })
|
|
},
|
|
(VMMemory::Number(n), "boolean") => {
|
|
if n.value != 0.0 {
|
|
VMMemory::Boolean(VMMemoryBoolean { value: true, variable_id: 0 })
|
|
} else {
|
|
VMMemory::Boolean(VMMemoryBoolean { value: false, variable_id: 0 })
|
|
}
|
|
},
|
|
(VMMemory::Boolean(b), "string") => {
|
|
VMMemory::String(VMMemoryString { value: b.value.to_string(), variable_id: 0 })
|
|
},
|
|
(VMMemory::Boolean(b), "number") => {
|
|
if b.value {
|
|
VMMemory::Number(VMMemoryNumber { value: 1.0, variable_id: 0 })
|
|
} else {
|
|
VMMemory::Number(VMMemoryNumber { value: 0.0, variable_id: 0 })
|
|
}
|
|
},
|
|
(VMMemory::Boolean(b), "boolean") => {
|
|
VMMemory::Boolean(VMMemoryBoolean { value: b.value, variable_id: 0 })
|
|
},
|
|
(VMMemory::Null(_), "string") => {
|
|
VMMemory::String(VMMemoryString { value: String::from("null"), variable_id: 0 })
|
|
},
|
|
(VMMemory::Null(_), "number") => {
|
|
VMMemory::Number(VMMemoryNumber { value: 0.0, variable_id: 0 })
|
|
},
|
|
(VMMemory::Null(_), "boolean") => {
|
|
VMMemory::Boolean(VMMemoryBoolean { value: false, variable_id: 0 })
|
|
},
|
|
_ => VMMemory::Null(VMMemoryNull { variable_id: 0 })
|
|
}
|
|
}
|
|
|
|
fn ugass(_machine: &mut Machine, _op: &DecompiledOperation, args: Vec<VMMemory>) -> VMMemory {
|
|
let mut out = String::new();
|
|
for arg in args {
|
|
out.push_str(&get_string_from_vmmem(&arg));
|
|
out.push_str(" ");
|
|
}
|
|
println!("{}", out.trim_end());
|
|
return VMMemory::Null(VMMemoryNull { variable_id: 0 });
|
|
}
|
|
fn bimba(machine: &mut Machine, op: &DecompiledOperation, args: Vec<VMMemory>) -> VMMemory {
|
|
arg_expect(&args, 0, "number", machine, op);
|
|
match &args[0] {
|
|
VMMemory::Number(n) => {
|
|
sleep(Duration::from_millis(n.value as u64));
|
|
},
|
|
_ => {}
|
|
}
|
|
return VMMemory::Null(VMMemoryNull { variable_id: 0 });
|
|
}
|
|
fn csomor(machine: &mut Machine, op: &DecompiledOperation, args: Vec<VMMemory>) -> VMMemory {
|
|
arg_expect(&args, 0, "string", machine, op);
|
|
match &args[0] {
|
|
VMMemory::String(s) => {
|
|
error(s.value.clone(), machine, op);
|
|
},
|
|
_ => {}
|
|
}
|
|
return VMMemory::Null(VMMemoryNull { variable_id: 0 });
|
|
}
|
|
fn tarh(_machine: &mut Machine, _op: &DecompiledOperation, args: Vec<VMMemory>) -> VMMemory {
|
|
if args.len() < 1 {
|
|
return VMMemory::String(VMMemoryString { value: String::from("null"), variable_id: 0 });
|
|
}
|
|
return VMMemory::String(VMMemoryString { value: get_type_str(&args[0]), variable_id: 0 });
|
|
}
|
|
fn bimbabemb(machine: &mut Machine, op: &DecompiledOperation, args: Vec<VMMemory>) -> VMMemory {
|
|
arg_expect(&args, 1, "string", machine, op);
|
|
let val = args[0].clone();
|
|
let target = match &args[1] {
|
|
VMMemory::String(s) => s.value.clone(),
|
|
_ => String::new()
|
|
};
|
|
return convert_type(&val, &target);
|
|
}
|
|
fn mennyiazido(machine: &mut Machine, op: &DecompiledOperation, _args: Vec<VMMemory>) -> 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>) -> 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>) -> VMMemory {
|
|
arg_expect(&args, 0, "number", machine, op);
|
|
match &args[0] {
|
|
VMMemory::Number(n) => {
|
|
return VMMemory::Number(VMMemoryNumber { value: n.value.abs(), variable_id: 0 });
|
|
},
|
|
_ => {}
|
|
}
|
|
return VMMemory::Null(VMMemoryNull { variable_id: 0 });
|
|
}
|
|
fn nerd_kerek(machine: &mut Machine, op: &DecompiledOperation, args: Vec<VMMemory>) -> VMMemory {
|
|
arg_expect(&args, 0, "number", machine, op);
|
|
arg_expect(&args, 1, "string", machine, op);
|
|
let num = match &args[0] {
|
|
VMMemory::Number(n) => n.value,
|
|
_ => {
|
|
error(String::from("Expected a number"), machine, op);
|
|
return VMMemory::Null(VMMemoryNull { variable_id: 0 });
|
|
}
|
|
};
|
|
let mode = match &args[1] {
|
|
VMMemory::String(s) => s.value.clone(),
|
|
_ => {
|
|
error(String::from("Expected a string"), machine, op);
|
|
return VMMemory::Null(VMMemoryNull { variable_id: 0 });
|
|
}
|
|
};
|
|
let rounded = match mode.as_str() {
|
|
"fel" => num.ceil(),
|
|
"le" => num.floor(),
|
|
"közel" => num.round(),
|
|
_ => {
|
|
error(format!("Unknown rounding mode: {}", mode), machine, op);
|
|
return VMMemory::Null(VMMemoryNull { variable_id: 0 });
|
|
}
|
|
};
|
|
return VMMemory::Number(VMMemoryNumber { value: rounded, variable_id: 0 });
|
|
}
|
|
fn nerd_sin(machine: &mut Machine, op: &DecompiledOperation, args: Vec<VMMemory>) -> VMMemory {
|
|
arg_expect(&args, 0, "number", machine, op);
|
|
let num = match &args[0] {
|
|
VMMemory::Number(n) => n.value,
|
|
_ => {
|
|
error(String::from("Expected a number"), machine, op);
|
|
return VMMemory::Null(VMMemoryNull { variable_id: 0 });
|
|
}
|
|
};
|
|
let result = num.sin();
|
|
return VMMemory::Number(VMMemoryNumber { value: result, variable_id: 0 });
|
|
}
|
|
fn nerd_cos(machine: &mut Machine, op: &DecompiledOperation, args: Vec<VMMemory>) -> VMMemory {
|
|
arg_expect(&args, 0, "number", machine, op);
|
|
let num = match &args[0] {
|
|
VMMemory::Number(n) => n.value,
|
|
_ => {
|
|
error(String::from("Expected a number"), machine, op);
|
|
return VMMemory::Null(VMMemoryNull { variable_id: 0 });
|
|
}
|
|
};
|
|
let result = num.cos();
|
|
return VMMemory::Number(VMMemoryNumber { value: result, variable_id: 0 });
|
|
}
|
|
fn nerd_tan(machine: &mut Machine, op: &DecompiledOperation, args: Vec<VMMemory>) -> VMMemory {
|
|
arg_expect(&args, 0, "number", machine, op);
|
|
let num = match &args[0] {
|
|
VMMemory::Number(n) => n.value,
|
|
_ => {
|
|
error(String::from("Expected a number"), machine, op);
|
|
return VMMemory::Null(VMMemoryNull { variable_id: 0 });
|
|
}
|
|
};
|
|
let result = num.tan();
|
|
return VMMemory::Number(VMMemoryNumber { value: result, variable_id: 0 });
|
|
}
|
|
fn nerd_sqrt(machine: &mut Machine, op: &DecompiledOperation, args: Vec<VMMemory>) -> VMMemory {
|
|
arg_expect(&args, 0, "number", machine, op);
|
|
let num = match &args[0] {
|
|
VMMemory::Number(n) => n.value,
|
|
_ => {
|
|
error(String::from("Expected a number"), machine, op);
|
|
return VMMemory::Null(VMMemoryNull { variable_id: 0 });
|
|
}
|
|
};
|
|
let result = num.sqrt();
|
|
return VMMemory::Number(VMMemoryNumber { value: result, variable_id: 0 });
|
|
}
|
|
fn nerd_legnagyobb(machine: &mut Machine, op: &DecompiledOperation, args: Vec<VMMemory>) -> VMMemory {
|
|
arg_expect(&args, 0, "number", machine, op);
|
|
let mut nums = Vec::new();
|
|
for arg in 0..args.len() {
|
|
match &args[arg] {
|
|
VMMemory::Number(n) => nums.push(n.value),
|
|
_ => {
|
|
error(format!("#{} expected number, got {}", arg, get_type_str(&args[arg])), machine, op);
|
|
return VMMemory::Null(VMMemoryNull { variable_id: 0 });
|
|
}
|
|
}
|
|
}
|
|
let mut result: f64 = 0.0;
|
|
let mut first = true;
|
|
for num in nums {
|
|
if first || num > result {
|
|
result = num;
|
|
}
|
|
first = false;
|
|
}
|
|
return VMMemory::Number(VMMemoryNumber { value: result, variable_id: 0 });
|
|
}
|
|
fn nerd_legkisebb(machine: &mut Machine, op: &DecompiledOperation, args: Vec<VMMemory>) -> VMMemory {
|
|
arg_expect(&args, 0, "number", machine, op);
|
|
let mut nums = Vec::new();
|
|
for arg in 0..args.len() {
|
|
match &args[arg] {
|
|
VMMemory::Number(n) => nums.push(n.value),
|
|
_ => {
|
|
error(format!("#{} expected number, got {}", arg, get_type_str(&args[arg])), machine, op);
|
|
return VMMemory::Null(VMMemoryNull { variable_id: 0 });
|
|
}
|
|
}
|
|
}
|
|
let mut result: f64 = 0.0;
|
|
let mut first = true;
|
|
for num in nums {
|
|
if first || num < result {
|
|
result = num;
|
|
}
|
|
first = false;
|
|
}
|
|
return VMMemory::Number(VMMemoryNumber { value: result, variable_id: 0 });
|
|
}
|
|
|
|
fn kabel_olvass(machine: &mut Machine, op: &DecompiledOperation, args: Vec<VMMemory>) -> VMMemory {
|
|
arg_expect(&args, 0, "table", machine, op);
|
|
arg_expect(&args, 1, "number", machine, op);
|
|
let id = match &args[0] {
|
|
VMMemory::Table(tbl) => {
|
|
get_mem_tbl_val(tbl, VMMemory::String(VMMemoryString { value: String::from("id"), variable_id: 0 }))
|
|
},
|
|
_ => None
|
|
};
|
|
if id.is_none() {
|
|
error(String::from("Stream not found"), machine, op);
|
|
}
|
|
let real_id = match &id.unwrap() {
|
|
VMMemory::Number(n) => n.value as usize,
|
|
_ => {
|
|
error(String::from("Stream is not a number"), machine, op);
|
|
0
|
|
}
|
|
};
|
|
let stored_stream = machine.storage.get(real_id);
|
|
if stored_stream.is_none() {
|
|
error(String::from("Stream not found in storage"), machine, op);
|
|
}
|
|
let boxed_stream = stored_stream.unwrap();
|
|
let stream = boxed_stream.downcast_ref::<TcpStream>();
|
|
if stream.is_none() {
|
|
error(String::from("Stream is not a TcpStream"), machine, op);
|
|
}
|
|
let stream = stream.unwrap();
|
|
let mut reader = BufReader::new(stream);
|
|
let len = match &args[1] {
|
|
VMMemory::Number(n) => n.value as usize,
|
|
_ => 1024
|
|
};
|
|
let mut buf: Vec<u8> = vec![0; len];
|
|
match reader.read(&mut buf) {
|
|
Ok(_) => {},
|
|
Err(e) => {
|
|
error(format!("Failed to read from stream: {}", e), machine, op);
|
|
return VMMemory::Null(VMMemoryNull { variable_id: 0 });
|
|
}
|
|
}
|
|
let str = match String::from_utf8(buf) {
|
|
Ok(s) => s,
|
|
Err(_) => {
|
|
error(String::from("Stream data is not valid UTF-8"), machine, op);
|
|
String::new()
|
|
}
|
|
};
|
|
return VMMemory::String(VMMemoryString { value: str, variable_id: 0 });
|
|
}
|
|
fn kabel_irj(machine: &mut Machine, op: &DecompiledOperation, args: Vec<VMMemory>) -> VMMemory {
|
|
arg_expect(&args, 0, "table", machine, op);
|
|
arg_expect(&args, 1, "string", machine, op);
|
|
let id = match &args[0] {
|
|
VMMemory::Table(tbl) => {
|
|
get_mem_tbl_val(tbl, VMMemory::String(VMMemoryString { value: String::from("id"), variable_id: 0 }))
|
|
},
|
|
_ => None
|
|
};
|
|
if id.is_none() {
|
|
error(String::from("Stream not found"), machine, op);
|
|
}
|
|
let real_id = match &id.unwrap() {
|
|
VMMemory::Number(n) => n.value as usize,
|
|
_ => {
|
|
error(String::from("Stream is not a number"), machine, op);
|
|
0
|
|
}
|
|
};
|
|
let stored_stream = machine.storage.get(real_id);
|
|
if stored_stream.is_none() {
|
|
error(String::from("Stream not found in storage"), machine, op);
|
|
}
|
|
let boxed_stream = stored_stream.unwrap();
|
|
let stream = boxed_stream.downcast_ref::<TcpStream>();
|
|
if stream.is_none() {
|
|
error(String::from("Stream is not a TcpStream"), machine, op);
|
|
}
|
|
let mut stream = stream.unwrap();
|
|
let write = match &args[1] {
|
|
VMMemory::String(s) => s.value.clone(),
|
|
_ => String::new()
|
|
};
|
|
match stream.write_all(write.as_bytes()) {
|
|
Ok(_) => {},
|
|
Err(e) => {
|
|
error(format!("Failed to write to stream: {}", e), machine, op);
|
|
return VMMemory::Null(VMMemoryNull { variable_id: 0 });
|
|
}
|
|
}
|
|
return VMMemory::Null(VMMemoryNull { variable_id: 0 });
|
|
}
|
|
fn kabel_zar(machine: &mut Machine, op: &DecompiledOperation, args: Vec<VMMemory>) -> VMMemory {
|
|
arg_expect(&args, 0, "table", machine, op);
|
|
let id = match &args[0] {
|
|
VMMemory::Table(tbl) => {
|
|
get_mem_tbl_val(tbl, VMMemory::String(VMMemoryString { value: String::from("id"), variable_id: 0 }))
|
|
},
|
|
_ => None
|
|
};
|
|
if id.is_none() {
|
|
error(String::from("Stream not found"), machine, op);
|
|
}
|
|
let real_id = match &id.unwrap() {
|
|
VMMemory::Number(n) => n.value as usize,
|
|
_ => {
|
|
error(String::from("Stream is not a number"), machine, op);
|
|
0
|
|
}
|
|
};
|
|
let stored_stream = machine.storage.get(real_id);
|
|
if stored_stream.is_none() {
|
|
error(String::from("Stream not found in storage"), machine, op);
|
|
}
|
|
let boxed_stream = stored_stream.unwrap();
|
|
let stream = boxed_stream.downcast_ref::<TcpStream>();
|
|
if stream.is_none() {
|
|
error(String::from("Stream is not a TcpStream"), machine, op);
|
|
}
|
|
let listener = stream.unwrap();
|
|
match listener.shutdown(net::Shutdown::Both) {
|
|
Ok(_) => {},
|
|
Err(e) => {
|
|
error(format!("Failed to close stream: {}", e), machine, op);
|
|
return VMMemory::Null(VMMemoryNull { variable_id: 0 });
|
|
}
|
|
};
|
|
return VMMemory::Null(VMMemoryNull { variable_id: 0 });
|
|
}
|
|
fn kabel_keres(machine: &mut Machine, op: &DecompiledOperation, args: Vec<VMMemory>) -> VMMemory {
|
|
arg_expect(&args, 0, "table", machine, op);
|
|
let id = match &args[0] {
|
|
VMMemory::Table(tbl) => {
|
|
get_mem_tbl_val(tbl, VMMemory::String(VMMemoryString { value: String::from("id"), variable_id: 0 }))
|
|
},
|
|
_ => None
|
|
};
|
|
if id.is_none() {
|
|
error(String::from("Halgató not found"), machine, op);
|
|
}
|
|
let real_id = match &id.unwrap() {
|
|
VMMemory::Number(n) => n.value as usize,
|
|
_ => {
|
|
error(String::from("Halgató is not a number"), machine, op);
|
|
0
|
|
}
|
|
};
|
|
let stored_listener = machine.storage.get(real_id);
|
|
if stored_listener.is_none() {
|
|
error(String::from("Halgató not found in storage"), machine, op);
|
|
}
|
|
let boxed_listener = stored_listener.unwrap();
|
|
let listener = boxed_listener.downcast_ref::<TcpListener>();
|
|
if listener.is_none() {
|
|
error(String::from("Halgató is not a TcpListener"), machine, op);
|
|
}
|
|
let listener = listener.unwrap();
|
|
for stream in listener.incoming() {
|
|
let stream = stream.unwrap();
|
|
machine.storage.push(Box::new(stream));
|
|
let ret_table: Vec<TableValue> = 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 });
|
|
}
|
|
return VMMemory::Null(VMMemoryNull { variable_id: 0 });
|
|
}
|
|
fn kabel_kapcsolodj(machine: &mut Machine, op: &DecompiledOperation, args: Vec<VMMemory>) -> 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<TableValue> = 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>) -> VMMemory {
|
|
arg_expect(&args, 0, "string", machine, op);
|
|
arg_expect(&args, 1, "number", machine, op);
|
|
let host = match &args[0] {
|
|
VMMemory::String(s) => s.value.clone(),
|
|
_ => String::from("0.0.0.0")
|
|
};
|
|
let port = match &args[1] {
|
|
VMMemory::Number(n) => n.value as u16,
|
|
_ => 1010
|
|
};
|
|
let listener = net::TcpListener::bind(host + ":" + &port.to_string()).unwrap();
|
|
machine.storage.push(Box::new(listener));
|
|
let ret_table: Vec<TableValue> = vec![
|
|
TableValue {
|
|
key: VMMemory::String(VMMemoryString { value: String::from("kérés"), variable_id: 0 }),
|
|
value: VMMemory::NativeFunction(VMMemoryNativeFunction { func: kabel_keres, 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 szaft_csemerdfel(machine: &mut Machine, op: &DecompiledOperation, args: Vec<VMMemory>) -> VMMemory {
|
|
arg_expect(&args, 0, "string", machine, op);
|
|
let str = match &args[0] {
|
|
VMMemory::String(s) => s.value.clone(),
|
|
_ => String::new()
|
|
};
|
|
return VMMemory::String(VMMemoryString { value: str.to_uppercase(), variable_id: 0 });
|
|
}
|
|
fn szaft_csemerdle(machine: &mut Machine, op: &DecompiledOperation, args: Vec<VMMemory>) -> VMMemory {
|
|
arg_expect(&args, 0, "string", machine, op);
|
|
let str = match &args[0] {
|
|
VMMemory::String(s) => s.value.clone(),
|
|
_ => String::new()
|
|
};
|
|
return VMMemory::String(VMMemoryString { value: str.to_lowercase(), variable_id: 0 });
|
|
}
|
|
fn szaft_hossz(machine: &mut Machine, op: &DecompiledOperation, args: Vec<VMMemory>) -> VMMemory {
|
|
arg_expect(&args, 0, "string", machine, op);
|
|
let str = match &args[0] {
|
|
VMMemory::String(s) => s.value.clone(),
|
|
_ => String::new()
|
|
};
|
|
return VMMemory::Number(VMMemoryNumber { value: str.len() as f64, variable_id: 0 });
|
|
}
|
|
fn szaft_ismeteld(machine: &mut Machine, op: &DecompiledOperation, args: Vec<VMMemory>) -> VMMemory {
|
|
arg_expect(&args, 0, "string", machine, op);
|
|
arg_expect(&args, 1, "number", machine, op);
|
|
let str = match &args[0] {
|
|
VMMemory::String(s) => s.value.clone(),
|
|
_ => String::new()
|
|
};
|
|
let times = match &args[1] {
|
|
VMMemory::Number(n) => n.value as usize,
|
|
_ => 1
|
|
};
|
|
return VMMemory::String(VMMemoryString { value: str.repeat(times), variable_id: 0 });
|
|
}
|
|
fn szaft_unoreverse(machine: &mut Machine, op: &DecompiledOperation, args: Vec<VMMemory>) -> VMMemory {
|
|
arg_expect(&args, 0, "string", machine, op);
|
|
let str = match &args[0] {
|
|
VMMemory::String(s) => s.value.clone(),
|
|
_ => String::new()
|
|
};
|
|
return VMMemory::String(VMMemoryString { value: str.chars().rev().collect(), variable_id: 0 });
|
|
}
|
|
fn szaft_darabos(machine: &mut Machine, op: &DecompiledOperation, args: Vec<VMMemory>) -> VMMemory {
|
|
arg_expect(&args, 0, "string", machine, op);
|
|
arg_expect(&args, 1, "number", machine, op);
|
|
arg_expect(&args, 2, "number", machine, op);
|
|
let str = match &args[0] {
|
|
VMMemory::String(s) => s.value.clone(),
|
|
_ => String::new()
|
|
};
|
|
let num1 = match &args[1] {
|
|
VMMemory::Number(n) => n.value as usize,
|
|
_ => 0
|
|
};
|
|
let num2 = match &args[2] {
|
|
VMMemory::Number(n) => n.value as usize,
|
|
_ => 0
|
|
};
|
|
return VMMemory::String(VMMemoryString { value: str[num1..num2].to_string(), variable_id: 0 });
|
|
}
|
|
fn szaft_keres(machine: &mut Machine, op: &DecompiledOperation, args: Vec<VMMemory>) -> 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()
|
|
};
|
|
return VMMemory::Boolean(VMMemoryBoolean { value: str.contains(&str2), variable_id: 0 });
|
|
}
|
|
fn szaft_atrak(machine: &mut Machine, op: &DecompiledOperation, args: Vec<VMMemory>) -> VMMemory {
|
|
arg_expect(&args, 0, "string", machine, op);
|
|
arg_expect(&args, 1, "string", machine, op);
|
|
arg_expect(&args, 2, "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()
|
|
};
|
|
let str3 = match &args[2] {
|
|
VMMemory::String(s) => s.value.clone(),
|
|
_ => String::new()
|
|
};
|
|
return VMMemory::String(VMMemoryString { value: str.replace(&str2, &str3), variable_id: 0 });
|
|
}
|
|
fn szaft_szamma(machine: &mut Machine, op: &DecompiledOperation, args: Vec<VMMemory>) -> VMMemory {
|
|
arg_expect(&args, 0, "string", machine, op);
|
|
arg_expect(&args, 1, "number", machine, op);
|
|
let str = match &args[0] {
|
|
VMMemory::String(s) => s.value.clone(),
|
|
_ => String::new()
|
|
};
|
|
let num = match &args[1] {
|
|
VMMemory::Number(n) => n.value as usize,
|
|
_ => 0
|
|
};
|
|
return VMMemory::Number(VMMemoryNumber { value: str.as_bytes()[num] as f64, variable_id: 0 });
|
|
}
|
|
fn szaft_betuve(machine: &mut Machine, op: &DecompiledOperation, args: Vec<VMMemory>) -> VMMemory {
|
|
arg_expect(&args, 0, "number", machine, op);
|
|
let num = match &args[0] {
|
|
VMMemory::Number(n) => n.value as usize,
|
|
_ => 0
|
|
};
|
|
let str = match String::from_utf8(vec![num.try_into().unwrap()]) {
|
|
Ok(s) => s,
|
|
Err(_) => {
|
|
error(String::from("Invalid UTF-8 sequence"), machine, op);
|
|
return VMMemory::Null(VMMemoryNull { variable_id: 0 });
|
|
}
|
|
};
|
|
return VMMemory::String(VMMemoryString { value: str, variable_id: 0 })
|
|
}
|
|
|
|
fn tabla_hozzaad(machine: &mut Machine, op: &DecompiledOperation, args: Vec<VMMemory>) -> VMMemory {
|
|
arg_expect(&args, 0, "table", machine, op);
|
|
let mut tbl = match &args[0] {
|
|
VMMemory::Table(tbl) => tbl.clone(),
|
|
_ => {
|
|
error(String::from("Expected a table"), machine, op);
|
|
return VMMemory::Null(VMMemoryNull { variable_id: 0 });
|
|
}
|
|
};
|
|
if args.len() < 2 {
|
|
error(String::from("Expected at least 2 arguments"), machine, op);
|
|
return VMMemory::Null(VMMemoryNull { variable_id: 0 });
|
|
}
|
|
let val = &args[1];
|
|
let mut next_index = 0;
|
|
for kv in &tbl.values {
|
|
if let VMMemory::Number(n) = &kv.key {
|
|
if n.value as usize > next_index {
|
|
next_index = (n.value as usize) + 1;
|
|
}
|
|
}
|
|
}
|
|
tbl.values.push(TableValue { key: VMMemory::Number(VMMemoryNumber { value: next_index as f64, variable_id: 0 }), value: val.clone() });
|
|
return VMMemory::Table(VMMemoryTable { values: tbl.values.clone(), variable_id: 0 });
|
|
}
|
|
fn tabla_torol(machine: &mut Machine, op: &DecompiledOperation, args: Vec<VMMemory>) -> VMMemory {
|
|
arg_expect(&args, 0, "table", machine, op);
|
|
arg_expect(&args, 1, "number", machine, op);
|
|
let mut 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 num = match &args[1] {
|
|
VMMemory::Number(n) => n.value as usize,
|
|
_ => {
|
|
error(String::from("Expected a number"), machine, op);
|
|
return VMMemory::Null(VMMemoryNull { variable_id: 0 });
|
|
}
|
|
};
|
|
for i in 0..tbl.values.len() {
|
|
let kv = &tbl.values[i];
|
|
if let VMMemory::Number(n) = &kv.key {
|
|
if n.value as usize == num {
|
|
tbl.values.remove(i);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return VMMemory::Table(VMMemoryTable { values: tbl.values.clone(), variable_id: 0 });
|
|
}
|
|
fn tabla_kulcsok(machine: &mut Machine, op: &DecompiledOperation, args: Vec<VMMemory>) -> 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 keys = VMMemoryTable {
|
|
values: vec![],
|
|
variable_id: 0,
|
|
};
|
|
for kv in &tbl.values {
|
|
keys.values.push(TableValue { key: VMMemory::Number(VMMemoryNumber { value: keys.values.len() as f64, variable_id: 0 }), value: kv.key.clone() });
|
|
}
|
|
return VMMemory::Table(keys);
|
|
}
|
|
fn tabla_ertekek(machine: &mut Machine, op: &DecompiledOperation, args: Vec<VMMemory>) -> 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>) -> 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>) -> 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 });
|
|
}
|
|
};
|
|
process::exit(num as i32);
|
|
}
|
|
|
|
fn intezo_letezik(machine: &mut Machine, op: &DecompiledOperation, args: Vec<VMMemory>) -> 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>) -> 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 get file metadata: {}", e), machine, op);
|
|
return VMMemory::Null(VMMemoryNull { variable_id: 0 });
|
|
}
|
|
};
|
|
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<String, VMMemory> = 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);
|
|
}
|
|
fn intezo_mappit(machine: &mut Machine, op: &DecompiledOperation, args: Vec<VMMemory>) -> 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>) -> 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(&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>) -> 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>) -> 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>) -> 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 });
|
|
}
|
|
|
|
fn krumpli_varj(machine: &mut Machine, _op: &DecompiledOperation, _args: Vec<VMMemory>) -> VMMemory {
|
|
machine.state = VMState::Paused;
|
|
return VMMemory::Null(VMMemoryNull { variable_id: 0 });
|
|
}
|
|
fn add_func(n_funcs: &mut Vec<DecompiledFunction>, n_ctx: &mut Vec<Context>, 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());
|
|
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.insert(start, exe_func);
|
|
}
|
|
fn krumpli_letrehoz(machine: &mut Machine, op: &DecompiledOperation, args: Vec<VMMemory>) -> 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<DecompiledFunction> = vec![];
|
|
let mut n_ctx: Vec<Context> = vec![];
|
|
add_func(&mut n_funcs, &mut n_ctx, machine, func.id, &mut 0);
|
|
let mut vm = Machine::new(n_ctx);
|
|
vm.load_functions(n_funcs);
|
|
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>) -> 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::<Machine>();
|
|
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();
|
|
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>) -> 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::<Machine>();
|
|
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<String, VMMemory> = 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<TableValue> = 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<String, VMMemory> {
|
|
let mut mem: HashMap<String, VMMemory> = HashMap::new();
|
|
|
|
mem.insert(String::from("ugass"), VMMemory::NativeFunction(VMMemoryNativeFunction { func: ugass, variable_id: 0 }));
|
|
mem.insert(String::from("bimba"), VMMemory::NativeFunction(VMMemoryNativeFunction { func: bimba, variable_id: 0 }));
|
|
mem.insert(String::from("csömör"), VMMemory::NativeFunction(VMMemoryNativeFunction { func: csomor, variable_id: 0 }));
|
|
mem.insert(String::from("tarh"), VMMemory::NativeFunction(VMMemoryNativeFunction { func: tarh, variable_id: 0 }));
|
|
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<TableValue> = vec![
|
|
TableValue {
|
|
key: VMMemory::String(VMMemoryString { value: String::from("abs"), variable_id: 0 }),
|
|
value: VMMemory::NativeFunction(VMMemoryNativeFunction { func: nerd_abs, variable_id: 0 }),
|
|
},
|
|
TableValue {
|
|
key: VMMemory::String(VMMemoryString { value: String::from("kerek"), variable_id: 0 }),
|
|
value: VMMemory::NativeFunction(VMMemoryNativeFunction { func: nerd_kerek, variable_id: 0 }),
|
|
},
|
|
TableValue {
|
|
key: VMMemory::String(VMMemoryString { value: String::from("sin"), variable_id: 0 }),
|
|
value: VMMemory::NativeFunction(VMMemoryNativeFunction { func: nerd_sin, variable_id: 0 }),
|
|
},
|
|
TableValue {
|
|
key: VMMemory::String(VMMemoryString { value: String::from("cos"), variable_id: 0 }),
|
|
value: VMMemory::NativeFunction(VMMemoryNativeFunction { func: nerd_cos, variable_id: 0 }),
|
|
},
|
|
TableValue {
|
|
key: VMMemory::String(VMMemoryString { value: String::from("tan"), variable_id: 0 }),
|
|
value: VMMemory::NativeFunction(VMMemoryNativeFunction { func: nerd_tan, variable_id: 0 }),
|
|
},
|
|
TableValue {
|
|
key: VMMemory::String(VMMemoryString { value: String::from("sqrt"), variable_id: 0 }),
|
|
value: VMMemory::NativeFunction(VMMemoryNativeFunction { func: nerd_sqrt, variable_id: 0 }),
|
|
},
|
|
TableValue {
|
|
key: VMMemory::String(VMMemoryString { value: String::from("legnagyobb"), variable_id: 0 }),
|
|
value: VMMemory::NativeFunction(VMMemoryNativeFunction { func: nerd_legnagyobb, variable_id: 0 }),
|
|
},
|
|
TableValue {
|
|
key: VMMemory::String(VMMemoryString { value: String::from("legkisebb"), variable_id: 0 }),
|
|
value: VMMemory::NativeFunction(VMMemoryNativeFunction { func: nerd_legkisebb, variable_id: 0 }),
|
|
},
|
|
TableValue {
|
|
key: VMMemory::String(VMMemoryString { value: String::from("pi"), variable_id: 0 }),
|
|
value: VMMemory::Number(VMMemoryNumber { value: std::f64::consts::PI, variable_id: 0 }),
|
|
}
|
|
];
|
|
mem.insert(String::from("nerd"), VMMemory::Table(VMMemoryTable { values: nerd, variable_id: 0 }));
|
|
|
|
let kabel: Vec<TableValue> = vec![
|
|
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 }));
|
|
|
|
let szaft: Vec<TableValue> = vec![
|
|
TableValue {
|
|
key: VMMemory::String(VMMemoryString { value: String::from("csemerd fel"), variable_id: 0 }),
|
|
value: VMMemory::NativeFunction(VMMemoryNativeFunction { func: szaft_csemerdfel, variable_id: 0 }),
|
|
},
|
|
TableValue {
|
|
key: VMMemory::String(VMMemoryString { value: String::from("csemerd le"), variable_id: 0 }),
|
|
value: VMMemory::NativeFunction(VMMemoryNativeFunction { func: szaft_csemerdle, variable_id: 0 }),
|
|
},
|
|
TableValue {
|
|
key: VMMemory::String(VMMemoryString { value: String::from("hossz"), variable_id: 0 }),
|
|
value: VMMemory::NativeFunction(VMMemoryNativeFunction { func: szaft_hossz, variable_id: 0 }),
|
|
},
|
|
TableValue {
|
|
key: VMMemory::String(VMMemoryString { value: String::from("ismételd"), variable_id: 0 }),
|
|
value: VMMemory::NativeFunction(VMMemoryNativeFunction { func: szaft_ismeteld, variable_id: 0 }),
|
|
},
|
|
TableValue {
|
|
key: VMMemory::String(VMMemoryString { value: String::from("uno reverse"), variable_id: 0 }),
|
|
value: VMMemory::NativeFunction(VMMemoryNativeFunction { func: szaft_unoreverse, variable_id: 0 }),
|
|
},
|
|
TableValue {
|
|
key: VMMemory::String(VMMemoryString { value: String::from("darabos"), variable_id: 0 }),
|
|
value: VMMemory::NativeFunction(VMMemoryNativeFunction { func: szaft_darabos, variable_id: 0 }),
|
|
},
|
|
TableValue {
|
|
key: VMMemory::String(VMMemoryString { value: String::from("keres"), variable_id: 0 }),
|
|
value: VMMemory::NativeFunction(VMMemoryNativeFunction { func: szaft_keres, variable_id: 0 }),
|
|
},
|
|
TableValue {
|
|
key: VMMemory::String(VMMemoryString { value: String::from("átrak"), variable_id: 0 }),
|
|
value: VMMemory::NativeFunction(VMMemoryNativeFunction { func: szaft_atrak, variable_id: 0 }),
|
|
},
|
|
TableValue {
|
|
key: VMMemory::String(VMMemoryString { value: String::from("számmá"), variable_id: 0 }),
|
|
value: VMMemory::NativeFunction(VMMemoryNativeFunction { func: szaft_szamma, variable_id: 0 }),
|
|
},
|
|
TableValue {
|
|
key: VMMemory::String(VMMemoryString { value: String::from("betűvé"), variable_id: 0 }),
|
|
value: VMMemory::NativeFunction(VMMemoryNativeFunction { func: szaft_betuve, variable_id: 0 }),
|
|
}
|
|
];
|
|
mem.insert(String::from("szaft"), VMMemory::Table(VMMemoryTable { values: szaft, variable_id: 0 }));
|
|
|
|
let table: Vec<TableValue> = vec![
|
|
TableValue {
|
|
key: VMMemory::String(VMMemoryString { value: String::from("hozzáad"), variable_id: 0 }),
|
|
value: VMMemory::NativeFunction(VMMemoryNativeFunction { func: tabla_hozzaad, variable_id: 0 }),
|
|
},
|
|
TableValue {
|
|
key: VMMemory::String(VMMemoryString { value: String::from("töröl"), variable_id: 0 }),
|
|
value: VMMemory::NativeFunction(VMMemoryNativeFunction { func: tabla_torol, variable_id: 0 }),
|
|
},
|
|
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 }));
|
|
|
|
let szenvedes: Vec<TableValue> = vec![
|
|
TableValue {
|
|
key: VMMemory::String(VMMemoryString { value: String::from("vége"), variable_id: 0 }),
|
|
value: VMMemory::NativeFunction(VMMemoryNativeFunction { func: szenvedes_vege, variable_id: 0 }),
|
|
},
|
|
];
|
|
mem.insert(String::from("szenvedés"), VMMemory::Table(VMMemoryTable { values: szenvedes, variable_id: 0 }));
|
|
|
|
let intezo: Vec<TableValue> = 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 }));
|
|
|
|
let krumpli: Vec<TableValue> = 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 }),
|
|
},
|
|
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 }));
|
|
|
|
return mem;
|
|
} |