mirror of
https://github.com/MeexReay/sustlang.git
synced 2025-06-24 10:33:01 +03:00
writing wow ezezez
This commit is contained in:
parent
28ed2c1b54
commit
b29952bec8
7
Cargo.lock
generated
Normal file
7
Cargo.lock
generated
Normal file
@ -0,0 +1,7 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "sustlang"
|
||||
version = "0.1.0"
|
17
README.md
17
README.md
@ -28,9 +28,9 @@ WRITE text cout
|
||||
| `TEMP_VAR` | `type_var`, `name_var`, `value_var` | Переменная `name_var` инициализируется с типом `type_var` и присваивается `value_var`, переменная дропается после первого же использования |
|
||||
| `MOVE_VAR` | `source_var`, `target_var` | Переместить значение переменной с `source_var` в `target_var` |
|
||||
| `COPY_VAR` | `source_var`, `target_var` | Скопировать значение переменной с `source_var` в `target_var` |
|
||||
| `TO_STR_VAR` | `source_var`, `target_var` | Скопировать значение переменной с `source_var` в `target_var`, переводя в строку |
|
||||
| `DROP_VAR` | `name_var` | Дропнуть переменную `name_var` |
|
||||
| `HAS_VAR` | `name_var`, `result_var` | В переменную `result_var` записывается `bool` существует ли переменная `name_var` |
|
||||
| `TO_STRING` | `source_var`, `target_var` | Скопировать значение переменной с `source_var` в `target_var`, переводя в строку |
|
||||
| `ADD_INT` | `int_var1`, `int_var2` | Прибавить к числу `int_var1` значение `int_var2` |
|
||||
| `ADD_FLOAT` | `float_var1`, `float_var2` | Прибавить к числу `float_var1` значение `float_var2` |
|
||||
| `ADD_STR` | `str_var`, `value_var` | Прибавить к строке `str_var` значение `value_var` (может быть типа `string/char/list[char]`) |
|
||||
@ -42,17 +42,18 @@ WRITE text cout
|
||||
| `READ_ALL` | `name_var`, `stream_var` | Прочитать с `stream_var` все имеющиеся байты в переменную `name_var` типа `list[char]` |
|
||||
| `READ_STR` | `name_var`, `size_var`, `stream_var` | Прочитать с `stream_var` ровно `size_var` байтов в переменную `name_var` типа `string` |
|
||||
| `READ_STR_ALL` | `name_var`, `stream_var` | Прочитать с `stream_var` все имеющиеся байты в переменную `name_var` типа `string` |
|
||||
| `FOR` | `func`, `start_index`, `end_index` | Функция `func` (с единственным аргументом с типом `int`) вызывается с `start_index` до `end_index` включительно, `start_index` и `end_index` это названия переменных |
|
||||
| `FOR_MAP` | `func`, `map_var` | Функция `func` (с двумя аргументами с типами мапы) вызывается для каждого `key`, `value` переменной `map_var` |
|
||||
| `FOR_LIST` | `func`, `list_var` | Функция `func` (с единственным аргументом с типом списка) вызывается для каждого предмета переменной `list_var` |
|
||||
| `WHILE` | `func` | Функция `func` (с результатом `bool`) вызывается, пока функция выдает `true` |
|
||||
| `FOR` | `func(int)`, `start_index`, `end_index` | Функция `func` (с единственным аргументом с типом `int`) вызывается с `start_index` до `end_index` включительно, `start_index` и `end_index` это названия переменных |
|
||||
| `FOR_MAP` | `func(any, any)`, `map_var` | Функция `func` вызывается для каждого `key`, `value` переменной `map_var` |
|
||||
| `FOR_LIST` | `func(any)`, `list_var` | Функция `func` вызывается для каждого предмета переменной `list_var` |
|
||||
| `WHILE` | `func -> bool` | Функция `func` (с результатом `bool`) вызывается, пока функция выдает `true` |
|
||||
| `USE_FUNC` | `func`, `result_var`, `[arg_var1] ... [arg_varN]` | Функция `func` вызывается с переданными аргументами и устанавливает результат в переменную `result_var` |
|
||||
| `OPEN_FILE_IN` | `path_var`, `stream_var` | Открыть файл по пути `path_var` (`path_var`, `stream_var` - переменные) для чтения и записать стрим для чтения в переменную `stream_var` |
|
||||
| `OPEN_FILE_OUT` | `path_var`, `stream_var` | Открыть файл по пути `path_var` (`path_var`, `stream_var` - переменные) для записи и записать стрим для записи в переменную `stream_var` |
|
||||
| `OPEN_TCP_CONNECTION` | `addr_var`, `port_var`, `in_stream`, `out_stream` | Подключиться по `addr_var:port_var` (`addr_var: string`, `port_var: int`, `in_stream: in_stream`, `out_stream: out_stream` - переменные) и записать стримы для чтения и записи в `in_stream` и `out_stream` |
|
||||
| `OPEN_TCP_LISTENER` | `addr_var`, `port_var`, `accept_func` | Ожидание подключений с `addr_var:port_var` (`addr_var: string`, `port_var: int` - переменные), при подключениях вызывается функция `accept_func` с четырьмя аргументами `in_stream: in_stream` и `out_stream: out_stream` и `addr_var: string` и `port_var: int` |
|
||||
| `OPEN_TCP_LISTENER` | `addr_var`, `port_var`, `accept_func(string,int,in_stream,out_stream)` | Ожидание подключений с `addr_var:port_var` (`addr_var: string`, `port_var: int` - переменные), при подключениях вызывается функция `accept_func` |
|
||||
| `HAS_OPTIONAL` | `optional_var`, `result_var` | Узнать, имеет ли данные опшнл `optional_var` и записать результат в `result_var: bool` |
|
||||
| `WHEN_OPTIONAL` | `optional_var`, `func` | Когда опшнл `optional_var` имеет данные, вызывается `func` с единственным аргументом типа опшнла |
|
||||
| `WHEN_OPTIONAL` | `optional_var`, `func(option[any])` | Когда опшнл `optional_var` имеет данные, вызывается `func` |
|
||||
| `SLEEP` | `time_var` | Ждать миллисекунд из переменной `time_var` (тип переменной: int) |
|
||||
|
||||
## Типы переменных
|
||||
|
||||
@ -64,7 +65,7 @@ WRITE text cout
|
||||
| `float` | `SET_VAR var 14.48` | `14.48` |
|
||||
| `char` | `SET_VAR var 255` | `0 - 255` |
|
||||
| `list[type]` | `SET_VAR var.0 value` | `value` |
|
||||
| `map[key_type value_type]` | `SET_VAR var.key value` | `value` |
|
||||
| `map[key_type,value_type]` | `SET_VAR var.key value` | `value` |
|
||||
| `optional[type]` | `SET_VAR var (value)` | `(value)` / `null` |
|
||||
| `in_stream` | `OPEN_FILE_IN path var` | |
|
||||
| `out_stream` | `OPEN_FILE_OUT path var` | |
|
||||
|
717
src/lib.rs
Normal file
717
src/lib.rs
Normal file
@ -0,0 +1,717 @@
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
hash::Hash,
|
||||
io::{Read, Write},
|
||||
ptr::hash,
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
|
||||
#[derive(PartialEq, Clone, Debug, Hash)]
|
||||
pub enum VarType {
|
||||
Bool,
|
||||
String,
|
||||
Integer,
|
||||
Float,
|
||||
Char,
|
||||
List(Box<VarType>),
|
||||
Map(Box<VarType>, Box<VarType>),
|
||||
Optional(Box<VarType>),
|
||||
InStream,
|
||||
OutStream,
|
||||
}
|
||||
|
||||
impl VarType {
|
||||
pub fn from_name(name: &str) -> Option<VarType> {
|
||||
if name.starts_with("map[") {
|
||||
let value_type = name[9..name.len() - 1].to_string();
|
||||
|
||||
let mut key_type = String::new();
|
||||
let mut val_type = String::new();
|
||||
|
||||
let mut val_tree = 0;
|
||||
let mut val_stat = 0;
|
||||
for char in value_type.chars() {
|
||||
if val_stat == 0 {
|
||||
key_type.push(char);
|
||||
} else if val_stat == 1 {
|
||||
val_type.push(char);
|
||||
}
|
||||
if char == ',' && val_tree == 0 {
|
||||
val_stat += 1;
|
||||
}
|
||||
if char == '[' {
|
||||
val_tree += 1;
|
||||
}
|
||||
if char == ']' {
|
||||
val_tree -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
let key_type = Box::new(VarType::from_name(&key_type)?);
|
||||
let val_type = Box::new(VarType::from_name(&val_type)?);
|
||||
|
||||
return Some(VarType::Map(key_type, val_type));
|
||||
}
|
||||
if name.starts_with("list[") {
|
||||
let value_type = name[5..name.len() - 1].to_string();
|
||||
let value_type = Box::new(VarType::from_name(&value_type)?);
|
||||
return Some(VarType::List(value_type));
|
||||
}
|
||||
if name.starts_with("optional[") {
|
||||
let value_type = name[9..name.len() - 1].to_string();
|
||||
let value_type = Box::new(VarType::from_name(&value_type)?);
|
||||
return Some(VarType::Optional(value_type));
|
||||
}
|
||||
|
||||
match name {
|
||||
"bool" => Some(VarType::Bool),
|
||||
"string" => Some(VarType::String),
|
||||
"integer" => Some(VarType::Integer),
|
||||
"float" => Some(VarType::Float),
|
||||
"char" => Some(VarType::Char),
|
||||
"in_stream" => Some(VarType::InStream),
|
||||
"out_stream" => Some(VarType::OutStream),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum Variable {
|
||||
Bool(VarType, Option<bool>),
|
||||
String(VarType, Option<String>),
|
||||
Integer(VarType, Option<isize>),
|
||||
Float(VarType, Option<f64>),
|
||||
Char(VarType, Option<u8>),
|
||||
List(VarType, Option<Vec<Variable>>),
|
||||
Map(VarType, Option<HashMap<Variable, Variable>>),
|
||||
Optional(VarType, Option<Option<Box<Variable>>>),
|
||||
InStream(VarType, Option<Arc<Mutex<dyn Read>>>),
|
||||
OutStream(VarType, Option<Arc<Mutex<dyn Write>>>),
|
||||
}
|
||||
|
||||
impl Variable {
|
||||
pub fn empty_var(var_type: VarType) -> Option<Variable> {
|
||||
match var_type {
|
||||
VarType::Bool => Some(Variable::Bool(VarType::Bool, None)),
|
||||
VarType::String => Some(Variable::String(VarType::String, None)),
|
||||
VarType::Integer => Some(Variable::Integer(VarType::Integer, None)),
|
||||
VarType::Float => Some(Variable::Float(VarType::Float, None)),
|
||||
VarType::Char => Some(Variable::Char(VarType::Char, None)),
|
||||
VarType::Optional(optional_type) => {
|
||||
Some(Variable::Optional(VarType::Optional(optional_type), None))
|
||||
}
|
||||
VarType::List(value_type) => Some(Variable::List(VarType::List(value_type), None)),
|
||||
VarType::Map(key_type, value_type) => {
|
||||
Some(Variable::Map(VarType::Map(key_type, value_type), None))
|
||||
}
|
||||
VarType::InStream => Some(Variable::InStream(VarType::InStream, None)),
|
||||
VarType::OutStream => Some(Variable::OutStream(VarType::OutStream, None)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_var(var_type: VarType, text: String) -> Option<Variable> {
|
||||
match var_type {
|
||||
VarType::Bool => Some(Variable::Bool(
|
||||
VarType::Bool,
|
||||
Some(match text.as_str() {
|
||||
"true" => true,
|
||||
"false" => false,
|
||||
"1" => true,
|
||||
"0" => false,
|
||||
_ => {
|
||||
return None;
|
||||
}
|
||||
}),
|
||||
)),
|
||||
VarType::String => Some(Variable::String(VarType::String, Some(text))),
|
||||
VarType::Integer => Some(Variable::Integer(
|
||||
VarType::Integer,
|
||||
Some(match text.parse() {
|
||||
Ok(i) => i,
|
||||
Err(_) => {
|
||||
return None;
|
||||
}
|
||||
}),
|
||||
)),
|
||||
VarType::Float => Some(Variable::Float(
|
||||
VarType::Float,
|
||||
Some(match text.parse() {
|
||||
Ok(i) => i,
|
||||
Err(_) => {
|
||||
return None;
|
||||
}
|
||||
}),
|
||||
)),
|
||||
VarType::Char => Some(Variable::Char(
|
||||
VarType::Char,
|
||||
Some(match text.parse() {
|
||||
Ok(i) => i,
|
||||
Err(_) => {
|
||||
return None;
|
||||
}
|
||||
}),
|
||||
)),
|
||||
VarType::Optional(optional_type) => {
|
||||
if text.starts_with("[") && text.ends_with("]") {
|
||||
let text = text[1..text.len() - 1].to_string();
|
||||
Some(Variable::Optional(
|
||||
VarType::Optional(optional_type.clone()),
|
||||
match Self::parse_var(optional_type.clone().as_mut().clone(), text) {
|
||||
Some(i) => Some(Some(Box::new(i))),
|
||||
None => None,
|
||||
},
|
||||
))
|
||||
} else if text.as_str() == "none" {
|
||||
Some(Variable::Optional(
|
||||
VarType::Optional(optional_type),
|
||||
Some(None),
|
||||
))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for Variable {}
|
||||
impl Hash for Variable {
|
||||
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||
match self {
|
||||
Variable::Bool(_, value) => {
|
||||
value.hash(state);
|
||||
}
|
||||
Variable::String(_, value) => {
|
||||
value.hash(state);
|
||||
}
|
||||
Variable::Integer(_, value) => {
|
||||
value.hash(state);
|
||||
}
|
||||
Variable::Float(_, value) => {
|
||||
hash(value, state);
|
||||
}
|
||||
Variable::Char(_, value) => {
|
||||
value.hash(state);
|
||||
}
|
||||
Variable::List(_, value) => {
|
||||
value.hash(state);
|
||||
}
|
||||
Variable::Map(_, value) => {
|
||||
hash(value, state);
|
||||
}
|
||||
Variable::Optional(_, value) => {
|
||||
value.hash(state);
|
||||
}
|
||||
Variable::InStream(_, value) => {
|
||||
hash(value, state);
|
||||
}
|
||||
Variable::OutStream(_, value) => {
|
||||
hash(value, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
impl PartialEq for Variable {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
match self {
|
||||
Variable::Bool(_, value) => match other {
|
||||
Variable::Bool(_, other_value) => value == other_value,
|
||||
_ => false,
|
||||
},
|
||||
Variable::String(_, value) => match other {
|
||||
Variable::String(_, other_value) => value == other_value,
|
||||
_ => false,
|
||||
},
|
||||
Variable::Integer(_, value) => match other {
|
||||
Variable::Integer(_, other_value) => value == other_value,
|
||||
_ => false,
|
||||
},
|
||||
Variable::Float(_, value) => match other {
|
||||
Variable::Float(_, other_value) => value == other_value,
|
||||
_ => false,
|
||||
},
|
||||
Variable::Char(_, value) => match other {
|
||||
Variable::Char(_, other_value) => value == other_value,
|
||||
_ => false,
|
||||
},
|
||||
Variable::List(_, value) => match other {
|
||||
Variable::List(_, other_value) => value == other_value,
|
||||
_ => false,
|
||||
},
|
||||
Variable::Map(_, value) => match other {
|
||||
Variable::Map(_, other_value) => match value {
|
||||
Some(value) => match other_value {
|
||||
Some(other_value) => {
|
||||
if other_value.len() == value.len() {
|
||||
let mut ovi = other_value.iter();
|
||||
let mut vi = value.iter();
|
||||
|
||||
loop {
|
||||
let Some((ok, ov)) = ovi.next() else {
|
||||
break;
|
||||
};
|
||||
let Some((k, v)) = vi.next() else {
|
||||
break;
|
||||
};
|
||||
if k != ok || v != ov {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
None => false,
|
||||
},
|
||||
None => match other_value {
|
||||
Some(_) => false,
|
||||
None => true,
|
||||
},
|
||||
},
|
||||
_ => false,
|
||||
},
|
||||
Variable::Optional(_, value) => match other {
|
||||
Variable::Optional(_, other_value) => other_value == value,
|
||||
_ => false,
|
||||
},
|
||||
Variable::InStream(_, value) => match other {
|
||||
Variable::InStream(_, other_value) => match value {
|
||||
Some(value) => match other_value {
|
||||
Some(other_value) => Arc::ptr_eq(value, other_value),
|
||||
None => false,
|
||||
},
|
||||
None => match other_value {
|
||||
Some(_) => false,
|
||||
None => true,
|
||||
},
|
||||
},
|
||||
_ => false,
|
||||
},
|
||||
Variable::OutStream(_, value) => match other {
|
||||
Variable::OutStream(_, other_value) => match value {
|
||||
Some(value) => match other_value {
|
||||
Some(other_value) => Arc::ptr_eq(value, other_value),
|
||||
None => false,
|
||||
},
|
||||
None => match other_value {
|
||||
Some(_) => false,
|
||||
None => true,
|
||||
},
|
||||
},
|
||||
_ => false,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Clone, Debug, Copy, Hash)]
|
||||
pub enum CommandType {
|
||||
InitVar,
|
||||
SetVar,
|
||||
TempVar,
|
||||
MoveVar,
|
||||
CopyVar,
|
||||
DropVar,
|
||||
HasVar,
|
||||
ToString,
|
||||
AddInt,
|
||||
AddFloat,
|
||||
SubStr,
|
||||
SubList,
|
||||
ListSize,
|
||||
Write,
|
||||
Read,
|
||||
ReadAll,
|
||||
ReadStr,
|
||||
ReadStrAll,
|
||||
For,
|
||||
ForMap,
|
||||
ForList,
|
||||
While,
|
||||
UseFunc,
|
||||
OpenFileIn,
|
||||
OpenFileOut,
|
||||
OpenTcpConnection,
|
||||
OpenTcpListener,
|
||||
HasOptional,
|
||||
WhenOptional,
|
||||
Sleep,
|
||||
Func,
|
||||
FuncEnd,
|
||||
}
|
||||
|
||||
impl CommandType {
|
||||
pub fn from_name(name: &str) -> Option<CommandType> {
|
||||
match name {
|
||||
"INIT_VAR" => Some(CommandType::InitVar),
|
||||
"SET_VAR" => Some(CommandType::SetVar),
|
||||
"TEMP_VAR" => Some(CommandType::TempVar),
|
||||
"MOVE_VAR" => Some(CommandType::MoveVar),
|
||||
"COPY_VAR" => Some(CommandType::CopyVar),
|
||||
"DROP_VAR" => Some(CommandType::DropVar),
|
||||
"HAS_VAR" => Some(CommandType::HasVar),
|
||||
"TO_STRING" => Some(CommandType::ToString),
|
||||
"ADD_INT" => Some(CommandType::AddInt),
|
||||
"ADD_FLOAT" => Some(CommandType::AddFloat),
|
||||
"SUB_STR" => Some(CommandType::SubStr),
|
||||
"SUB_LIST" => Some(CommandType::SubList),
|
||||
"LIST_SIZE" => Some(CommandType::ListSize),
|
||||
"WRITE" => Some(CommandType::Write),
|
||||
"READ" => Some(CommandType::Read),
|
||||
"READ_ALL" => Some(CommandType::ReadAll),
|
||||
"READ_STR" => Some(CommandType::ReadStr),
|
||||
"READ_STR_ALL" => Some(CommandType::ReadStrAll),
|
||||
"FOR" => Some(CommandType::For),
|
||||
"FOR_MAP" => Some(CommandType::ForMap),
|
||||
"FOR_LIST" => Some(CommandType::ForList),
|
||||
"WHILE" => Some(CommandType::While),
|
||||
"USE_FUNC" => Some(CommandType::UseFunc),
|
||||
"OPEN_FILE_IN" => Some(CommandType::OpenFileIn),
|
||||
"OPEN_FILE_OUT" => Some(CommandType::OpenFileOut),
|
||||
"OPEN_TCP_CONNECTION" => Some(CommandType::OpenTcpConnection),
|
||||
"OPEN_TCP_LISTENER" => Some(CommandType::OpenTcpListener),
|
||||
"HAS_OPTIONAL" => Some(CommandType::HasOptional),
|
||||
"WHEN_OPTIONAL" => Some(CommandType::WhenOptional),
|
||||
"SLEEP" => Some(CommandType::Sleep),
|
||||
"FUNC" => Some(CommandType::Func),
|
||||
"FUNC_END" => Some(CommandType::FuncEnd),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Clone, Debug)]
|
||||
pub struct Command {
|
||||
command_type: CommandType,
|
||||
args: Vec<String>,
|
||||
}
|
||||
|
||||
impl Command {
|
||||
pub fn new(command_type: CommandType, args: Vec<String>) -> Command {
|
||||
Command { command_type, args }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Clone, Debug)]
|
||||
pub struct Function {
|
||||
name: String,
|
||||
result_type: VarType,
|
||||
parameters: HashMap<String, VarType>,
|
||||
commands: Vec<Command>,
|
||||
}
|
||||
|
||||
impl Function {
|
||||
pub fn new(
|
||||
name: String,
|
||||
result_type: VarType,
|
||||
parameters: HashMap<String, VarType>,
|
||||
commands: Vec<Command>,
|
||||
) -> Function {
|
||||
Function {
|
||||
name,
|
||||
result_type,
|
||||
parameters,
|
||||
commands,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn prepare_script(text: String) -> Vec<String> {
|
||||
text.lines()
|
||||
.map(|s| match s.split_once("#") {
|
||||
Some(s) => s.0,
|
||||
None => s,
|
||||
})
|
||||
.filter(|s| !s.trim().is_empty())
|
||||
.map(|s| s.to_string())
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn parse_commands(lines: Vec<String>) -> Vec<Command> {
|
||||
let mut commands = Vec::new();
|
||||
|
||||
for line in lines {
|
||||
let params: Vec<String> = line.split(" ").map(|v| v.to_string()).collect();
|
||||
|
||||
let command_type = match CommandType::from_name(¶ms[0]) {
|
||||
Some(i) => i,
|
||||
None => {
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
let args = if params.is_empty() {
|
||||
Vec::new()
|
||||
} else {
|
||||
params[1..].to_vec()
|
||||
};
|
||||
|
||||
commands.push(Command::new(command_type, args))
|
||||
}
|
||||
|
||||
commands
|
||||
}
|
||||
|
||||
fn cut_funcs(commands: &mut Vec<Command>) -> Vec<Function> {
|
||||
let mut functions: Vec<Function> = Vec::new();
|
||||
|
||||
let mut now_func = None;
|
||||
|
||||
let mut index = 0;
|
||||
for command in commands.clone() {
|
||||
match now_func.clone() {
|
||||
Some(mut func) => {
|
||||
if command.command_type == CommandType::FuncEnd {
|
||||
commands.remove(index);
|
||||
index -= 1;
|
||||
|
||||
functions.push(func);
|
||||
now_func = None;
|
||||
} else {
|
||||
commands.remove(index);
|
||||
index -= 1;
|
||||
|
||||
func.commands.push(command);
|
||||
}
|
||||
}
|
||||
None => {
|
||||
if command.command_type == CommandType::Func {
|
||||
commands.remove(index);
|
||||
index -= 1;
|
||||
|
||||
let name = command.args[0].clone();
|
||||
let result_type = match VarType::from_name(&command.args[1]) {
|
||||
Some(i) => i,
|
||||
None => {
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let mut parameters = HashMap::new();
|
||||
|
||||
let mut param_key: Option<String> = None;
|
||||
for i in &command.args[2..] {
|
||||
match ¶m_key {
|
||||
Some(key) => {
|
||||
parameters.insert(
|
||||
key.to_string(),
|
||||
match VarType::from_name(i) {
|
||||
Some(i) => i,
|
||||
None => {
|
||||
continue;
|
||||
}
|
||||
},
|
||||
);
|
||||
param_key = None;
|
||||
}
|
||||
None => {
|
||||
param_key = Some(i.to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
now_func = Some(Function::new(name, result_type, parameters, Vec::new()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
index += 1;
|
||||
}
|
||||
|
||||
functions
|
||||
}
|
||||
|
||||
pub struct Script {
|
||||
commands: Vec<Command>,
|
||||
functions: Vec<Function>,
|
||||
}
|
||||
|
||||
impl Script {
|
||||
pub fn parse(text: String) -> Script {
|
||||
let lines = prepare_script(text);
|
||||
let mut commands = parse_commands(lines);
|
||||
let functions = cut_funcs(&mut commands);
|
||||
Script {
|
||||
commands,
|
||||
functions,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct RunningScript {
|
||||
commands: Vec<Command>,
|
||||
functions: Vec<Function>,
|
||||
variables: HashMap<String, Variable>,
|
||||
}
|
||||
|
||||
impl RunningScript {
|
||||
pub fn new(script: Script) -> RunningScript {
|
||||
RunningScript {
|
||||
commands: script.commands,
|
||||
functions: script.functions,
|
||||
variables: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_standard_vars(
|
||||
&mut self,
|
||||
args: Vec<String>,
|
||||
cout: Box<dyn Write>,
|
||||
cin: Box<dyn Read>,
|
||||
) {
|
||||
self.variables.insert(
|
||||
String::from("args"),
|
||||
Variable::List(
|
||||
VarType::List(Box::new(VarType::String)),
|
||||
Some(
|
||||
args.iter()
|
||||
.map(|s| Variable::String(VarType::String, Some(s.to_string())))
|
||||
.collect(),
|
||||
),
|
||||
),
|
||||
);
|
||||
self.variables.insert(
|
||||
String::from("cout"),
|
||||
Variable::OutStream(VarType::OutStream, Some(Arc::new(Mutex::new(cout)))),
|
||||
);
|
||||
self.variables.insert(
|
||||
String::from("cin"),
|
||||
Variable::InStream(VarType::InStream, Some(Arc::new(Mutex::new(cin)))),
|
||||
);
|
||||
}
|
||||
|
||||
pub fn get_var(
|
||||
&mut self,
|
||||
name: String,
|
||||
locals: &mut HashMap<String, Variable>,
|
||||
) -> Option<Variable> {
|
||||
let mut var: Option<Variable> = None;
|
||||
|
||||
for part in name.split(".") {
|
||||
match &var {
|
||||
Some(v) => match v {
|
||||
Variable::List(_, list) => match list {
|
||||
Some(list) => {
|
||||
let index: usize = part.parse().unwrap();
|
||||
var = match list.get(index) {
|
||||
Some(i) => Some(i.clone()),
|
||||
None => {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
None => {
|
||||
return None;
|
||||
}
|
||||
},
|
||||
Variable::Map(map_type, map) => match map {
|
||||
Some(map) => {
|
||||
var = map
|
||||
.get(
|
||||
&match Variable::parse_var(map_type.clone(), part.to_string()) {
|
||||
Some(i) => i,
|
||||
None => {
|
||||
return None;
|
||||
}
|
||||
},
|
||||
)
|
||||
.cloned();
|
||||
}
|
||||
None => {
|
||||
return None;
|
||||
}
|
||||
},
|
||||
_ => {}
|
||||
},
|
||||
None => match self.variables.get(part) {
|
||||
Some(i) => var = Some(i.clone()),
|
||||
None => match locals.get(part) {
|
||||
Some(i) => var = Some(i.clone()),
|
||||
None => {
|
||||
return None;
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
var
|
||||
}
|
||||
|
||||
pub fn exec_command(
|
||||
&mut self,
|
||||
command: Command,
|
||||
global: bool,
|
||||
locals: &mut HashMap<String, Variable>,
|
||||
) {
|
||||
match command.command_type {
|
||||
CommandType::InitVar => {
|
||||
// TODO: for hello world
|
||||
}
|
||||
CommandType::SetVar => {
|
||||
// TODO: for hello world
|
||||
}
|
||||
CommandType::TempVar => {
|
||||
// TODO: for hello world
|
||||
}
|
||||
CommandType::MoveVar => {}
|
||||
CommandType::CopyVar => {}
|
||||
CommandType::DropVar => {}
|
||||
CommandType::HasVar => {}
|
||||
CommandType::ToString => {}
|
||||
CommandType::AddInt => {}
|
||||
CommandType::AddFloat => {}
|
||||
CommandType::SubStr => {}
|
||||
CommandType::SubList => {}
|
||||
CommandType::ListSize => {}
|
||||
CommandType::Write => {
|
||||
// TODO: for hello world
|
||||
}
|
||||
CommandType::Read => {}
|
||||
CommandType::ReadAll => {}
|
||||
CommandType::ReadStr => {}
|
||||
CommandType::ReadStrAll => {}
|
||||
CommandType::For => {}
|
||||
CommandType::ForMap => {}
|
||||
CommandType::ForList => {}
|
||||
CommandType::While => {}
|
||||
CommandType::UseFunc => {}
|
||||
CommandType::OpenFileIn => {}
|
||||
CommandType::OpenFileOut => {}
|
||||
CommandType::OpenTcpConnection => {}
|
||||
CommandType::OpenTcpListener => {}
|
||||
CommandType::HasOptional => {}
|
||||
CommandType::WhenOptional => {}
|
||||
CommandType::Sleep => {}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn exec_function(&mut self, function: Function, result_var: String, args: Vec<Variable>) {
|
||||
let mut locals: HashMap<String, Variable> = HashMap::new();
|
||||
let mut index = 0;
|
||||
for (k, _) in function.parameters {
|
||||
locals.insert(k, args[index].clone());
|
||||
index += 1;
|
||||
}
|
||||
locals.insert(
|
||||
"result".to_string(),
|
||||
Variable::empty_var(function.result_type).unwrap(),
|
||||
);
|
||||
|
||||
for command in function.commands.clone() {
|
||||
self.exec_command(command, false, &mut locals);
|
||||
}
|
||||
|
||||
self.variables
|
||||
.insert(result_var, locals.get("result").unwrap().clone());
|
||||
}
|
||||
|
||||
pub fn run(&mut self) {
|
||||
for command in self.commands.clone() {
|
||||
self.exec_command(command, true, &mut HashMap::new());
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +1 @@
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
}
|
||||
fn main() {}
|
||||
|
Loading…
x
Reference in New Issue
Block a user