- changed the list type from [t] to [t ...]

- added more examples to the readme
This commit is contained in:
Dummi26
2023-04-13 17:40:25 +02:00
parent a6389b7ac0
commit a2a976c7f9
11 changed files with 935 additions and 106 deletions

495
mers/Cargo.lock generated
View File

@@ -11,6 +11,197 @@ dependencies = [
"memchr",
]
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "cc"
version = "1.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "crossbeam-channel"
version = "0.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200"
dependencies = [
"cfg-if",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b"
dependencies = [
"cfg-if",
]
[[package]]
name = "edit"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c562aa71f7bc691fde4c6bf5f93ae5a5298b617c2eb44c76c87832299a17fbb4"
dependencies = [
"tempfile",
"which",
]
[[package]]
name = "either"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
[[package]]
name = "errno"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
dependencies = [
"errno-dragonfly",
"libc",
"windows-sys 0.48.0",
]
[[package]]
name = "errno-dragonfly"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
dependencies = [
"cc",
"libc",
]
[[package]]
name = "fastrand"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be"
dependencies = [
"instant",
]
[[package]]
name = "filetime"
version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5cbc844cecaee9d4443931972e1289c8ff485cb4cc2767cb03ca139ed6885153"
dependencies = [
"cfg-if",
"libc",
"redox_syscall 0.2.16",
"windows-sys 0.48.0",
]
[[package]]
name = "fsevent-sys"
version = "4.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2"
dependencies = [
"libc",
]
[[package]]
name = "hermit-abi"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
[[package]]
name = "inotify"
version = "0.9.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff"
dependencies = [
"bitflags",
"inotify-sys",
"libc",
]
[[package]]
name = "inotify-sys"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb"
dependencies = [
"libc",
]
[[package]]
name = "instant"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
dependencies = [
"cfg-if",
]
[[package]]
name = "io-lifetimes"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220"
dependencies = [
"hermit-abi",
"libc",
"windows-sys 0.48.0",
]
[[package]]
name = "kqueue"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c8fc60ba15bf51257aa9807a48a61013db043fcf3a78cb0d916e8e396dcad98"
dependencies = [
"kqueue-sys",
"libc",
]
[[package]]
name = "kqueue-sys"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8367585489f01bc55dd27404dcf56b95e6da061a256a666ab23be9ba96a2e587"
dependencies = [
"bitflags",
"libc",
]
[[package]]
name = "libc"
version = "0.2.141"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5"
[[package]]
name = "linux-raw-sys"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d59d8c75012853d2e872fb56bc8a2e53718e2cafe1a4c823143141c6d90c322f"
[[package]]
name = "log"
version = "0.4.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
dependencies = [
"cfg-if",
]
[[package]]
name = "memchr"
version = "2.5.0"
@@ -21,7 +212,64 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
name = "mers"
version = "0.1.0"
dependencies = [
"edit",
"notify",
"regex",
"static_assertions",
]
[[package]]
name = "mio"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9"
dependencies = [
"libc",
"log",
"wasi",
"windows-sys 0.45.0",
]
[[package]]
name = "notify"
version = "5.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58ea850aa68a06e48fdb069c0ec44d0d64c8dbffa49bf3b6f7f0a901fdea1ba9"
dependencies = [
"bitflags",
"crossbeam-channel",
"filetime",
"fsevent-sys",
"inotify",
"kqueue",
"libc",
"mio",
"walkdir",
"windows-sys 0.42.0",
]
[[package]]
name = "once_cell"
version = "1.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
[[package]]
name = "redox_syscall"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
dependencies = [
"bitflags",
]
[[package]]
name = "redox_syscall"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
dependencies = [
"bitflags",
]
[[package]]
@@ -40,3 +288,250 @@ name = "regex-syntax"
version = "0.6.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
[[package]]
name = "rustix"
version = "0.37.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85597d61f83914ddeba6a47b3b8ffe7365107221c2e557ed94426489fefb5f77"
dependencies = [
"bitflags",
"errno",
"io-lifetimes",
"libc",
"linux-raw-sys",
"windows-sys 0.48.0",
]
[[package]]
name = "same-file"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
dependencies = [
"winapi-util",
]
[[package]]
name = "static_assertions"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
name = "tempfile"
version = "3.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998"
dependencies = [
"cfg-if",
"fastrand",
"redox_syscall 0.3.5",
"rustix",
"windows-sys 0.45.0",
]
[[package]]
name = "walkdir"
version = "2.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698"
dependencies = [
"same-file",
"winapi-util",
]
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "which"
version = "4.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269"
dependencies = [
"either",
"libc",
"once_cell",
]
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [
"winapi",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
dependencies = [
"windows_aarch64_gnullvm 0.42.2",
"windows_aarch64_msvc 0.42.2",
"windows_i686_gnu 0.42.2",
"windows_i686_msvc 0.42.2",
"windows_x86_64_gnu 0.42.2",
"windows_x86_64_gnullvm 0.42.2",
"windows_x86_64_msvc 0.42.2",
]
[[package]]
name = "windows-sys"
version = "0.45.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
dependencies = [
"windows-targets 0.42.2",
]
[[package]]
name = "windows-sys"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
"windows-targets 0.48.0",
]
[[package]]
name = "windows-targets"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
dependencies = [
"windows_aarch64_gnullvm 0.42.2",
"windows_aarch64_msvc 0.42.2",
"windows_i686_gnu 0.42.2",
"windows_i686_msvc 0.42.2",
"windows_x86_64_gnu 0.42.2",
"windows_x86_64_gnullvm 0.42.2",
"windows_x86_64_msvc 0.42.2",
]
[[package]]
name = "windows-targets"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5"
dependencies = [
"windows_aarch64_gnullvm 0.48.0",
"windows_aarch64_msvc 0.48.0",
"windows_i686_gnu 0.48.0",
"windows_i686_msvc 0.48.0",
"windows_x86_64_gnu 0.48.0",
"windows_x86_64_gnullvm 0.48.0",
"windows_x86_64_msvc 0.48.0",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
[[package]]
name = "windows_aarch64_msvc"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
[[package]]
name = "windows_aarch64_msvc"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
[[package]]
name = "windows_i686_gnu"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
[[package]]
name = "windows_i686_gnu"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
[[package]]
name = "windows_i686_msvc"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
[[package]]
name = "windows_i686_msvc"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
[[package]]
name = "windows_x86_64_gnu"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
[[package]]
name = "windows_x86_64_gnu"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
[[package]]
name = "windows_x86_64_msvc"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
[[package]]
name = "windows_x86_64_msvc"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"

View File

@@ -10,4 +10,7 @@ name = "mers"
path = "src/main.rs"
[dependencies]
edit = "0.1.4"
notify = "5.1.0"
regex = "1.7.2"
static_assertions = "1.1.0"

View File

@@ -1,24 +1,172 @@
use std::time::Instant;
use std::{
fs,
sync::{Arc, Mutex},
time::Instant,
};
use notify::Watcher as FsWatcher;
pub mod libs;
pub mod parse;
pub mod script;
fn main() {
let args: Vec<_> = std::env::args().skip(1).collect();
let path = std::env::args().nth(1).unwrap();
let script = parse::parse::parse(&mut if path.trim() == "-e" {
parse::file::File::new(
std::env::args()
.skip(2)
.map(|mut v| {
v.push('\n');
v
})
.collect::<String>(),
path.into(),
)
} else {
parse::file::File::new(std::fs::read_to_string(&path).unwrap(), path.into())
let script = parse::parse::parse(&mut match args.len() {
0 => {
println!("Please provide some arguments, such as the path to a file or \"-e <code>\".");
std::process::exit(100);
}
_ => {
if args[0].trim_start().starts_with("-") {
let mut execute = false;
let mut verbose = 0;
let mut interactive = 0;
let mut interactive_use_new_terminal = false;
let mut prev_char = None;
let mut advanced = false;
for ch in args[0][1..].chars() {
if !advanced {
if ch == '+' {
advanced = true;
continue;
}
match ch {
'e' => execute = true,
'v' => verbose += 1,
'i' => interactive += 1,
ch => {
eprintln!("Ignoring -{ch}. (unknown char)");
continue;
}
}
prev_char = Some(ch);
} else {
if let Some(prev_char) = prev_char {
match prev_char {
'i' => {
match ch {
't' => interactive_use_new_terminal = true,
_ => eprintln!("Ignoring i+{ch}. (unknown adv char)"),
}
}
_ => (),
}
} else {
eprintln!("Ignoring advanced args because there was no previous argument.");
}
advanced = false;
}
}
if verbose != 0 {
eprintln!("info: set verbosity level to {verbose}. this doesn't do anything yet. [TODO!]");
}
if interactive >= 0 {
let (contents, path) = match interactive {
1 => {
// basic: open file and watch for fs changes
let temp_file_edit = edit::Builder::new().suffix(".mers").tempfile().unwrap();
let temp_file = temp_file_edit.path();
eprintln!("Using temporary file at {temp_file:?}. Save the file to update the output here.");
if let Ok(_) = std::fs::write(&temp_file, []) {
if let Ok(mut watcher) = {
let temp_file = temp_file.to_path_buf();
// the file watcher
notify::recommended_watcher(move |event: Result<notify::Event, notify::Error>| {
if let Ok(event) = event {
match &event.kind {
notify::EventKind::Modify(notify::event::ModifyKind::Data(_)) => {
if let Ok(file_contents) = fs::read_to_string(&temp_file) {
let mut file = parse::file::File::new(file_contents, temp_file.clone());
static_assertions::const_assert_eq!(parse::parse::PARSE_VERSION, 0);
let mut ginfo = script::block::to_runnable::GInfo::default();
let libs = parse::parse::parse_step_lib_paths(&mut file);
match parse::parse::parse_step_interpret(&mut file) {
Ok(func) => {
let libs = parse::parse::parse_step_libs_load(libs, &mut ginfo);
ginfo.libs = Arc::new(libs);
match parse::parse::parse_step_compile(func, &mut ginfo) {
Ok(func) => {
println!();
println!(" - - - - -");
let output = func.run(vec![]);
println!(" - - - - -");
println!("{}", output);
}
Err(e) => eprintln!("Couldn't compile:\n{e:?}"),
}
}
Err(e) =>eprintln!("Couldn't interpret:\n{e:?}"),
}
} else {
println!("can't read file at {:?}!", temp_file);
std::process::exit(105);
}
}
_ => (),
}
}
})} {
if let Ok(_) = watcher.watch(&temp_file, notify::RecursiveMode::NonRecursive) {
if interactive_use_new_terminal {
if let Ok(term) = std::env::var("TERM") {
let editor = edit::get_editor().unwrap();
eprintln!("launching \"{term} -e {editor:?} {temp_file:?}...");
std::process::Command::new(term)
.arg("-e")
.arg(&editor)
.arg(temp_file)
.spawn()
.unwrap()
.wait()
.unwrap();
}
} else {
edit::edit_file(temp_file_edit.path()).unwrap();
}
temp_file_edit.close().unwrap();
std::process::exit(0);
} else {
println!("Cannot watch the file at \"{:?}\" for hot-reload.", temp_file);
std::process::exit(104);
}
} else {
println!("Cannot use filesystem watcher for hot-reload.");
// TODO: don't exit here?
std::process::exit(103);
}
} else {
println!("could not write file \"{:?}\".", temp_file);
std::process::exit(102);
}
}
_ => (String::new(), String::new()),
};
parse::file::File::new(
contents,
path.into()
)
}
else if execute {
parse::file::File::new(
args.iter().skip(1).fold(String::new(), |mut s, v| {
if !s.is_empty() {
s.push(' ');
}
s.push_str(v);
s
}),
path.into(),
)
} else {
println!("please provide either a file or -e and a script to run!");
std::process::exit(101);
}
} else {
parse::file::File::new(std::fs::read_to_string(&args[0]).unwrap(), path.into())
}
}
})
.unwrap();
println!(" - - - - -");

View File

@@ -33,9 +33,31 @@ impl From<ToRunnableError> for ScriptError {
#[derive(Debug)]
pub enum ParseError {}
pub const PARSE_VERSION: u64 = 0;
/// executes the 4 parse_steps in order: lib_paths => interpret => libs_load => compile
pub fn parse(file: &mut File) -> Result<RScript, ScriptError> {
let mut ginfo = GInfo::default();
let libs = parse_step_lib_paths(file);
let func = parse_step_interpret(file)?;
ginfo.libs = Arc::new(parse_step_libs_load(libs, &mut ginfo));
eprintln!();
#[cfg(debug_assertions)]
eprintln!("Parsed: {func}");
#[cfg(debug_assertions)]
eprintln!("Parsed: {func:#?}");
let run = parse_step_compile(func, &mut ginfo)?;
#[cfg(debug_assertions)]
eprintln!("Runnable: {run:#?}");
Ok(run)
}
pub fn parse_step_lib_paths(file: &mut File) -> Vec<Command> {
let mut libs = vec![];
let mut enum_variants = GInfo::default_enum_variants();
loop {
file.skip_whitespaces();
let pos = file.get_pos().clone();
@@ -49,37 +71,43 @@ pub fn parse(file: &mut File) -> Result<RScript, ScriptError> {
if let Some(parent) = path_to_executable.parent() {
cmd.current_dir(parent.clone());
}
match libs::Lib::launch(cmd, &mut enum_variants) {
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(),
),
}
libs.push(cmd);
} else {
file.set_pos(pos);
break;
}
}
let func = SFunction::new(
libs
}
pub fn parse_step_interpret(file: &mut File) -> Result<SFunction, ParseError> {
Ok(SFunction::new(
vec![(
"args".to_string(),
VSingleType::List(VSingleType::String.into()).into(),
)],
parse_block_advanced(file, Some(false), true, true, false)?,
);
eprintln!();
#[cfg(debug_assertions)]
eprintln!("Parsed: {func}");
#[cfg(debug_assertions)]
eprintln!("Parsed: {func:#?}");
let run = to_runnable::to_runnable(func, GInfo::new(Arc::new(libs), enum_variants))?;
#[cfg(debug_assertions)]
eprintln!("Runnable: {run:#?}");
Ok(run)
))
}
pub fn parse_step_libs_load(lib_cmds: Vec<Command>, ginfo: &mut GInfo) -> Vec<libs::Lib> {
let mut libs = vec![];
for cmd in lib_cmds {
match libs::Lib::launch(cmd, &mut ginfo.enum_variants) {
Ok(lib) => {
libs.push(lib);
}
Err(e) => eprintln!("!! Unable to load library: {e:?} !!",),
}
}
libs
}
pub fn parse_step_compile(
main_func: SFunction,
ginfo: &mut GInfo,
) -> Result<RScript, ToRunnableError> {
to_runnable::to_runnable(main_func, ginfo)
}
fn parse_block(file: &mut File) -> Result<SBlock, ParseError> {
@@ -503,8 +531,17 @@ fn parse_single_type_adv(
// Tuple or Array
Some('[') => {
let mut types = vec![];
let mut list = false;
loop {
file.skip_whitespaces();
if file[file.get_char_index()..].starts_with("...]") {
list = true;
file.next();
file.next();
file.next();
file.next();
break;
}
match file.peek() {
Some(']') => {
file.next();
@@ -521,7 +558,7 @@ fn parse_single_type_adv(
file.next();
}
}
if types.len() == 1 {
if list {
VSingleType::List(types.pop().unwrap())
} else {
VSingleType::Tuple(types)

View File

@@ -8,7 +8,7 @@ use std::{
use crate::libs;
use self::to_runnable::{ToRunnableError, GInfo};
use self::to_runnable::{GInfo, ToRunnableError};
use super::{
builtins::BuiltinFunction,
@@ -94,10 +94,14 @@ pub mod to_runnable {
sync::Arc,
};
use crate::{script::{
val_data::VDataEnum,
val_type::{VSingleType, VType}, builtins,
}, libs};
use crate::{
libs,
script::{
builtins,
val_data::VDataEnum,
val_type::{VSingleType, VType},
},
};
use super::{
BuiltinFunction, RBlock, RFunction, RScript, RStatement, RStatementEnum, SBlock, SFunction,
@@ -150,13 +154,27 @@ pub mod to_runnable {
// Global, shared between all
pub struct GInfo {
vars: usize,
libs: Arc<Vec<libs::Lib>>,
lib_fns: HashMap<String, (usize, usize)>,
enum_variants: HashMap<String, usize>,
pub libs: Arc<Vec<libs::Lib>>,
pub lib_fns: HashMap<String, (usize, usize)>,
pub enum_variants: HashMap<String, usize>,
}
impl Default for GInfo {
fn default() -> Self {
Self {
vars: 0,
libs: Arc::new(vec![]),
lib_fns: HashMap::new(),
enum_variants: Self::default_enum_variants(),
}
}
}
impl GInfo {
pub fn default_enum_variants() -> HashMap<String, usize> {
builtins::EVS.iter().enumerate().map(|(i, v)| (v.to_string(), i)).collect()
builtins::EVS
.iter()
.enumerate()
.map(|(i, v)| (v.to_string(), i))
.collect()
}
pub fn new(libs: Arc<Vec<libs::Lib>>, enum_variants: HashMap<String, usize>) -> Self {
let mut lib_fns = HashMap::new();
@@ -165,7 +183,12 @@ pub mod to_runnable {
lib_fns.insert(name.to_string(), (libid, fnid));
}
}
Self { vars: 0, libs, lib_fns, enum_variants }
Self {
vars: 0,
libs,
lib_fns,
enum_variants,
}
}
}
// Local, used to keep local variables separated
@@ -175,24 +198,27 @@ pub mod to_runnable {
fns: HashMap<String, Arc<RFunction>>,
}
pub fn to_runnable(s: SFunction, mut ginfo: GInfo) -> Result<RScript, ToRunnableError> {
pub fn to_runnable(s: SFunction, ginfo: &mut GInfo) -> Result<RScript, ToRunnableError> {
if s.inputs.len() != 1 || s.inputs[0].0 != "args" {
return Err(ToRunnableError::MainWrongInput);
}
assert_eq!(s.inputs[0].1,VType {
types: vec![VSingleType::List(VType {
types: vec![VSingleType::String],
})],
});
assert_eq!(
s.inputs[0].1,
VType {
types: vec![VSingleType::List(VType {
types: vec![VSingleType::String],
})],
}
);
let func = function(
&s,
&mut ginfo,
ginfo,
LInfo {
vars: HashMap::new(),
fns: HashMap::new(),
},
)?;
Ok(RScript::new(func, ginfo.vars, ginfo.libs)?)
Ok(RScript::new(func, ginfo.vars, ginfo.libs.clone())?)
}
// go over every possible known-type input for the given function, returning all possible RFunctions.
@@ -276,21 +302,24 @@ pub mod to_runnable {
for t in v {
stypes(t, ginfo);
}
},
VSingleType::EnumVariantS(e, v) => *t = VSingleType::EnumVariant({
if let Some(v) = ginfo.enum_variants.get(e) {
*v
} else {
let v = ginfo.enum_variants.len();
ginfo.enum_variants.insert(e.clone(), v);
v
}
},
{
stypes(v, ginfo);
v.clone()
}
),
VSingleType::EnumVariantS(e, v) => {
*t = VSingleType::EnumVariant(
{
if let Some(v) = ginfo.enum_variants.get(e) {
*v
} else {
let v = ginfo.enum_variants.len();
ginfo.enum_variants.insert(e.clone(), v);
v
}
},
{
stypes(v, ginfo);
v.clone()
},
)
}
_ => (),
}
}
@@ -533,7 +562,6 @@ pub mod to_runnable {
} else {
eprintln!("WARN: Match condition with return type {} never returns a match and will be ignored entirely. Note: this also skips type-checking for the action part of this match arm because the success type is not known.", case_condition_out);
}
}
linfo.vars.get_mut(match_on).unwrap().1 = og_type;
@@ -721,7 +749,7 @@ pub enum RStatementEnum {
Switch(RStatement, Vec<(VType, RStatement)>),
Match(usize, Vec<(RStatement, RStatement)>),
IndexFixed(RStatement, usize),
EnumVariant(usize, RStatement)
EnumVariant(usize, RStatement),
}
impl RStatementEnum {
pub fn run(&self, vars: &Vec<Am<VData>>, libs: &Arc<Vec<libs::Lib>>) -> VData {
@@ -758,7 +786,9 @@ impl RStatementEnum {
func.run(vars, libs)
}
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::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) => {
if let VDataEnum::Bool(v) = c.run(vars, libs).data {
@@ -802,7 +832,10 @@ impl RStatementEnum {
}
VDataEnum::String(v) => {
for ch in v.chars() {
if let Some(v) = in_loop(VDataEnum::String(ch.to_string()).to()).data.matches() {
if let Some(v) = in_loop(VDataEnum::String(ch.to_string()).to())
.data
.matches()
{
oval = v;
break;
}
@@ -836,9 +869,7 @@ impl RStatementEnum {
for (case_condition, case_action) in cases {
// [t] => Some(t), t => Some(t), [] | false => None
if let Some(v) = case_condition.run(vars, libs).data.matches() {
let og = {
std::mem::replace(&mut *vars[*match_on].lock().unwrap(), v)
};
let og = { std::mem::replace(&mut *vars[*match_on].lock().unwrap(), v) };
let res = case_action.run(vars, libs);
*vars[*match_on].lock().unwrap() = og;
break 'm res;
@@ -847,9 +878,7 @@ impl RStatementEnum {
VDataEnum::Tuple(vec![]).to()
}
Self::IndexFixed(st, i) => st.run(vars, libs).get(*i).unwrap(),
Self::EnumVariant(e, v) => {
VDataEnum::EnumVariant(*e, Box::new(v.run(vars, libs))).to()
}
Self::EnumVariant(e, v) => VDataEnum::EnumVariant(*e, Box::new(v.run(vars, libs))).to(),
}
}
pub fn out(&self) -> VType {
@@ -887,12 +916,8 @@ impl RStatementEnum {
a.out() | VSingleType::Tuple(vec![]).to()
}
}
Self::While(c) => {
c.out().matches().1
}
Self::For(_, _, b) => {
VSingleType::Tuple(vec![]).to() | b.out().matches().1
}
Self::While(c) => c.out().matches().1,
Self::For(_, _, b) => VSingleType::Tuple(vec![]).to() | b.out().matches().1,
Self::BuiltinFunction(f, args) => f.returns(args.iter().map(|rs| rs.out()).collect()),
Self::Switch(switch_on, cases) => {
let switch_on = switch_on.out().types;
@@ -941,7 +966,11 @@ pub struct RScript {
libs: Arc<Vec<libs::Lib>>,
}
impl RScript {
fn new(main: RFunction, vars: usize, libs: Arc<Vec<libs::Lib>>) -> Result<Self, ToRunnableError> {
fn new(
main: RFunction,
vars: usize,
libs: Arc<Vec<libs::Lib>>,
) -> Result<Self, ToRunnableError> {
if main.inputs.len() != 1 {
return Err(ToRunnableError::MainWrongInput);
}
@@ -1016,7 +1045,7 @@ impl Display for VSingleType {
write!(f, "]")?;
Ok(())
}
Self::List(t) => write!(f, "[{t}]"),
Self::List(t) => write!(f, "[{t} ...]"),
Self::Function(_) => write!(f, "FUNCTION"),
Self::Thread(_) => write!(f, "THREAD"),
Self::Reference(r) => write!(f, "&{r}"),

View File

@@ -354,7 +354,16 @@ impl BuiltinFunction {
}
}
// TODO! finish this
_ => true,
Self::Pop | Self::Remove | Self::Get | Self::Len | Self::Substring => true,
Self::Contains | Self::StartsWith | Self::EndsWith | Self::Regex => {
input.len() == 2
&& input
.iter()
.all(|v| v.fits_in(&VSingleType::String.to()).is_empty())
}
Self::Trim => {
input.len() == 1 && input[0].fits_in(&VSingleType::String.to()).is_empty()
}
}
}
/// for invalid inputs, may panic