From ee94ba13e2cea5215411e6bb72fe9053d2061606 Mon Sep 17 00:00:00 2001 From: MeexReay Date: Mon, 29 Jul 2024 17:52:22 +0300 Subject: [PATCH] input read --- README.md | 5 +- input.sus | 14 +++ src/sustlang/command/command.rs | 172 ++++++++++++++++++++++++++- src/sustlang/command/command_type.rs | 31 ++++- src/sustlang/other.rs | 6 +- src/sustlang/script/error.rs | 2 + src/sustlang/script/function.rs | 4 +- 7 files changed, 222 insertions(+), 12 deletions(-) create mode 100644 input.sus diff --git a/README.md b/README.md index 05a7401..6c2eed8 100644 --- a/README.md +++ b/README.md @@ -189,8 +189,11 @@ FUNC_END | Команда | Параметры | Описание | |--------------------------|------------|-------------| | `WRITE` | `name_var`, `stream_var` | Вывести переменную `name_var` в `stream_var` | -| `READ` | `name_var`, `size_var`, `stream_var` | Прочитать с `stream_var` ровно `size_var` байтов в переменную `name_var` типа `list[char]`/`string` | +| `READ` | `name_var`, `stream_var` | Прочитать с `stream_var` в переменную `name_var` типа `list[char]`/`string` | +| `READ_CHAR` | `name_var`, `stream_var` | Прочитать с `stream_var` один символ в переменную `name_var` типа `char` | +| `READ_LENGTH` | `name_var`, `length_var`, `stream_var` | Прочитать с `stream_var` ровно `length_var` байтов в переменную `name_var` типа `list[char]`/`string` | | `READ_ALL` | `name_var`, `stream_var` | Прочитать с `stream_var` все имеющиеся байты в переменную `name_var` типа `list[char]`/`string` | +| `READ_LINE` | `name_var`, `stream_var` | Прочитать с `stream_var` одну строку в переменную `name_var` типа `list[char]`/`string` | ### Файлы diff --git a/input.sus b/input.sus new file mode 100644 index 0000000..ce5781b --- /dev/null +++ b/input.sus @@ -0,0 +1,14 @@ + +FUNC null println text string + TEMP_VAR char new_line 10 + ADD_STR text new_line + WRITE text cout +FUNC_END + +FUNC string input + READ_LINE result cin +FUNC_END + +INIT_VAR string read +USE_FUNC input read +USE_FUNC println null read diff --git a/src/sustlang/command/command.rs b/src/sustlang/command/command.rs index 7f42321..2f4a553 100644 --- a/src/sustlang/command/command.rs +++ b/src/sustlang/command/command.rs @@ -1,13 +1,14 @@ use bytebuffer::ByteBuffer; use rand::Rng; -use crate::{variable, FileOutStream, Pohuy}; +use crate::{variable, FileOutStream, IgnoreResult}; use super::super::command::CommandType; use super::super::script::{RunningScript, ScriptError}; use super::super::var::{VarType, Variable}; use std::collections::HashMap; +use std::io::{BufRead, BufReader}; use std::sync::{Arc, Mutex}; use std::time::Duration; use std::{fs, thread}; @@ -1831,7 +1832,176 @@ impl Command { ) .map_err(|f| (f, self.clone()))?; } + CommandType::ReadLine => { + let name_var = self + .args + .get(0) + .ok_or((ScriptError::CommandArgsInvalidError, self.clone()))? + .clone(); + let stream_var = self + .args + .get(1) + .ok_or((ScriptError::CommandArgsInvalidError, self.clone()))? + .clone(); + + let var = script + .lock() + .unwrap() + .get_var(name_var.clone(), locals) + .map_err(|f| (f, self.clone()))?; + let stream = script + .lock() + .unwrap() + .get_var(stream_var.clone(), locals) + .map_err(|f| (f, self.clone()))? + .as_in_stream() + .map_err(|f| (f, self.clone()))?; + + let mut line = String::new(); + let mut buffer = [0; 1]; + while stream + .lock() + .unwrap() + .read(&mut buffer) + .map_err(|_| (ScriptError::StreamReadError, self.clone()))? + > 0 + { + if buffer[0] == b'\n' { + break; + } + line.push(buffer[0] as char); + } + + let buffer = line.as_bytes().to_vec(); + + script + .lock() + .unwrap() + .set_var( + name_var, + match var { + Variable::List(VarType::Char, _) => Variable::from_list( + Some( + buffer + .iter() + .map(|f| Variable::from_char(Some(*f))) + .collect(), + ), + VarType::List(Box::new(VarType::Char)), + ), + Variable::String(_, _) => Variable::from_str(Some( + String::from_utf8(buffer) + .or(Err(ScriptError::StringUTF8Error)) + .map_err(|f| (f, self.clone()))?, + )), + _ => { + return Err((ScriptError::TypeMismatchError, self.clone())); + } + }, + global, + false, + locals, + ) + .map_err(|f| (f, self.clone()))?; + } + CommandType::ReadChar => { + let name_var = self + .args + .get(0) + .ok_or((ScriptError::CommandArgsInvalidError, self.clone()))? + .clone(); + let stream_var = self + .args + .get(1) + .ok_or((ScriptError::CommandArgsInvalidError, self.clone()))? + .clone(); + + let stream = script + .lock() + .unwrap() + .get_var(stream_var.clone(), locals) + .map_err(|f| (f, self.clone()))? + .as_in_stream() + .map_err(|f| (f, self.clone()))?; + + let mut buffer = [0; 1]; + let read = stream + .lock() + .unwrap() + .read(&mut buffer) + .map_err(|_| (ScriptError::StreamReadError, self.clone()))? + > 0; + let variable = if read { + Variable::from_char(Some(buffer[0])) + } else { + Variable::from_char(None) + }; + + script + .lock() + .unwrap() + .set_var(name_var, variable, global, false, locals) + .map_err(|f| (f, self.clone()))?; + } CommandType::Read => { + let name_var = self + .args + .get(0) + .ok_or((ScriptError::CommandArgsInvalidError, self.clone()))? + .clone(); + let stream_var = self + .args + .get(1) + .ok_or((ScriptError::CommandArgsInvalidError, self.clone()))? + .clone(); + + let var = script + .lock() + .unwrap() + .get_var(name_var.clone(), locals) + .map_err(|f| (f, self.clone()))?; + let stream = script + .lock() + .unwrap() + .get_var(stream_var.clone(), locals) + .map_err(|f| (f, self.clone()))? + .as_in_stream() + .map_err(|f| (f, self.clone()))?; + + let mut buffer: Vec = Vec::new(); + stream.lock().unwrap().read(&mut buffer).unwrap(); + + script + .lock() + .unwrap() + .set_var( + name_var, + match var { + Variable::List(VarType::Char, _) => Variable::from_list( + Some( + buffer + .iter() + .map(|f| Variable::from_char(Some(*f))) + .collect(), + ), + VarType::List(Box::new(VarType::Char)), + ), + Variable::String(_, _) => Variable::from_str(Some( + String::from_utf8(buffer) + .or(Err(ScriptError::StringUTF8Error)) + .map_err(|f| (f, self.clone()))?, + )), + _ => { + return Err((ScriptError::TypeMismatchError, self.clone())); + } + }, + global, + false, + locals, + ) + .map_err(|f| (f, self.clone()))?; + } + CommandType::ReadLength => { let name_var = self .args .get(0) diff --git a/src/sustlang/command/command_type.rs b/src/sustlang/command/command_type.rs index a1f80da..1cc7a7e 100644 --- a/src/sustlang/command/command_type.rs +++ b/src/sustlang/command/command_type.rs @@ -134,18 +134,36 @@ pub enum CommandType { /// Параметры: `name_var`, `stream_var` Write, - /// Прочитать с `stream_var` ровно `size_var` байтов в переменную `name_var` типа `list[char]` + /// Прочитать с `stream_var` ровно `length_var` байтов в переменную `name_var` типа `string`/`list[char]` /// - /// Название: READ \ - /// Параметры: `name_var`, `size_var`, `stream_var` - Read, + /// Название: READ_LENGTH \ + /// Параметры: `name_var`, `length_var`, `stream_var` + ReadLength, - /// Прочитать с `stream_var` все имеющиеся байты в переменную `name_var` типа `list[char]` + /// Прочитать с `stream_var` все имеющиеся байты в переменную `name_var` типа `string`/`list[char]` /// /// Название: READ_ALL \ /// Параметры: `name_var`, `stream_var` ReadAll, + /// Прочитать с `stream_var` в переменную `name_var` типа `list[char]`/`string` + /// + /// Название: READ \ + /// Параметры: `name_var`, `stream_var` + Read, + + /// Прочитать с `stream_var` один символ в переменную `name_var` типа `char` + /// + /// Название: READ_CHAR \ + /// Параметры: `name_var`, `stream_var` + ReadChar, + + /// Прочитать с `stream_var` одну строку в переменную `name_var` типа `list[char]`/`string` + /// + /// Название: READ_LINE \ + /// Параметры: `name_var`, `stream_var` + ReadLine, + /// Функция `func` (с единственным аргументом с типом `int`) вызывается с `start_index` до `end_index` включительно, `start_index` и `end_index` это названия переменных /// /// Название: FOR \ @@ -415,6 +433,9 @@ impl CommandType { "WRITE" => Ok(CommandType::Write), "READ" => Ok(CommandType::Read), "READ_ALL" => Ok(CommandType::ReadAll), + "READ_LINE" => Ok(CommandType::ReadLine), + "READ_CHAR" => Ok(CommandType::ReadChar), + "READ_LENGTH" => Ok(CommandType::ReadLength), "FOR" => Ok(CommandType::For), "FOR_MAP" => Ok(CommandType::ForMap), "FOR_LIST" => Ok(CommandType::ForList), diff --git a/src/sustlang/other.rs b/src/sustlang/other.rs index 2631c5a..c60e9fc 100644 --- a/src/sustlang/other.rs +++ b/src/sustlang/other.rs @@ -1,10 +1,10 @@ use std::{fs, io::Write}; -pub trait Pohuy { - fn pohuy(&self) {} +pub trait IgnoreResult { + fn ignore(&self) {} } -impl Pohuy for Result {} +impl IgnoreResult for Result {} pub struct FileOutStream { bytes: Vec, diff --git a/src/sustlang/script/error.rs b/src/sustlang/script/error.rs index 5ea0e76..3c69f90 100644 --- a/src/sustlang/script/error.rs +++ b/src/sustlang/script/error.rs @@ -14,6 +14,8 @@ pub enum ScriptError { FunctionUnknownError, FileReadError, FileWriteError, + StreamReadError, + StreamWriteError, } impl Display for ScriptError { diff --git a/src/sustlang/script/function.rs b/src/sustlang/script/function.rs index bc1c921..c7836bb 100644 --- a/src/sustlang/script/function.rs +++ b/src/sustlang/script/function.rs @@ -1,5 +1,5 @@ use super::super::command::{Command, CommandType}; -use super::super::other::Pohuy; +use super::super::other::IgnoreResult; use super::super::var::{VarType, Variable}; use super::{RunningScript, ScriptError}; @@ -67,7 +67,7 @@ impl Function { .unwrap() .drop_var(ele, &mut locals) .map_err(|f| (f, command.clone())) - .pohuy(); + .ignore(); } }