added networking to the enviroment
This commit is contained in:
parent
cca26d9fc3
commit
f2220d1014
4 changed files with 267 additions and 25 deletions
|
@ -1,6 +1,6 @@
|
|||
use std::{collections::HashMap, process, thread::sleep, time::Duration};
|
||||
use std::{collections::HashMap, io::{BufRead, BufReader, Read, Write}, net::{self, TcpListener, TcpStream}, process, thread::sleep, time::Duration};
|
||||
|
||||
use crate::{errors::{create_error, print_error, ErrorSubType, ErrorType}, virtualmachine::{DecompiledOperation, Machine, VMMemory, VMMemoryNativeFunction, VMMemoryNull, VMMemoryString}};
|
||||
use crate::{errors::{create_error, print_error, ErrorSubType, ErrorType}, virtualmachine::{DecompiledOperation, Machine, TableValue, VMMemory, VMMemoryNativeFunction, VMMemoryNull, VMMemoryNumber, VMMemoryString, VMMemoryTable}};
|
||||
|
||||
fn get_string_from_vmmem(mem: &VMMemory) -> String {
|
||||
let mut out = String::new();
|
||||
|
@ -43,12 +43,14 @@ fn get_type_str(mem: &VMMemory) -> String {
|
|||
VMMemory::NativeFunction(_) => "native_function".to_string(),
|
||||
}
|
||||
}
|
||||
fn expect(mem: &VMMemory, expected_type: &str) -> bool {
|
||||
let actual_type = get_type_str(&mem);
|
||||
if actual_type == expected_type {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
fn arg_expect(args: &Vec<VMMemory>, pos: usize, expected_type: &str, machine: &Machine, op: &DecompiledOperation) {
|
||||
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) {
|
||||
|
@ -58,6 +60,43 @@ fn error(msg: String, machine: &Machine, op: &DecompiledOperation) {
|
|||
print_error(&err, &machine.ctx[func]);
|
||||
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 ugass(_machine: &mut Machine, _op: &DecompiledOperation, args: Vec<VMMemory>) -> VMMemory {
|
||||
let mut out = String::new();
|
||||
|
@ -68,11 +107,8 @@ fn ugass(_machine: &mut Machine, _op: &DecompiledOperation, args: Vec<VMMemory>)
|
|||
println!("{}", out.trim_end());
|
||||
return VMMemory::Null(VMMemoryNull { variable_id: 0 });
|
||||
}
|
||||
|
||||
fn bimba(machine: &mut Machine, op: &DecompiledOperation, args: Vec<VMMemory>) -> VMMemory {
|
||||
if args.len() < 1 || !expect(&args[0], "number") {
|
||||
error(format!("#1 number expected got {}", get_type_str(&args[0])), machine, op);
|
||||
}
|
||||
arg_expect(&args, 0, "number", machine, op);
|
||||
match &args[0] {
|
||||
VMMemory::Number(n) => {
|
||||
sleep(Duration::from_millis(n.value as u64));
|
||||
|
@ -81,11 +117,8 @@ fn bimba(machine: &mut Machine, op: &DecompiledOperation, args: Vec<VMMemory>) -
|
|||
}
|
||||
return VMMemory::Null(VMMemoryNull { variable_id: 0 });
|
||||
}
|
||||
|
||||
fn csomor(machine: &mut Machine, op: &DecompiledOperation, args: Vec<VMMemory>) -> VMMemory {
|
||||
if args.len() < 1 || !expect(&args[0], "string") {
|
||||
error(format!("#1 string expected got {}", get_type_str(&args[0])), machine, op);
|
||||
}
|
||||
arg_expect(&args, 0, "string", machine, op);
|
||||
match &args[0] {
|
||||
VMMemory::String(s) => {
|
||||
error(s.value.clone(), machine, op);
|
||||
|
@ -94,7 +127,6 @@ fn csomor(machine: &mut Machine, op: &DecompiledOperation, args: Vec<VMMemory>)
|
|||
}
|
||||
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 });
|
||||
|
@ -102,6 +134,185 @@ fn tarh(_machine: &mut Machine, _op: &DecompiledOperation, args: Vec<VMMemory>)
|
|||
return VMMemory::String(VMMemoryString { value: get_type_str(&args[0]), 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 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 listener = stream.unwrap();
|
||||
let write = match &args[1] {
|
||||
VMMemory::String(s) => s.value.clone(),
|
||||
_ => String::new()
|
||||
};
|
||||
match listener.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_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("id"), variable_id: 0 }),
|
||||
value: VMMemory::Number(VMMemoryNumber { value: (machine.storage.len()-1) as i64, variable_id: 0 }),
|
||||
}
|
||||
];
|
||||
return VMMemory::Table(VMMemoryTable { values: ret_table, variable_id: 0 });
|
||||
}
|
||||
return VMMemory::Null(VMMemoryNull { 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 i64, variable_id: 0 }),
|
||||
}
|
||||
];
|
||||
return VMMemory::Table(VMMemoryTable { values: ret_table, variable_id: 0 });
|
||||
}
|
||||
|
||||
pub fn generate() -> HashMap<String, VMMemory> {
|
||||
let mut mem: HashMap<String, VMMemory> = HashMap::new();
|
||||
|
||||
|
@ -110,5 +321,21 @@ pub fn generate() -> HashMap<String, VMMemory> {
|
|||
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 }));
|
||||
|
||||
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 }),
|
||||
}
|
||||
];
|
||||
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 }),
|
||||
}
|
||||
];
|
||||
mem.insert(String::from("kábel"), VMMemory::Table(VMMemoryTable { values: kabel, variable_id: 0 }));
|
||||
|
||||
return mem;
|
||||
}
|
|
@ -835,6 +835,18 @@ fn next_operation(pos: &mut usize, input: &Vec<Token>, op_ends: &Vec<Token>, par
|
|||
let var = ASTPart::VarRead(AstVarRead { variable: token.value.clone(), pos: token.pos });
|
||||
let cal = read_call(var, pos, input, ctx);
|
||||
return check_continue(pos, input, cal, op_ends, parse_ends, ctx)
|
||||
} else if next_token.typ == TokenType::SEPARATOR && next_token.value == "." {
|
||||
let var_pos = token.pos;
|
||||
*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);
|
||||
print_error(&err, &ctx);
|
||||
process::exit(1);
|
||||
}
|
||||
*pos += 1;
|
||||
let gt = ASTPart::TableGet(AstTableGet { table: Box::new(ASTPart::VarRead(AstVarRead { variable: token.value.clone(), pos: var_pos })), key: Box::new(ASTPart::String(AstString { value: keyy.value.clone(), pos: keyy.pos })), pos: var_pos+1 });
|
||||
return check_continue(pos, input, gt, op_ends, parse_ends, ctx);
|
||||
} else if next_token.typ == TokenType::SEPARATOR && next_token.value == "[" {
|
||||
*pos += 1;
|
||||
let key_ends: Vec<Token> = vec![
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use std::{collections::HashMap, process, vec};
|
||||
use std::{any::Any, collections::HashMap, process, vec};
|
||||
use crate::{enviroment, errors::{create_error, print_error, ErrorSubType, ErrorType}, Context};
|
||||
|
||||
const ASXVERSION: [u8; 3] = [0,1,0];
|
||||
|
@ -98,6 +98,7 @@ pub struct Machine {
|
|||
pub call_stack: Vec<CallStack>,
|
||||
pub env: HashMap<String, VMMemory>,
|
||||
pub ctx: Vec<Context>,
|
||||
pub storage: Vec<Box<dyn Any>>,
|
||||
}
|
||||
|
||||
fn read_be_num(input: &[u8]) -> usize {
|
||||
|
@ -520,6 +521,7 @@ impl Machine {
|
|||
}],
|
||||
env: enviroment::generate(),
|
||||
ctx: ctx,
|
||||
storage: Vec::new(),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
15
test.asl
15
test.asl
|
@ -1,7 +1,8 @@
|
|||
gethelj a = {
|
||||
[szaft"test"szaft] = szaft"test"szaft,
|
||||
[szaft"teher"szaft] = szaft"teher"szaft
|
||||
}
|
||||
ugass(a)
|
||||
//csömör(szaft"háh, appja hám"szaft)
|
||||
ugass(tarh(a))
|
||||
gethelj listener = kábel.halgass(szaft"0.0.0.0"szaft, 1010)
|
||||
gethelj stream = listener.kérés(listener)
|
||||
|
||||
ugass(stream.olvass(stream, 1024))
|
||||
stream.írj(stream, szaft"HTTP/1.1 200 OK
|
||||
Content-type: text/html; charset=utf-8
|
||||
|
||||
szafal a pofád!"szaft)
|
Loading…
Add table
Add a link
Reference in a new issue