mirror of
https://github.com/Dummi26/mers.git
synced 2025-04-28 18:16:05 +02:00
changed get to return [] or [v] instead of [] or v because v might be []. This also matches the 0-or-1-length-tuple patterns for optionals (so it can be unwrap()d using .assume1()).
This commit is contained in:
parent
45186e3803
commit
2ba1ed270d
188
src/libs/mod.rs
188
src/libs/mod.rs
@ -1,36 +1,200 @@
|
|||||||
use std::{
|
use std::{
|
||||||
io,
|
io::{self, BufRead, BufReader, Read, Write},
|
||||||
process::{Child, ChildStdin, ChildStdout, Command},
|
process::{Child, ChildStdin, ChildStdout, Command, Stdio},
|
||||||
|
sync::{Arc, Mutex},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
parse::{file::File, parse},
|
||||||
|
script::{
|
||||||
|
val_data::{VData, VDataEnum},
|
||||||
|
val_type::VType,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Libraries are processes that communicate via stdout/stdin.
|
||||||
|
data in stdout is only expected after it was requested via stdin. ignoring this will likely cause issues.
|
||||||
|
requests in stdin can be identified via the first byte (ascii char) and end with a \n newline character.
|
||||||
|
the identifying ascii chars:
|
||||||
|
i init
|
||||||
|
reply format:
|
||||||
|
two bytes, the first for major and the second for minor version number.
|
||||||
|
the utf8-encoded name of the library followed by a newline
|
||||||
|
the number of lines in the description (0 for no description) as a byte. (more than 255 lines aren't supported)
|
||||||
|
a (optionally markdown-formatted [TODO!]) description of the library; all lines (including the last one) must end with a newline
|
||||||
|
the things you would like to register; one line each unless explicitly stated otherwise; the first byte (char) decides what type to register:
|
||||||
|
f a function: followed by the function signature, i.e. "my_func(string int/float [string]) string/[float int]"
|
||||||
|
x end: indicates that you are done registering things
|
||||||
|
I init 2
|
||||||
|
TODO! (currently nothing)
|
||||||
|
reply should be a single line (only the newline char). If there is data before the newline char, it will be reported as an error and the script will not run.
|
||||||
|
f call a function:
|
||||||
|
followed by the function id byte (0 <= id < #funcs; function ids are assigned in ascending order as they were registered in the reply to "i"
|
||||||
|
and the data for each argument, in order.
|
||||||
|
reply: the data for the returned value
|
||||||
|
x exit
|
||||||
|
sending data: (all ints are encoded so that the most significant data is sent FIRST)
|
||||||
|
the first byte (ascii char) identifies the type of data: (exceptions listed first: bools)
|
||||||
|
b false
|
||||||
|
B true
|
||||||
|
1 int
|
||||||
|
2 int as string
|
||||||
|
5 float
|
||||||
|
6 float as string
|
||||||
|
" string (format: ", 64-bit unsigned int indicating string length, so many bytes utf-8)
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct Lib {
|
pub struct Lib {
|
||||||
process: Child,
|
process: Child,
|
||||||
stdin: ChildStdin,
|
stdin: Arc<Mutex<ChildStdin>>,
|
||||||
stdout: ChildStdout,
|
stdout: Arc<Mutex<BufReader<ChildStdout>>>,
|
||||||
|
pub registered_fns: Vec<(String, Vec<VType>, VType)>,
|
||||||
}
|
}
|
||||||
impl Lib {
|
impl Lib {
|
||||||
pub fn launch(mut exec: Command) -> Result<Self, LaunchError> {
|
pub fn launch(mut exec: Command) -> Result<Self, LaunchError> {
|
||||||
let mut handle = match exec.spawn() {
|
let mut handle = match exec
|
||||||
|
.stdin(Stdio::piped())
|
||||||
|
.stdout(Stdio::piped())
|
||||||
|
.stderr(Stdio::inherit())
|
||||||
|
.spawn()
|
||||||
|
{
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(e) => return Err(LaunchError::CouldNotSpawnProcess(e)),
|
Err(e) => return Err(LaunchError::CouldNotSpawnProcess(e)),
|
||||||
};
|
};
|
||||||
if let (Some(stdin), Some(stdout), stderr) = (
|
if let (Some(mut stdin), Some(stdout)) = (handle.stdin.take(), handle.stdout.take()) {
|
||||||
handle.stdin.take(),
|
let mut stdout = BufReader::new(stdout);
|
||||||
handle.stdout.take(),
|
writeln!(stdin, "i").unwrap();
|
||||||
handle.stderr.take(),
|
let vernum = {
|
||||||
) {
|
let mut vernum = [0, 0];
|
||||||
|
stdout.read_exact(&mut vernum).unwrap();
|
||||||
|
(vernum[0], vernum[1])
|
||||||
|
};
|
||||||
|
let name = stdout.line().unwrap();
|
||||||
|
let name = name.trim();
|
||||||
|
eprintln!("- <<< ADDING LIB: {name} v{}.{} >>> -", vernum.0, vernum.1);
|
||||||
|
let lines_in_desc = stdout.one_byte().unwrap();
|
||||||
|
let mut lines_desc = Vec::with_capacity(lines_in_desc as _);
|
||||||
|
for _ in 0..lines_in_desc {
|
||||||
|
let line = stdout.line().unwrap();
|
||||||
|
let line = line.trim_end_matches('\n');
|
||||||
|
eprintln!("| {line}");
|
||||||
|
lines_desc.push(line.to_string());
|
||||||
|
}
|
||||||
|
let mut registered_fns = vec![];
|
||||||
|
loop {
|
||||||
|
let line = stdout.line().unwrap();
|
||||||
|
match line.chars().next() {
|
||||||
|
Some('f') => {
|
||||||
|
let (name, args) = line[1..]
|
||||||
|
.split_once('(')
|
||||||
|
.expect("function signature didn't include the ( character.");
|
||||||
|
let mut fn_signature = File::new(args.to_string());
|
||||||
|
let mut fn_in = vec![];
|
||||||
|
loop {
|
||||||
|
let t = parse::parse_type_adv(&mut fn_signature, true).unwrap();
|
||||||
|
fn_in.push(t.0);
|
||||||
|
if t.1 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let fn_out = parse::parse_type(&mut fn_signature).unwrap();
|
||||||
|
eprintln!("Registering function \"{name}\" with args \"{}\" and return type \"{fn_out}\"", &fn_in.iter().fold(String::new(), |mut s, v| { s.push_str(format!(" {}", v).as_str()); s })[1..]);
|
||||||
|
registered_fns.push((name.to_string(), fn_in, fn_out));
|
||||||
|
}
|
||||||
|
_ => break,
|
||||||
|
}
|
||||||
|
}
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
process: handle,
|
process: handle,
|
||||||
stdin,
|
stdin: Arc::new(Mutex::new(stdin)),
|
||||||
stdout,
|
stdout: Arc::new(Mutex::new(stdout)),
|
||||||
|
registered_fns,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
return Err(LaunchError::NoStdio);
|
return Err(LaunchError::NoStdio);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn run_fn(&self, fnid: usize, args: &Vec<VData>) -> VData {
|
||||||
|
let mut stdin = self.stdin.lock().unwrap();
|
||||||
|
let mut stdout = self.stdout.lock().unwrap();
|
||||||
|
debug_assert!(args.len() == self.registered_fns[fnid].1.len());
|
||||||
|
write!(stdin, "f").unwrap();
|
||||||
|
stdin.write(&[fnid as _]).unwrap();
|
||||||
|
for (_i, arg) in args.iter().enumerate() {
|
||||||
|
data_to_bytes(arg, &mut stdin);
|
||||||
|
}
|
||||||
|
let o = data_from_bytes(&mut stdout).to();
|
||||||
|
o
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub enum LaunchError {
|
pub enum LaunchError {
|
||||||
NoStdio,
|
NoStdio,
|
||||||
CouldNotSpawnProcess(io::Error),
|
CouldNotSpawnProcess(io::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trait DirectReader {
|
||||||
|
fn line(&mut self) -> Result<String, io::Error>;
|
||||||
|
fn one_byte(&mut self) -> Result<u8, io::Error>;
|
||||||
|
}
|
||||||
|
impl<T> DirectReader for T
|
||||||
|
where
|
||||||
|
T: BufRead,
|
||||||
|
{
|
||||||
|
fn line(&mut self) -> Result<String, io::Error> {
|
||||||
|
let mut buf = String::new();
|
||||||
|
self.read_line(&mut buf)?;
|
||||||
|
Ok(buf)
|
||||||
|
}
|
||||||
|
fn one_byte(&mut self) -> Result<u8, io::Error> {
|
||||||
|
let mut b = [0];
|
||||||
|
self.read(&mut b)?;
|
||||||
|
Ok(b[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn data_to_bytes(data: &VData, stdin: &mut ChildStdin) {
|
||||||
|
match &data.data {
|
||||||
|
VDataEnum::Bool(false) => write!(stdin, "b").unwrap(),
|
||||||
|
VDataEnum::Bool(true) => write!(stdin, "B").unwrap(),
|
||||||
|
VDataEnum::Int(_) => todo!(),
|
||||||
|
VDataEnum::Float(_) => todo!("floats are not yet implemented for LibFunction calls."),
|
||||||
|
VDataEnum::String(s) => {
|
||||||
|
write!(stdin, "\"").unwrap();
|
||||||
|
stdin.write(&(s.len() as u64).to_be_bytes()).unwrap();
|
||||||
|
stdin.write(s.as_bytes()).unwrap();
|
||||||
|
}
|
||||||
|
VDataEnum::Tuple(_) => todo!(),
|
||||||
|
VDataEnum::List(..) => todo!(),
|
||||||
|
VDataEnum::Function(..) | VDataEnum::Reference(..) | VDataEnum::Thread(..) => {
|
||||||
|
panic!("cannot use functions, references or threads in LibFunctions.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stdin.flush().unwrap();
|
||||||
|
}
|
||||||
|
fn data_from_bytes(stdout: &mut BufReader<ChildStdout>) -> VDataEnum {
|
||||||
|
match stdout.one_byte().unwrap().into() {
|
||||||
|
'b' => VDataEnum::Bool(false),
|
||||||
|
'B' => VDataEnum::Bool(true),
|
||||||
|
'1' | '2' | '5' | '6' => todo!(),
|
||||||
|
'"' => {
|
||||||
|
let mut len_bytes = 0u64;
|
||||||
|
for _ in 0..8 {
|
||||||
|
len_bytes <<= 8;
|
||||||
|
len_bytes |= stdout.one_byte().unwrap() as u64;
|
||||||
|
}
|
||||||
|
let mut buf = Vec::with_capacity(len_bytes as _);
|
||||||
|
for _ in 0..len_bytes {
|
||||||
|
buf.push(stdout.one_byte().unwrap());
|
||||||
|
}
|
||||||
|
VDataEnum::String(String::from_utf8_lossy(&buf).into_owned())
|
||||||
|
}
|
||||||
|
_ => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -8,6 +8,7 @@ pub struct File {
|
|||||||
chars: Vec<(usize, char)>,
|
chars: Vec<(usize, char)>,
|
||||||
pos: FilePosition,
|
pos: FilePosition,
|
||||||
}
|
}
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
pub struct FilePosition {
|
pub struct FilePosition {
|
||||||
current_char_index: usize,
|
current_char_index: usize,
|
||||||
current_line: usize,
|
current_line: usize,
|
||||||
@ -100,6 +101,17 @@ impl File {
|
|||||||
None => None,
|
None => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn next_line(&mut self) -> String {
|
||||||
|
let mut o = String::new();
|
||||||
|
for ch in self {
|
||||||
|
if ch == '\n' {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
o.push(ch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
o
|
||||||
|
}
|
||||||
pub fn peek(&self) -> Option<char> {
|
pub fn peek(&self) -> Option<char> {
|
||||||
match self.chars.get(self.pos.current_char_index) {
|
match self.chars.get(self.pos.current_char_index) {
|
||||||
Some((_, c)) => Some(*c),
|
Some((_, c)) => Some(*c),
|
||||||
|
@ -1,10 +1,16 @@
|
|||||||
use crate::script::{
|
use std::{path::PathBuf, process::Command, sync::Arc};
|
||||||
block::{
|
|
||||||
to_runnable, to_runnable::ToRunnableError, RScript, SBlock, SFunction, SStatement,
|
use crate::{
|
||||||
SStatementEnum,
|
libs,
|
||||||
|
script::{
|
||||||
|
block::{
|
||||||
|
to_runnable::ToRunnableError,
|
||||||
|
to_runnable::{self, GInfo},
|
||||||
|
RScript, SBlock, SFunction, SStatement, SStatementEnum,
|
||||||
|
},
|
||||||
|
val_data::VDataEnum,
|
||||||
|
val_type::{VSingleType, VType},
|
||||||
},
|
},
|
||||||
val_data::VDataEnum,
|
|
||||||
val_type::{VSingleType, VType},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::file::File;
|
use super::file::File;
|
||||||
@ -28,6 +34,32 @@ impl From<ToRunnableError> for ScriptError {
|
|||||||
pub enum ParseError {}
|
pub enum ParseError {}
|
||||||
|
|
||||||
pub fn parse(file: &mut File) -> Result<RScript, ScriptError> {
|
pub fn parse(file: &mut File) -> Result<RScript, ScriptError> {
|
||||||
|
let mut libs = vec![];
|
||||||
|
loop {
|
||||||
|
file.skip_whitespaces();
|
||||||
|
let pos = file.get_pos().clone();
|
||||||
|
let line = file.next_line();
|
||||||
|
if line.starts_with("lib ") {
|
||||||
|
let path_to_executable: PathBuf = line[4..].into();
|
||||||
|
let mut cmd = Command::new(&path_to_executable);
|
||||||
|
if let Some(parent) = path_to_executable.parent() {
|
||||||
|
cmd.current_dir(parent.clone());
|
||||||
|
}
|
||||||
|
match libs::Lib::launch(cmd) {
|
||||||
|
Ok(lib) => {
|
||||||
|
libs.push(lib);
|
||||||
|
eprintln!("Loaded library!");
|
||||||
|
}
|
||||||
|
Err(e) => panic!(
|
||||||
|
"Unable to load library at {}: {e:?}",
|
||||||
|
path_to_executable.to_string_lossy().as_ref(),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
file.set_pos(pos);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
let func = SFunction::new(
|
let func = SFunction::new(
|
||||||
vec![(
|
vec![(
|
||||||
"args".to_string(),
|
"args".to_string(),
|
||||||
@ -36,10 +68,11 @@ pub fn parse(file: &mut File) -> Result<RScript, ScriptError> {
|
|||||||
parse_block_advanced(file, Some(false), true, true, false)?,
|
parse_block_advanced(file, Some(false), true, true, false)?,
|
||||||
);
|
);
|
||||||
eprintln!();
|
eprintln!();
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
eprintln!("Parsed: {func}");
|
eprintln!("Parsed: {func}");
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
eprintln!("Parsed: {func:#?}");
|
eprintln!("Parsed: {func:#?}");
|
||||||
let run = to_runnable(func)?;
|
let run = to_runnable::to_runnable(func, GInfo::new(Arc::new(libs)))?;
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
eprintln!("Runnable: {run:#?}");
|
eprintln!("Runnable: {run:#?}");
|
||||||
Ok(run)
|
Ok(run)
|
||||||
@ -400,13 +433,16 @@ fn parse_function(file: &mut File) -> Result<SFunction, ParseError> {
|
|||||||
Ok(SFunction::new(args, parse_block(file)?))
|
Ok(SFunction::new(args, parse_block(file)?))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_type(file: &mut File) -> Result<VType, ParseError> {
|
pub(crate) fn parse_type(file: &mut File) -> Result<VType, ParseError> {
|
||||||
match parse_type_adv(file, false) {
|
match parse_type_adv(file, false) {
|
||||||
Ok((v, _)) => Ok(v),
|
Ok((v, _)) => Ok(v),
|
||||||
Err(e) => Err(e),
|
Err(e) => Err(e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn parse_type_adv(file: &mut File, in_fn_args: bool) -> Result<(VType, bool), ParseError> {
|
pub(crate) fn parse_type_adv(
|
||||||
|
file: &mut File,
|
||||||
|
in_fn_args: bool,
|
||||||
|
) -> Result<(VType, bool), ParseError> {
|
||||||
let mut types = vec![];
|
let mut types = vec![];
|
||||||
let mut closed_fn_args = false;
|
let mut closed_fn_args = false;
|
||||||
loop {
|
loop {
|
||||||
|
@ -6,7 +6,9 @@ use std::{
|
|||||||
sync::{Arc, Mutex},
|
sync::{Arc, Mutex},
|
||||||
};
|
};
|
||||||
|
|
||||||
use self::to_runnable::ToRunnableError;
|
use crate::libs;
|
||||||
|
|
||||||
|
use self::to_runnable::{ToRunnableError, GInfo};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
builtins::BuiltinFunction,
|
builtins::BuiltinFunction,
|
||||||
@ -84,8 +86,8 @@ fn am<T>(i: T) -> Am<T> {
|
|||||||
Arc::new(Mutex::new(i))
|
Arc::new(Mutex::new(i))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_runnable(f: SFunction) -> Result<RScript, ToRunnableError> {
|
pub fn to_runnable(f: SFunction, ginfo: GInfo) -> Result<RScript, ToRunnableError> {
|
||||||
to_runnable::to_runnable(f)
|
to_runnable::to_runnable(f, ginfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod to_runnable {
|
pub mod to_runnable {
|
||||||
@ -95,10 +97,10 @@ pub mod to_runnable {
|
|||||||
sync::Arc,
|
sync::Arc,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::script::{
|
use crate::{script::{
|
||||||
val_data::VDataEnum,
|
val_data::VDataEnum,
|
||||||
val_type::{VSingleType, VType},
|
val_type::{VSingleType, VType},
|
||||||
};
|
}, libs};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
BuiltinFunction, RBlock, RFunction, RScript, RStatement, RStatementEnum, SBlock, SFunction,
|
BuiltinFunction, RBlock, RFunction, RScript, RStatement, RStatementEnum, SBlock, SFunction,
|
||||||
@ -151,8 +153,21 @@ pub mod to_runnable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Global, shared between all
|
// Global, shared between all
|
||||||
struct GInfo {
|
pub struct GInfo {
|
||||||
vars: usize,
|
vars: usize,
|
||||||
|
libs: Arc<Vec<libs::Lib>>,
|
||||||
|
lib_fns: HashMap<String, (usize, usize)>,
|
||||||
|
}
|
||||||
|
impl GInfo {
|
||||||
|
pub fn new(libs: Arc<Vec<libs::Lib>>) -> Self {
|
||||||
|
let mut lib_fns = HashMap::new();
|
||||||
|
for (libid, lib) in libs.iter().enumerate() {
|
||||||
|
for (fnid, (name, ..)) in lib.registered_fns.iter().enumerate() {
|
||||||
|
lib_fns.insert(name.to_string(), (libid, fnid));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Self { vars: 0, libs, lib_fns, }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Local, used to keep local variables separated
|
// Local, used to keep local variables separated
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -161,7 +176,7 @@ pub mod to_runnable {
|
|||||||
fns: HashMap<String, Arc<RFunction>>,
|
fns: HashMap<String, Arc<RFunction>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_runnable(s: SFunction) -> Result<RScript, ToRunnableError> {
|
pub fn to_runnable(s: SFunction, mut ginfo: GInfo) -> Result<RScript, ToRunnableError> {
|
||||||
if s.inputs.len() != 1 || s.inputs[0].0 != "args" {
|
if s.inputs.len() != 1 || s.inputs[0].0 != "args" {
|
||||||
return Err(ToRunnableError::MainWrongInput);
|
return Err(ToRunnableError::MainWrongInput);
|
||||||
}
|
}
|
||||||
@ -172,7 +187,6 @@ pub mod to_runnable {
|
|||||||
})],
|
})],
|
||||||
})
|
})
|
||||||
{}
|
{}
|
||||||
let mut ginfo = GInfo { vars: 0 };
|
|
||||||
let func = function(
|
let func = function(
|
||||||
&s,
|
&s,
|
||||||
&mut ginfo,
|
&mut ginfo,
|
||||||
@ -181,7 +195,7 @@ pub mod to_runnable {
|
|||||||
fns: HashMap::new(),
|
fns: HashMap::new(),
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
Ok(RScript::new(func, ginfo.vars)?)
|
Ok(RScript::new(func, ginfo.vars, ginfo.libs)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
// go over every possible known-type input for the given function, returning all possible RFunctions.
|
// go over every possible known-type input for the given function, returning all possible RFunctions.
|
||||||
@ -313,7 +327,22 @@ pub mod to_runnable {
|
|||||||
todo!("ERR: Builtin function \"{v}\" with wrong args - this isn't a proper error yet, sorry.");
|
todo!("ERR: Builtin function \"{v}\" with wrong args - this isn't a proper error yet, sorry.");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// LIBRARY FUNCTION?
|
||||||
|
if let Some((libid, fnid)) = ginfo.lib_fns.get(v) {
|
||||||
|
let (_name, fn_in, fn_out) = &ginfo.libs[*libid].registered_fns[*fnid];
|
||||||
|
if fn_in.len() == rargs.len() && fn_in.iter().zip(rargs.iter()).all(|(fn_in, arg)| arg.out().fits_in(fn_in).is_empty()) {
|
||||||
|
RStatementEnum::LibFunction(*libid, *fnid, rargs, fn_out.clone())
|
||||||
|
} else {
|
||||||
|
// TODO! better error here
|
||||||
|
return Err(if fn_in.len() == rargs.len() {
|
||||||
|
todo!("Err: Wrong args for LibFunction \"{v}\".");
|
||||||
|
} else {
|
||||||
|
ToRunnableError::FunctionWrongArgCount(v.to_string(), fn_in.len(), rargs.len())
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
return Err(ToRunnableError::UseOfUndefinedFunction(v.clone()));
|
return Err(ToRunnableError::UseOfUndefinedFunction(v.clone()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -538,10 +567,10 @@ pub struct RBlock {
|
|||||||
statements: Vec<RStatement>,
|
statements: Vec<RStatement>,
|
||||||
}
|
}
|
||||||
impl RBlock {
|
impl RBlock {
|
||||||
pub fn run(&self, vars: &Vec<Am<VData>>) -> VData {
|
pub fn run(&self, vars: &Vec<Am<VData>>, libs: &Arc<Vec<libs::Lib>>) -> VData {
|
||||||
let mut last = None;
|
let mut last = None;
|
||||||
for statement in &self.statements {
|
for statement in &self.statements {
|
||||||
last = Some(statement.run(vars));
|
last = Some(statement.run(vars, libs));
|
||||||
}
|
}
|
||||||
if let Some(v) = last {
|
if let Some(v) = last {
|
||||||
v
|
v
|
||||||
@ -568,8 +597,8 @@ pub struct RFunction {
|
|||||||
pub block: RBlock,
|
pub block: RBlock,
|
||||||
}
|
}
|
||||||
impl RFunction {
|
impl RFunction {
|
||||||
pub fn run(&self, vars: &Vec<Am<VData>>) -> VData {
|
pub fn run(&self, vars: &Vec<Am<VData>>, libs: &Arc<Vec<libs::Lib>>) -> VData {
|
||||||
self.block.run(vars)
|
self.block.run(vars, libs)
|
||||||
}
|
}
|
||||||
pub fn out(&self, input_types: &Vec<VSingleType>) -> VType {
|
pub fn out(&self, input_types: &Vec<VSingleType>) -> VType {
|
||||||
self.input_output_map
|
self.input_output_map
|
||||||
@ -610,8 +639,8 @@ pub struct RStatement {
|
|||||||
statement: Box<RStatementEnum>,
|
statement: Box<RStatementEnum>,
|
||||||
}
|
}
|
||||||
impl RStatement {
|
impl RStatement {
|
||||||
pub fn run(&self, vars: &Vec<Am<VData>>) -> VData {
|
pub fn run(&self, vars: &Vec<Am<VData>>, libs: &Arc<Vec<libs::Lib>>) -> VData {
|
||||||
let out = self.statement.run(vars);
|
let out = self.statement.run(vars, libs);
|
||||||
if let Some(v) = self.output_to {
|
if let Some(v) = self.output_to {
|
||||||
*vars[v].lock().unwrap() = out;
|
*vars[v].lock().unwrap() = out;
|
||||||
VDataEnum::Tuple(vec![]).to()
|
VDataEnum::Tuple(vec![]).to()
|
||||||
@ -637,6 +666,7 @@ pub enum RStatementEnum {
|
|||||||
Variable(usize, VType, bool), // Arc<Mutex<..>> here, because imagine variable in for loop that is used in a different thread -> we need multiple "same" variables
|
Variable(usize, VType, bool), // Arc<Mutex<..>> here, because imagine variable in for loop that is used in a different thread -> we need multiple "same" variables
|
||||||
FunctionCall(Arc<RFunction>, Vec<RStatement>),
|
FunctionCall(Arc<RFunction>, Vec<RStatement>),
|
||||||
BuiltinFunction(BuiltinFunction, Vec<RStatement>),
|
BuiltinFunction(BuiltinFunction, Vec<RStatement>),
|
||||||
|
LibFunction(usize, usize, Vec<RStatement>, VType),
|
||||||
Block(RBlock),
|
Block(RBlock),
|
||||||
If(RStatement, RStatement, Option<RStatement>),
|
If(RStatement, RStatement, Option<RStatement>),
|
||||||
While(RStatement),
|
While(RStatement),
|
||||||
@ -646,13 +676,13 @@ pub enum RStatementEnum {
|
|||||||
IndexFixed(RStatement, usize),
|
IndexFixed(RStatement, usize),
|
||||||
}
|
}
|
||||||
impl RStatementEnum {
|
impl RStatementEnum {
|
||||||
pub fn run(&self, vars: &Vec<Am<VData>>) -> VData {
|
pub fn run(&self, vars: &Vec<Am<VData>>, libs: &Arc<Vec<libs::Lib>>) -> VData {
|
||||||
match self {
|
match self {
|
||||||
Self::Value(v) => v.clone(),
|
Self::Value(v) => v.clone(),
|
||||||
Self::Tuple(v) => {
|
Self::Tuple(v) => {
|
||||||
let mut w = vec![];
|
let mut w = vec![];
|
||||||
for v in v {
|
for v in v {
|
||||||
w.push(v.run(vars));
|
w.push(v.run(vars, libs));
|
||||||
}
|
}
|
||||||
VDataEnum::Tuple(w).to()
|
VDataEnum::Tuple(w).to()
|
||||||
}
|
}
|
||||||
@ -660,7 +690,7 @@ impl RStatementEnum {
|
|||||||
let mut w = vec![];
|
let mut w = vec![];
|
||||||
let mut out = VType { types: vec![] };
|
let mut out = VType { types: vec![] };
|
||||||
for v in v {
|
for v in v {
|
||||||
let val = v.run(vars);
|
let val = v.run(vars, libs);
|
||||||
out = out | val.out();
|
out = out | val.out();
|
||||||
w.push(val);
|
w.push(val);
|
||||||
}
|
}
|
||||||
@ -675,18 +705,20 @@ impl RStatementEnum {
|
|||||||
}
|
}
|
||||||
Self::FunctionCall(func, args) => {
|
Self::FunctionCall(func, args) => {
|
||||||
for (i, input) in func.inputs.iter().enumerate() {
|
for (i, input) in func.inputs.iter().enumerate() {
|
||||||
*vars[*input].lock().unwrap() = args[i].run(vars);
|
*vars[*input].lock().unwrap() = args[i].run(vars, libs);
|
||||||
}
|
}
|
||||||
func.run(vars)
|
func.run(vars, libs)
|
||||||
}
|
}
|
||||||
Self::Block(b) => b.run(vars),
|
Self::BuiltinFunction(v, args) => v.run(args, vars, libs),
|
||||||
|
Self::LibFunction(libid, fnid, args, _) => libs[*libid].run_fn(*fnid, &args.iter().map(|arg| arg.run(vars, libs)).collect()),
|
||||||
|
Self::Block(b) => b.run(vars, libs),
|
||||||
Self::If(c, t, e) => {
|
Self::If(c, t, e) => {
|
||||||
if let VDataEnum::Bool(v) = c.run(vars).data {
|
if let VDataEnum::Bool(v) = c.run(vars, libs).data {
|
||||||
if v {
|
if v {
|
||||||
t.run(vars)
|
t.run(vars, libs)
|
||||||
} else {
|
} else {
|
||||||
if let Some(e) = e {
|
if let Some(e) = e {
|
||||||
e.run(vars)
|
e.run(vars, libs)
|
||||||
} else {
|
} else {
|
||||||
VDataEnum::Tuple(vec![]).to()
|
VDataEnum::Tuple(vec![]).to()
|
||||||
}
|
}
|
||||||
@ -697,7 +729,7 @@ impl RStatementEnum {
|
|||||||
}
|
}
|
||||||
Self::While(c) => loop {
|
Self::While(c) => loop {
|
||||||
// While loops blocks can return a bool (false to break from the loop) or a 0-1 length tuple (0-length => continue, 1-length => break with value)
|
// While loops blocks can return a bool (false to break from the loop) or a 0-1 length tuple (0-length => continue, 1-length => break with value)
|
||||||
match c.run(vars).data {
|
match c.run(vars, libs).data {
|
||||||
VDataEnum::Bool(v) => {
|
VDataEnum::Bool(v) => {
|
||||||
if !v {
|
if !v {
|
||||||
break VDataEnum::Tuple(vec![]).to();
|
break VDataEnum::Tuple(vec![]).to();
|
||||||
@ -709,11 +741,11 @@ impl RStatementEnum {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
Self::For(v, c, b) => {
|
Self::For(v, c, b) => {
|
||||||
let c = c.run(vars);
|
let c = c.run(vars, libs);
|
||||||
let mut vars = vars.clone();
|
let mut vars = vars.clone();
|
||||||
let mut in_loop = |c| {
|
let mut in_loop = |c| {
|
||||||
vars[*v] = Arc::new(Mutex::new(c));
|
vars[*v] = Arc::new(Mutex::new(c));
|
||||||
b.run(&vars);
|
b.run(&vars, libs);
|
||||||
};
|
};
|
||||||
|
|
||||||
match c.data {
|
match c.data {
|
||||||
@ -736,14 +768,13 @@ impl RStatementEnum {
|
|||||||
}
|
}
|
||||||
VDataEnum::Tuple(vec![]).to()
|
VDataEnum::Tuple(vec![]).to()
|
||||||
}
|
}
|
||||||
Self::BuiltinFunction(v, args) => v.run(args, vars),
|
|
||||||
Self::Switch(switch_on, cases) => {
|
Self::Switch(switch_on, cases) => {
|
||||||
let switch_on = switch_on.run(vars);
|
let switch_on = switch_on.run(vars, libs);
|
||||||
let switch_on_type = switch_on.out();
|
let switch_on_type = switch_on.out();
|
||||||
let mut out = VDataEnum::Tuple(vec![]).to();
|
let mut out = VDataEnum::Tuple(vec![]).to();
|
||||||
for (case_type, case_action) in cases.iter() {
|
for (case_type, case_action) in cases.iter() {
|
||||||
if switch_on_type.fits_in(case_type).is_empty() {
|
if switch_on_type.fits_in(case_type).is_empty() {
|
||||||
out = case_action.run(vars);
|
out = case_action.run(vars, libs);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -752,7 +783,7 @@ impl RStatementEnum {
|
|||||||
Self::Match(match_on, cases) => 'm: {
|
Self::Match(match_on, cases) => 'm: {
|
||||||
for (case_condition, case_action) in cases {
|
for (case_condition, case_action) in cases {
|
||||||
// [t] => Some(t), t => Some(t), [] => None
|
// [t] => Some(t), t => Some(t), [] => None
|
||||||
if let Some(v) = match case_condition.run(vars).data {
|
if let Some(v) = match case_condition.run(vars, libs).data {
|
||||||
VDataEnum::Tuple(mut tuple) => tuple.pop(),
|
VDataEnum::Tuple(mut tuple) => tuple.pop(),
|
||||||
VDataEnum::Bool(v) => if v { Some(VDataEnum::Bool(v).to()) } else { None },
|
VDataEnum::Bool(v) => if v { Some(VDataEnum::Bool(v).to()) } else { None },
|
||||||
other => Some(other.to()),
|
other => Some(other.to()),
|
||||||
@ -760,14 +791,14 @@ impl RStatementEnum {
|
|||||||
let og = {
|
let og = {
|
||||||
std::mem::replace(&mut *vars[*match_on].lock().unwrap(), v)
|
std::mem::replace(&mut *vars[*match_on].lock().unwrap(), v)
|
||||||
};
|
};
|
||||||
let res = case_action.run(vars);
|
let res = case_action.run(vars, libs);
|
||||||
*vars[*match_on].lock().unwrap() = og;
|
*vars[*match_on].lock().unwrap() = og;
|
||||||
break 'm res;
|
break 'm res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
VDataEnum::Tuple(vec![]).to()
|
VDataEnum::Tuple(vec![]).to()
|
||||||
}
|
}
|
||||||
Self::IndexFixed(st, i) => st.run(vars).get(*i).unwrap(),
|
Self::IndexFixed(st, i) => st.run(vars, libs).get(*i).unwrap(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn out(&self) -> VType {
|
pub fn out(&self) -> VType {
|
||||||
@ -796,6 +827,7 @@ impl RStatementEnum {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Self::FunctionCall(f, args) => f.out_vt(&args.iter().map(|v| v.out()).collect()),
|
Self::FunctionCall(f, args) => f.out_vt(&args.iter().map(|v| v.out()).collect()),
|
||||||
|
Self::LibFunction(.., out) => out.clone(),
|
||||||
Self::Block(b) => b.out(),
|
Self::Block(b) => b.out(),
|
||||||
Self::If(_, a, b) => {
|
Self::If(_, a, b) => {
|
||||||
if let Some(b) = b {
|
if let Some(b) = b {
|
||||||
@ -877,13 +909,14 @@ impl RStatementEnum {
|
|||||||
pub struct RScript {
|
pub struct RScript {
|
||||||
main: RFunction,
|
main: RFunction,
|
||||||
vars: usize,
|
vars: usize,
|
||||||
|
libs: Arc<Vec<libs::Lib>>,
|
||||||
}
|
}
|
||||||
impl RScript {
|
impl RScript {
|
||||||
fn new(main: RFunction, vars: usize) -> Result<Self, ToRunnableError> {
|
fn new(main: RFunction, vars: usize, libs: Arc<Vec<libs::Lib>>) -> Result<Self, ToRunnableError> {
|
||||||
if main.inputs.len() != 1 {
|
if main.inputs.len() != 1 {
|
||||||
return Err(ToRunnableError::MainWrongInput);
|
return Err(ToRunnableError::MainWrongInput);
|
||||||
}
|
}
|
||||||
Ok(Self { main, vars })
|
Ok(Self { main, vars, libs })
|
||||||
}
|
}
|
||||||
pub fn run(&self, args: Vec<String>) -> VData {
|
pub fn run(&self, args: Vec<String>) -> VData {
|
||||||
let mut vars = Vec::with_capacity(self.vars);
|
let mut vars = Vec::with_capacity(self.vars);
|
||||||
@ -897,7 +930,7 @@ impl RScript {
|
|||||||
for _i in 1..self.vars {
|
for _i in 1..self.vars {
|
||||||
vars.push(am(VDataEnum::Tuple(vec![]).to()));
|
vars.push(am(VDataEnum::Tuple(vec![]).to()));
|
||||||
}
|
}
|
||||||
self.main.run(&vars)
|
self.main.run(&vars, &self.libs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,8 @@ use std::{
|
|||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::libs;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
block::RStatement,
|
block::RStatement,
|
||||||
val_data::{VData, VDataEnum, VDataThreadEnum},
|
val_data::{VData, VDataEnum, VDataThreadEnum},
|
||||||
@ -505,16 +507,21 @@ impl BuiltinFunction {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn run(&self, args: &Vec<RStatement>, vars: &Vec<Arc<Mutex<VData>>>) -> VData {
|
pub fn run(
|
||||||
|
&self,
|
||||||
|
args: &Vec<RStatement>,
|
||||||
|
vars: &Vec<Arc<Mutex<VData>>>,
|
||||||
|
libs: &Arc<Vec<libs::Lib>>,
|
||||||
|
) -> VData {
|
||||||
match self {
|
match self {
|
||||||
Self::Assume1 => {
|
Self::Assume1 => {
|
||||||
if let VDataEnum::Tuple(mut v) = args[0].run(vars).data {
|
if let VDataEnum::Tuple(mut v) = args[0].run(vars, libs).data {
|
||||||
v.pop().unwrap()
|
v.pop().unwrap()
|
||||||
} else {
|
} else {
|
||||||
panic!(
|
panic!(
|
||||||
"ASSUMPTION FAILED: assume1 :: {}",
|
"ASSUMPTION FAILED: assume1 :: {}",
|
||||||
if args.len() > 1 {
|
if args.len() > 1 {
|
||||||
if let VDataEnum::String(v) = args[1].run(vars).data {
|
if let VDataEnum::String(v) = args[1].run(vars, libs).data {
|
||||||
v
|
v
|
||||||
} else {
|
} else {
|
||||||
String::new()
|
String::new()
|
||||||
@ -526,7 +533,7 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
BuiltinFunction::Print => {
|
BuiltinFunction::Print => {
|
||||||
if let VDataEnum::String(arg) = args[0].run(vars).data {
|
if let VDataEnum::String(arg) = args[0].run(vars, libs).data {
|
||||||
print!("{}", arg);
|
print!("{}", arg);
|
||||||
VDataEnum::Tuple(vec![]).to()
|
VDataEnum::Tuple(vec![]).to()
|
||||||
} else {
|
} else {
|
||||||
@ -534,7 +541,7 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
BuiltinFunction::Println => {
|
BuiltinFunction::Println => {
|
||||||
if let VDataEnum::String(arg) = args[0].run(vars).data {
|
if let VDataEnum::String(arg) = args[0].run(vars, libs).data {
|
||||||
println!("{}", arg);
|
println!("{}", arg);
|
||||||
VDataEnum::Tuple(vec![]).to()
|
VDataEnum::Tuple(vec![]).to()
|
||||||
} else {
|
} else {
|
||||||
@ -542,7 +549,7 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
BuiltinFunction::Debug => {
|
BuiltinFunction::Debug => {
|
||||||
println!("{:#?}", args[0].run(vars).data);
|
println!("{:#?}", args[0].run(vars, libs).data);
|
||||||
VDataEnum::Tuple(vec![]).to()
|
VDataEnum::Tuple(vec![]).to()
|
||||||
}
|
}
|
||||||
Self::StdinReadLine => {
|
Self::StdinReadLine => {
|
||||||
@ -551,13 +558,15 @@ impl BuiltinFunction {
|
|||||||
VDataEnum::String(line.trim_end_matches(['\n', '\r']).to_string()).to()
|
VDataEnum::String(line.trim_end_matches(['\n', '\r']).to_string()).to()
|
||||||
}
|
}
|
||||||
BuiltinFunction::ToString => {
|
BuiltinFunction::ToString => {
|
||||||
VDataEnum::String(format!("{}", args[0].run(vars).data)).to()
|
VDataEnum::String(format!("{}", args[0].run(vars, libs).data)).to()
|
||||||
}
|
}
|
||||||
BuiltinFunction::Format => {
|
BuiltinFunction::Format => {
|
||||||
if let VDataEnum::String(mut text) = args.first().unwrap().run(vars).data {
|
if let VDataEnum::String(mut text) = args.first().unwrap().run(vars, libs).data {
|
||||||
for (i, arg) in args.iter().skip(1).enumerate() {
|
for (i, arg) in args.iter().skip(1).enumerate() {
|
||||||
text =
|
text = text.replace(
|
||||||
text.replace(&format!("{{{i}}}"), &format!("{}", arg.run(vars).data));
|
&format!("{{{i}}}"),
|
||||||
|
&format!("{}", arg.run(vars, libs).data),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
VDataEnum::String(text).to()
|
VDataEnum::String(text).to()
|
||||||
} else {
|
} else {
|
||||||
@ -566,7 +575,7 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
BuiltinFunction::ParseInt => {
|
BuiltinFunction::ParseInt => {
|
||||||
if args.len() == 1 {
|
if args.len() == 1 {
|
||||||
if let VDataEnum::String(s) = args[0].run(vars).data {
|
if let VDataEnum::String(s) = args[0].run(vars, libs).data {
|
||||||
if let Ok(s) = s.parse() {
|
if let Ok(s) = s.parse() {
|
||||||
VDataEnum::Int(s).to()
|
VDataEnum::Int(s).to()
|
||||||
} else {
|
} else {
|
||||||
@ -581,7 +590,7 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
BuiltinFunction::ParseFloat => {
|
BuiltinFunction::ParseFloat => {
|
||||||
if args.len() == 1 {
|
if args.len() == 1 {
|
||||||
if let VDataEnum::String(s) = args[0].run(vars).data {
|
if let VDataEnum::String(s) = args[0].run(vars, libs).data {
|
||||||
if let Ok(s) = s.parse() {
|
if let Ok(s) = s.parse() {
|
||||||
VDataEnum::Float(s).to()
|
VDataEnum::Float(s).to()
|
||||||
} else {
|
} else {
|
||||||
@ -596,15 +605,15 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
BuiltinFunction::Run => {
|
BuiltinFunction::Run => {
|
||||||
if args.len() >= 1 {
|
if args.len() >= 1 {
|
||||||
if let VDataEnum::Function(f) = args[0].run(vars).data {
|
if let VDataEnum::Function(f) = args[0].run(vars, libs).data {
|
||||||
if f.inputs.len() != args.len() - 1 {
|
if f.inputs.len() != args.len() - 1 {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
for (i, var) in f.inputs.iter().enumerate() {
|
for (i, var) in f.inputs.iter().enumerate() {
|
||||||
let val = args[i + 1].run(vars);
|
let val = args[i + 1].run(vars, libs);
|
||||||
*vars[*var].lock().unwrap() = val;
|
*vars[*var].lock().unwrap() = val;
|
||||||
}
|
}
|
||||||
f.run(vars)
|
f.run(vars, libs)
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
@ -614,7 +623,7 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
BuiltinFunction::Thread => {
|
BuiltinFunction::Thread => {
|
||||||
if args.len() >= 1 {
|
if args.len() >= 1 {
|
||||||
if let VDataEnum::Function(f) = args[0].run(vars).data {
|
if let VDataEnum::Function(f) = args[0].run(vars, libs).data {
|
||||||
if f.inputs.len() != args.len() - 1 {
|
if f.inputs.len() != args.len() - 1 {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
@ -622,14 +631,15 @@ impl BuiltinFunction {
|
|||||||
let mut thread_vars = vars.clone();
|
let mut thread_vars = vars.clone();
|
||||||
let mut run_input_types = vec![];
|
let mut run_input_types = vec![];
|
||||||
for (i, var) in f.inputs.iter().enumerate() {
|
for (i, var) in f.inputs.iter().enumerate() {
|
||||||
let val = args[i + 1].run(vars);
|
let val = args[i + 1].run(vars, libs);
|
||||||
run_input_types.push(val.out_single());
|
run_input_types.push(val.out_single());
|
||||||
thread_vars[*var] = Arc::new(Mutex::new(val));
|
thread_vars[*var] = Arc::new(Mutex::new(val));
|
||||||
}
|
}
|
||||||
let out_type = f.out(&run_input_types);
|
let out_type = f.out(&run_input_types);
|
||||||
|
let libs = libs.clone();
|
||||||
VDataEnum::Thread(
|
VDataEnum::Thread(
|
||||||
VDataThreadEnum::Running(std::thread::spawn(move || {
|
VDataThreadEnum::Running(std::thread::spawn(move || {
|
||||||
f.run(&thread_vars)
|
f.run(&thread_vars, &libs)
|
||||||
}))
|
}))
|
||||||
.to(),
|
.to(),
|
||||||
out_type,
|
out_type,
|
||||||
@ -644,7 +654,7 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
BuiltinFunction::Await => {
|
BuiltinFunction::Await => {
|
||||||
if args.len() == 1 {
|
if args.len() == 1 {
|
||||||
if let VDataEnum::Thread(t, _) = args[0].run(vars).data {
|
if let VDataEnum::Thread(t, _) = args[0].run(vars, libs).data {
|
||||||
t.get()
|
t.get()
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
@ -655,7 +665,7 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
BuiltinFunction::Sleep => {
|
BuiltinFunction::Sleep => {
|
||||||
if args.len() == 1 {
|
if args.len() == 1 {
|
||||||
match args[0].run(vars).data {
|
match args[0].run(vars, libs).data {
|
||||||
VDataEnum::Int(v) => std::thread::sleep(Duration::from_secs(v as _)),
|
VDataEnum::Int(v) => std::thread::sleep(Duration::from_secs(v as _)),
|
||||||
VDataEnum::Float(v) => std::thread::sleep(Duration::from_secs_f64(v)),
|
VDataEnum::Float(v) => std::thread::sleep(Duration::from_secs_f64(v)),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
@ -667,7 +677,7 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::Exit => {
|
Self::Exit => {
|
||||||
if let Some(s) = args.first() {
|
if let Some(s) = args.first() {
|
||||||
if let VDataEnum::Int(v) = s.run(vars).data {
|
if let VDataEnum::Int(v) = s.run(vars, libs).data {
|
||||||
std::process::exit(v as _);
|
std::process::exit(v as _);
|
||||||
} else {
|
} else {
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
@ -678,7 +688,7 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::FsList => {
|
Self::FsList => {
|
||||||
if args.len() > 0 {
|
if args.len() > 0 {
|
||||||
if let VDataEnum::String(path) = args[0].run(vars).data {
|
if let VDataEnum::String(path) = args[0].run(vars, libs).data {
|
||||||
if args.len() > 1 {
|
if args.len() > 1 {
|
||||||
todo!("fs_list advanced filters")
|
todo!("fs_list advanced filters")
|
||||||
}
|
}
|
||||||
@ -713,7 +723,7 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::FsRead => {
|
Self::FsRead => {
|
||||||
if args.len() > 0 {
|
if args.len() > 0 {
|
||||||
if let VDataEnum::String(path) = args[0].run(vars).data {
|
if let VDataEnum::String(path) = args[0].run(vars, libs).data {
|
||||||
if let Ok(data) = std::fs::read(path) {
|
if let Ok(data) = std::fs::read(path) {
|
||||||
VDataEnum::List(
|
VDataEnum::List(
|
||||||
VSingleType::Int.into(),
|
VSingleType::Int.into(),
|
||||||
@ -735,7 +745,7 @@ impl BuiltinFunction {
|
|||||||
Self::FsWrite => {
|
Self::FsWrite => {
|
||||||
if args.len() > 1 {
|
if args.len() > 1 {
|
||||||
if let (VDataEnum::String(path), VDataEnum::List(_, data)) =
|
if let (VDataEnum::String(path), VDataEnum::List(_, data)) =
|
||||||
(args[0].run(vars).data, args[1].run(vars).data)
|
(args[0].run(vars, libs).data, args[1].run(vars, libs).data)
|
||||||
{
|
{
|
||||||
if let Some(bytes) = vdata_to_bytes(&data) {
|
if let Some(bytes) = vdata_to_bytes(&data) {
|
||||||
let file_path: PathBuf = path.into();
|
let file_path: PathBuf = path.into();
|
||||||
@ -760,7 +770,7 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::BytesToString => {
|
Self::BytesToString => {
|
||||||
if args.len() == 1 {
|
if args.len() == 1 {
|
||||||
if let VDataEnum::List(_, byte_data) = args[0].run(vars).data {
|
if let VDataEnum::List(_, byte_data) = args[0].run(vars, libs).data {
|
||||||
if let Some(bytes) = vdata_to_bytes(&byte_data) {
|
if let Some(bytes) = vdata_to_bytes(&byte_data) {
|
||||||
match String::from_utf8(bytes) {
|
match String::from_utf8(bytes) {
|
||||||
Ok(v) => VDataEnum::String(v).to(),
|
Ok(v) => VDataEnum::String(v).to(),
|
||||||
@ -788,7 +798,7 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::StringToBytes => {
|
Self::StringToBytes => {
|
||||||
if args.len() == 1 {
|
if args.len() == 1 {
|
||||||
if let VDataEnum::String(s) = args[0].run(vars).data {
|
if let VDataEnum::String(s) = args[0].run(vars, libs).data {
|
||||||
VDataEnum::List(
|
VDataEnum::List(
|
||||||
VSingleType::Int.into(),
|
VSingleType::Int.into(),
|
||||||
s.bytes().map(|v| VDataEnum::Int(v as isize).to()).collect(),
|
s.bytes().map(|v| VDataEnum::Int(v as isize).to()).collect(),
|
||||||
@ -803,10 +813,10 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::RunCommand | Self::RunCommandGetBytes => {
|
Self::RunCommand | Self::RunCommandGetBytes => {
|
||||||
if args.len() > 0 {
|
if args.len() > 0 {
|
||||||
if let VDataEnum::String(s) = args[0].run(vars).data {
|
if let VDataEnum::String(s) = args[0].run(vars, libs).data {
|
||||||
let mut command = std::process::Command::new(s);
|
let mut command = std::process::Command::new(s);
|
||||||
if args.len() > 1 {
|
if args.len() > 1 {
|
||||||
if let VDataEnum::List(_, args) = args[1].run(vars).data {
|
if let VDataEnum::List(_, args) = args[1].run(vars, libs).data {
|
||||||
for arg in args {
|
for arg in args {
|
||||||
if let VDataEnum::String(v) = arg.data {
|
if let VDataEnum::String(v) = arg.data {
|
||||||
command.arg(v);
|
command.arg(v);
|
||||||
@ -865,7 +875,7 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::Add => {
|
Self::Add => {
|
||||||
if args.len() == 2 {
|
if args.len() == 2 {
|
||||||
match (args[0].run(vars).data, args[1].run(vars).data) {
|
match (args[0].run(vars, libs).data, args[1].run(vars, libs).data) {
|
||||||
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Int(a + b).to(),
|
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Int(a + b).to(),
|
||||||
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
||||||
VDataEnum::Float(a as f64 + b).to()
|
VDataEnum::Float(a as f64 + b).to()
|
||||||
@ -882,7 +892,7 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::Sub => {
|
Self::Sub => {
|
||||||
if args.len() == 2 {
|
if args.len() == 2 {
|
||||||
match (args[0].run(vars).data, args[1].run(vars).data) {
|
match (args[0].run(vars, libs).data, args[1].run(vars, libs).data) {
|
||||||
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Int(a - b).to(),
|
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Int(a - b).to(),
|
||||||
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
||||||
VDataEnum::Float(a as f64 - b).to()
|
VDataEnum::Float(a as f64 - b).to()
|
||||||
@ -899,7 +909,7 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::Mul => {
|
Self::Mul => {
|
||||||
if args.len() == 2 {
|
if args.len() == 2 {
|
||||||
match (args[0].run(vars).data, args[1].run(vars).data) {
|
match (args[0].run(vars, libs).data, args[1].run(vars, libs).data) {
|
||||||
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Int(a * b).to(),
|
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Int(a * b).to(),
|
||||||
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
||||||
VDataEnum::Float(a as f64 * b).to()
|
VDataEnum::Float(a as f64 * b).to()
|
||||||
@ -916,7 +926,7 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::Div => {
|
Self::Div => {
|
||||||
if args.len() == 2 {
|
if args.len() == 2 {
|
||||||
match (args[0].run(vars).data, args[1].run(vars).data) {
|
match (args[0].run(vars, libs).data, args[1].run(vars, libs).data) {
|
||||||
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Int(a / b).to(),
|
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Int(a / b).to(),
|
||||||
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
||||||
VDataEnum::Float(a as f64 / b).to()
|
VDataEnum::Float(a as f64 / b).to()
|
||||||
@ -933,7 +943,7 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::Mod => {
|
Self::Mod => {
|
||||||
if args.len() == 2 {
|
if args.len() == 2 {
|
||||||
match (args[0].run(vars).data, args[1].run(vars).data) {
|
match (args[0].run(vars, libs).data, args[1].run(vars, libs).data) {
|
||||||
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Int(a % b).to(),
|
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Int(a % b).to(),
|
||||||
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
||||||
VDataEnum::Float(a as f64 % b).to()
|
VDataEnum::Float(a as f64 % b).to()
|
||||||
@ -950,7 +960,7 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::Pow => {
|
Self::Pow => {
|
||||||
if args.len() == 2 {
|
if args.len() == 2 {
|
||||||
match (args[0].run(vars).data, args[1].run(vars).data) {
|
match (args[0].run(vars, libs).data, args[1].run(vars, libs).data) {
|
||||||
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Int(if b == 0 {
|
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Int(if b == 0 {
|
||||||
1
|
1
|
||||||
} else if b > 0 {
|
} else if b > 0 {
|
||||||
@ -976,7 +986,7 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::Eq => {
|
Self::Eq => {
|
||||||
if args.len() == 2 {
|
if args.len() == 2 {
|
||||||
match (args[0].run(vars).data, args[1].run(vars).data) {
|
match (args[0].run(vars, libs).data, args[1].run(vars, libs).data) {
|
||||||
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Bool(a == b).to(),
|
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Bool(a == b).to(),
|
||||||
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
||||||
VDataEnum::Bool(a as f64 == b).to()
|
VDataEnum::Bool(a as f64 == b).to()
|
||||||
@ -996,7 +1006,7 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::Gt => {
|
Self::Gt => {
|
||||||
if args.len() == 2 {
|
if args.len() == 2 {
|
||||||
match (args[0].run(vars).data, args[1].run(vars).data) {
|
match (args[0].run(vars, libs).data, args[1].run(vars, libs).data) {
|
||||||
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Bool(a > b).to(),
|
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Bool(a > b).to(),
|
||||||
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
||||||
VDataEnum::Bool(a as f64 > b).to()
|
VDataEnum::Bool(a as f64 > b).to()
|
||||||
@ -1013,7 +1023,7 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::Lt => {
|
Self::Lt => {
|
||||||
if args.len() == 2 {
|
if args.len() == 2 {
|
||||||
match (args[0].run(vars).data, args[1].run(vars).data) {
|
match (args[0].run(vars, libs).data, args[1].run(vars, libs).data) {
|
||||||
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Bool(a < b).to(),
|
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Bool(a < b).to(),
|
||||||
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
||||||
VDataEnum::Bool((a as f64) < b).to()
|
VDataEnum::Bool((a as f64) < b).to()
|
||||||
@ -1030,7 +1040,7 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::Gtoe => {
|
Self::Gtoe => {
|
||||||
if args.len() == 2 {
|
if args.len() == 2 {
|
||||||
match (args[0].run(vars).data, args[1].run(vars).data) {
|
match (args[0].run(vars, libs).data, args[1].run(vars, libs).data) {
|
||||||
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Bool(a >= b).to(),
|
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Bool(a >= b).to(),
|
||||||
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
||||||
VDataEnum::Bool(a as f64 >= b).to()
|
VDataEnum::Bool(a as f64 >= b).to()
|
||||||
@ -1047,7 +1057,7 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::Ltoe => {
|
Self::Ltoe => {
|
||||||
if args.len() == 2 {
|
if args.len() == 2 {
|
||||||
match (args[0].run(vars).data, args[1].run(vars).data) {
|
match (args[0].run(vars, libs).data, args[1].run(vars, libs).data) {
|
||||||
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Bool(a <= b).to(),
|
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Bool(a <= b).to(),
|
||||||
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
||||||
VDataEnum::Bool(a as f64 <= b).to()
|
VDataEnum::Bool(a as f64 <= b).to()
|
||||||
@ -1064,7 +1074,7 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::Min => {
|
Self::Min => {
|
||||||
if args.len() == 2 {
|
if args.len() == 2 {
|
||||||
match (args[0].run(vars).data, args[1].run(vars).data) {
|
match (args[0].run(vars, libs).data, args[1].run(vars, libs).data) {
|
||||||
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Int(a.min(b)).to(),
|
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Int(a.min(b)).to(),
|
||||||
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
||||||
VDataEnum::Float((a as f64).min(b)).to()
|
VDataEnum::Float((a as f64).min(b)).to()
|
||||||
@ -1083,7 +1093,7 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::Max => {
|
Self::Max => {
|
||||||
if args.len() == 2 {
|
if args.len() == 2 {
|
||||||
match (args[0].run(vars).data, args[1].run(vars).data) {
|
match (args[0].run(vars, libs).data, args[1].run(vars, libs).data) {
|
||||||
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Int(a.max(b)).to(),
|
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Int(a.max(b)).to(),
|
||||||
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
||||||
VDataEnum::Float((a as f64).max(b)).to()
|
VDataEnum::Float((a as f64).max(b)).to()
|
||||||
@ -1102,9 +1112,9 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::Push => {
|
Self::Push => {
|
||||||
if args.len() == 2 {
|
if args.len() == 2 {
|
||||||
if let VDataEnum::Reference(v) = args[0].run(vars).data {
|
if let VDataEnum::Reference(v) = args[0].run(vars, libs).data {
|
||||||
if let VDataEnum::List(_, v) = &mut v.lock().unwrap().data {
|
if let VDataEnum::List(_, v) = &mut v.lock().unwrap().data {
|
||||||
v.push(args[1].run(vars));
|
v.push(args[1].run(vars, libs));
|
||||||
}
|
}
|
||||||
VDataEnum::Tuple(vec![]).to()
|
VDataEnum::Tuple(vec![]).to()
|
||||||
} else {
|
} else {
|
||||||
@ -1117,10 +1127,10 @@ impl BuiltinFunction {
|
|||||||
Self::Insert => {
|
Self::Insert => {
|
||||||
if args.len() == 3 {
|
if args.len() == 3 {
|
||||||
if let (VDataEnum::Reference(v), VDataEnum::Int(i)) =
|
if let (VDataEnum::Reference(v), VDataEnum::Int(i)) =
|
||||||
(args[0].run(vars).data, args[2].run(vars).data)
|
(args[0].run(vars, libs).data, args[2].run(vars, libs).data)
|
||||||
{
|
{
|
||||||
if let VDataEnum::List(_, v) = &mut v.lock().unwrap().data {
|
if let VDataEnum::List(_, v) = &mut v.lock().unwrap().data {
|
||||||
v.insert(i as _, args[1].run(vars));
|
v.insert(i as _, args[1].run(vars, libs));
|
||||||
}
|
}
|
||||||
VDataEnum::Tuple(vec![]).to()
|
VDataEnum::Tuple(vec![]).to()
|
||||||
} else {
|
} else {
|
||||||
@ -1132,7 +1142,7 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::Pop => {
|
Self::Pop => {
|
||||||
if args.len() == 1 {
|
if args.len() == 1 {
|
||||||
if let VDataEnum::Reference(v) = args[0].run(vars).data {
|
if let VDataEnum::Reference(v) = args[0].run(vars, libs).data {
|
||||||
if let VDataEnum::List(_, v) = &mut v.lock().unwrap().data {
|
if let VDataEnum::List(_, v) = &mut v.lock().unwrap().data {
|
||||||
v.pop().unwrap_or_else(|| VDataEnum::Tuple(vec![]).to())
|
v.pop().unwrap_or_else(|| VDataEnum::Tuple(vec![]).to())
|
||||||
} else {
|
} else {
|
||||||
@ -1148,7 +1158,7 @@ impl BuiltinFunction {
|
|||||||
Self::Remove => {
|
Self::Remove => {
|
||||||
if args.len() == 2 {
|
if args.len() == 2 {
|
||||||
if let (VDataEnum::Reference(v), VDataEnum::Int(i)) =
|
if let (VDataEnum::Reference(v), VDataEnum::Int(i)) =
|
||||||
(args[0].run(vars).data, args[1].run(vars).data)
|
(args[0].run(vars, libs).data, args[1].run(vars, libs).data)
|
||||||
{
|
{
|
||||||
if let VDataEnum::List(_, v) = &mut v.lock().unwrap().data {
|
if let VDataEnum::List(_, v) = &mut v.lock().unwrap().data {
|
||||||
if v.len() > i as _ && i >= 0 {
|
if v.len() > i as _ && i >= 0 {
|
||||||
@ -1169,19 +1179,21 @@ impl BuiltinFunction {
|
|||||||
Self::Get => {
|
Self::Get => {
|
||||||
if args.len() == 2 {
|
if args.len() == 2 {
|
||||||
if let (VDataEnum::Reference(v), VDataEnum::Int(i)) =
|
if let (VDataEnum::Reference(v), VDataEnum::Int(i)) =
|
||||||
(args[0].run(vars).data, args[1].run(vars).data)
|
(args[0].run(vars, libs).data, args[1].run(vars, libs).data)
|
||||||
{
|
{
|
||||||
if let VDataEnum::List(_, v) = &mut v.lock().unwrap().data {
|
if let VDataEnum::List(_, v) | VDataEnum::Tuple(v) =
|
||||||
|
&mut v.lock().unwrap().data
|
||||||
|
{
|
||||||
if i >= 0 {
|
if i >= 0 {
|
||||||
match v.get(i as usize) {
|
match v.get(i as usize) {
|
||||||
Some(v) => v.clone(),
|
Some(v) => VDataEnum::Tuple(vec![v.clone()]).to(),
|
||||||
None => VDataEnum::Tuple(vec![]).to(),
|
None => VDataEnum::Tuple(vec![]).to(),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
VDataEnum::Tuple(vec![]).to()
|
VDataEnum::Tuple(vec![]).to()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
unreachable!("get: not a list")
|
unreachable!("get: not a list/tuple")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
unreachable!("get: not a reference and index")
|
unreachable!("get: not a reference and index")
|
||||||
@ -1192,7 +1204,7 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::Len => {
|
Self::Len => {
|
||||||
if args.len() == 1 {
|
if args.len() == 1 {
|
||||||
VDataEnum::Int(match args[0].run(vars).data {
|
VDataEnum::Int(match args[0].run(vars, libs).data {
|
||||||
VDataEnum::String(v) => v.len(),
|
VDataEnum::String(v) => v.len(),
|
||||||
VDataEnum::Tuple(v) => v.len(),
|
VDataEnum::Tuple(v) => v.len(),
|
||||||
VDataEnum::List(_, v) => v.len(),
|
VDataEnum::List(_, v) => v.len(),
|
||||||
@ -1205,8 +1217,8 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::Contains => {
|
Self::Contains => {
|
||||||
if args.len() == 2 {
|
if args.len() == 2 {
|
||||||
if let VDataEnum::String(a1) = args[0].run(vars).data {
|
if let VDataEnum::String(a1) = args[0].run(vars, libs).data {
|
||||||
if let VDataEnum::String(a2) = args[1].run(vars).data {
|
if let VDataEnum::String(a2) = args[1].run(vars, libs).data {
|
||||||
VDataEnum::Bool(a1.contains(a2.as_str())).to()
|
VDataEnum::Bool(a1.contains(a2.as_str())).to()
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
@ -1220,8 +1232,8 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::StartsWith => {
|
Self::StartsWith => {
|
||||||
if args.len() == 2 {
|
if args.len() == 2 {
|
||||||
if let VDataEnum::String(a1) = args[0].run(vars).data {
|
if let VDataEnum::String(a1) = args[0].run(vars, libs).data {
|
||||||
if let VDataEnum::String(a2) = args[1].run(vars).data {
|
if let VDataEnum::String(a2) = args[1].run(vars, libs).data {
|
||||||
VDataEnum::Bool(a1.starts_with(a2.as_str())).to()
|
VDataEnum::Bool(a1.starts_with(a2.as_str())).to()
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
@ -1235,8 +1247,8 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::EndsWith => {
|
Self::EndsWith => {
|
||||||
if args.len() == 2 {
|
if args.len() == 2 {
|
||||||
if let VDataEnum::String(a1) = args[0].run(vars).data {
|
if let VDataEnum::String(a1) = args[0].run(vars, libs).data {
|
||||||
if let VDataEnum::String(a2) = args[1].run(vars).data {
|
if let VDataEnum::String(a2) = args[1].run(vars, libs).data {
|
||||||
VDataEnum::Bool(a1.ends_with(a2.as_str())).to()
|
VDataEnum::Bool(a1.ends_with(a2.as_str())).to()
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
@ -1250,7 +1262,7 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::Trim => {
|
Self::Trim => {
|
||||||
if args.len() == 1 {
|
if args.len() == 1 {
|
||||||
if let VDataEnum::String(a) = args[0].run(vars).data {
|
if let VDataEnum::String(a) = args[0].run(vars, libs).data {
|
||||||
VDataEnum::String(a.trim().to_string()).to()
|
VDataEnum::String(a.trim().to_string()).to()
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
@ -1261,17 +1273,17 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::Substring => {
|
Self::Substring => {
|
||||||
if args.len() >= 2 {
|
if args.len() >= 2 {
|
||||||
if let VDataEnum::String(a) = args[0].run(vars).data {
|
if let VDataEnum::String(a) = args[0].run(vars, libs).data {
|
||||||
if args.len() > 3 {
|
if args.len() > 3 {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
let left = if let VDataEnum::Int(left) = args[1].run(vars).data {
|
let left = if let VDataEnum::Int(left) = args[1].run(vars, libs).data {
|
||||||
left
|
left
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
let len = if args.len() == 3 {
|
let len = if args.len() == 3 {
|
||||||
if let VDataEnum::Int(len) = args[2].run(vars).data {
|
if let VDataEnum::Int(len) = args[2].run(vars, libs).data {
|
||||||
Some(len)
|
Some(len)
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
@ -1300,7 +1312,7 @@ impl BuiltinFunction {
|
|||||||
Self::Regex => {
|
Self::Regex => {
|
||||||
if args.len() == 2 {
|
if args.len() == 2 {
|
||||||
if let (VDataEnum::String(a), VDataEnum::String(regex)) =
|
if let (VDataEnum::String(a), VDataEnum::String(regex)) =
|
||||||
(args[0].run(vars).data, args[1].run(vars).data)
|
(args[0].run(vars, libs).data, args[1].run(vars, libs).data)
|
||||||
{
|
{
|
||||||
match regex::Regex::new(regex.as_str()) {
|
match regex::Regex::new(regex.as_str()) {
|
||||||
Ok(regex) => {
|
Ok(regex) => {
|
||||||
|
Loading…
Reference in New Issue
Block a user