diff --git a/Cargo.lock b/Cargo.lock index a8b6eec866..cda7338648 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -71,6 +71,18 @@ dependencies = [ "version_check", ] +[[package]] +name = "ahash" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" +dependencies = [ + "cfg-if 1.0.0", + "const-random", + "once_cell", + "version_check", +] + [[package]] name = "aho-corasick" version = "0.7.19" @@ -131,7 +143,7 @@ name = "app_io" version = "0.1.0" dependencies = [ "core2", - "hashbrown", + "hashbrown 0.11.2", "lazy_static", "logger_x86_64", "mutex_sleep", @@ -288,7 +300,7 @@ dependencies = [ name = "block_cache" version = "0.1.0" dependencies = [ - "hashbrown", + "hashbrown 0.11.2", "lazy_static", "log", "storage_device", @@ -485,6 +497,28 @@ dependencies = [ "tty", ] +[[package]] +name = "const-random" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368a7a772ead6ce7e1de82bfb04c485f3db8ec744f72925af5735e29a22cc18e" +dependencies = [ + "const-random-macro", + "proc-macro-hack", +] + +[[package]] +name = "const-random-macro" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d7d6ab3c3a2282db210df5f02c4dab6e0a7057af0fb7ebd4070f30fe05c0ddb" +dependencies = [ + "getrandom", + "once_cell", + "proc-macro-hack", + "tiny-keccak", +] + [[package]] name = "const_format" version = "0.2.22" @@ -544,6 +578,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" +[[package]] +name = "core-error" +version = "0.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efcdb2972eb64230b4c50646d8498ff73f5128d196a90c7236eec4cbe8619b8f" +dependencies = [ + "version_check", +] + [[package]] name = "core2" version = "0.4.0" @@ -628,7 +671,7 @@ dependencies = [ "crate_metadata_serde", "fs_node", "goblin", - "hashbrown", + "hashbrown 0.11.2", "log", "memory", "qp-trie", @@ -642,7 +685,7 @@ dependencies = [ name = "crate_metadata_serde" version = "0.1.0" dependencies = [ - "hashbrown", + "hashbrown 0.11.2", "serde", ] @@ -661,7 +704,7 @@ version = "0.1.0" dependencies = [ "by_address", "fs_node", - "hashbrown", + "hashbrown 0.11.2", "hpet", "lazy_static", "log", @@ -702,6 +745,12 @@ dependencies = [ "cfg-if 1.0.0", ] +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + [[package]] name = "crypto-common" version = "0.1.6" @@ -745,7 +794,7 @@ dependencies = [ "fs_node", "gimli", "goblin", - "hashbrown", + "hashbrown 0.11.2", "log", "memory", "mod_mgmt", @@ -997,7 +1046,7 @@ name = "environment" version = "0.1.0" dependencies = [ "fs_node", - "hashbrown", + "hashbrown 0.11.2", "path", "root", ] @@ -1181,7 +1230,7 @@ version = "0.1.0" dependencies = [ "compositor", "framebuffer", - "hashbrown", + "hashbrown 0.11.2", "shapes", "spin 0.9.4", ] @@ -1373,10 +1422,19 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" dependencies = [ - "ahash", + "ahash 0.7.6", "serde", ] +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash 0.8.3", +] + [[package]] name = "heap" version = "0.1.0" @@ -1397,7 +1455,7 @@ dependencies = [ "app_io", "cpu", "getopts", - "hashbrown", + "hashbrown 0.11.2", "heap", "hpet", "libtest", @@ -1481,7 +1539,7 @@ dependencies = [ "app_io", "core2", "embedded-hal", - "hashbrown", + "hashbrown 0.11.2", "mod_mgmt", "nb 1.0.0", "noline", @@ -1507,10 +1565,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" dependencies = [ "autocfg", - "hashbrown", + "hashbrown 0.11.2", "serde", ] +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if 1.0.0", +] + [[package]] name = "intel_ethernet" version = "0.1.0" @@ -1618,7 +1685,7 @@ version = "0.1.0" dependencies = [ "acpi", "bit_field 0.7.0", - "hashbrown", + "hashbrown 0.11.2", "hpet", "intel_ethernet", "interrupts", @@ -1723,9 +1790,9 @@ source = "git+https://github.com/theseus-os/libc?branch=theseus#5e1da08f39d9b25c [[package]] name = "libm" -version = "0.2.1" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7d73b3f436185384286bd8098d17ec07c9a7d2388a6599f824d8502b529702a" +checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb" [[package]] name = "libterm" @@ -1756,7 +1823,7 @@ dependencies = [ "apic", "bit_field 0.10.1", "cpu", - "hashbrown", + "hashbrown 0.11.2", "hpet", "libm", "log", @@ -2092,7 +2159,7 @@ dependencies = [ "cstr_core", "early_tls", "fs_node", - "hashbrown", + "hashbrown 0.11.2", "kernel_config", "log", "lz4_flex", @@ -2205,7 +2272,7 @@ version = "0.1.0" dependencies = [ "apic", "cfg-if 0.1.10", - "hashbrown", + "hashbrown 0.11.2", "heap", "intrusive-collections", "irq_safety", @@ -2356,6 +2423,12 @@ dependencies = [ "nic_buffers", ] +[[package]] +name = "no-std-compat" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b93853da6d84c2e3c7d730d6473e8817692dd89be387eb01b94d7f108ecb5b8c" + [[package]] name = "no_drop" version = "0.1.0" @@ -2406,11 +2479,11 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +version = "0.2.15" +source = "git+https://github.com/rust-num/num-traits#b5906eeeab1fffd1458285c036e099be01d8cd14" dependencies = [ "autocfg", + "libm", ] [[package]] @@ -2440,16 +2513,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e42c982f2d955fac81dd7e1d0e1426a7d702acd9c98d19ab01083a6a0328c424" dependencies = [ "crc32fast", - "hashbrown", + "hashbrown 0.11.2", "indexmap", "memchr", ] [[package]] name = "once_cell" -version = "1.9.0" +version = "1.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" [[package]] name = "ota_update_client" @@ -2621,7 +2694,7 @@ dependencies = [ "app_io", "byteorder", "getopts", - "hashbrown", + "hashbrown 0.11.2", "hpet", "log", "network_manager", @@ -2767,6 +2840,12 @@ dependencies = [ "version_check", ] +[[package]] +name = "proc-macro-hack" +version = "0.5.20+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" + [[package]] name = "proc-macro2" version = "1.0.40" @@ -2961,6 +3040,34 @@ dependencies = [ "wait_queue", ] +[[package]] +name = "rhai" +version = "1.14.0" +source = "git+https://github.com/rhaiscript/rhai#b78cb6131bdf6b6c55e8a03e3d12dcdd8d34d9ef" +dependencies = [ + "ahash 0.8.3", + "bitflags", + "core-error", + "hashbrown 0.13.2", + "instant", + "libm", + "no-std-compat", + "num-traits", + "rhai_codegen", + "smallvec", + "smartstring", +] + +[[package]] +name = "rhai_codegen" +version = "1.5.0" +source = "git+https://github.com/rhaiscript/rhai#b78cb6131bdf6b6c55e8a03e3d12dcdd8d34d9ef" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "riscv" version = "0.7.0" @@ -3074,6 +3181,19 @@ dependencies = [ "x86_64", ] +[[package]] +name = "run_rhai" +version = "0.1.0" +dependencies = [ + "app_io", + "getopts", + "log", + "path", + "rhai", + "spin 0.9.4", + "task", +] + [[package]] name = "runqueue" version = "0.1.0" @@ -3434,6 +3554,23 @@ dependencies = [ "time", ] +[[package]] +name = "smallvec" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" + +[[package]] +name = "smartstring" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fb72c633efbaa2dd666986505016c32c3044395ceaf881518399d2f4127ee29" +dependencies = [ + "autocfg", + "static_assertions", + "version_check", +] + [[package]] name = "smoltcp" version = "0.5.0" @@ -3989,6 +4126,7 @@ dependencies = [ "rq", "rq_access_eval", "rq_eval", + "run_rhai", "scheduler_eval", "seconds_counter", "shell", @@ -4067,6 +4205,15 @@ dependencies = [ "log", ] +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + [[package]] name = "tlb_shootdown" version = "0.1.0" @@ -4384,7 +4531,7 @@ dependencies = [ "app_io", "core2", "fs_node", - "hashbrown", + "hashbrown 0.11.2", "memfs", "path", "root", @@ -4434,7 +4581,7 @@ name = "wasmparser" version = "0.81.0" source = "git+https://github.com/theseus-os/wasm-tools?branch=no-std-wasmparser#7b0eb0d074606c8a49027e60e452862f5fe183b4" dependencies = [ - "hashbrown", + "hashbrown 0.11.2", ] [[package]] @@ -4448,7 +4595,7 @@ dependencies = [ "cfg-if 1.0.0", "core2", "cpp_demangle", - "hashbrown", + "hashbrown 0.11.2", "indexmap", "lazy_static", "libc", @@ -4478,7 +4625,7 @@ dependencies = [ "core2", "cranelift-entity", "gimli", - "hashbrown", + "hashbrown 0.11.2", "indexmap", "log", "more-asserts", @@ -4525,7 +4672,7 @@ dependencies = [ "cc", "cfg-if 1.0.0", "core2", - "hashbrown", + "hashbrown 0.11.2", "indexmap", "lazy_static", "libc", diff --git a/Cargo.toml b/Cargo.toml index 54713858b7..0dad37e609 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -79,6 +79,7 @@ exclude = [ ## Exclude application crates used for testing specific Theseus functionality. ## TODO: move these to a specific "tests" folder so we can exclude that entire folder. + "applications/test_async", "applications/test_backtrace", "applications/test_block_io", "applications/test_channel", @@ -90,22 +91,29 @@ exclude = [ "applications/test_panic", "applications/test_realtime", "applications/test_restartable", + "applications/test_scheduler", "applications/test_serial_echo", "applications/test_std_fs", + "applications/test_task_cancel", "applications/test_wait_queue", "applications/test_wasmtime", "applications/tls_test", "applications/unwind_test", + + ## Exclude application crates used for one specific feature. + "applications/run_rhai", ] [patch.crates-io] ### use our own version of volatile which supports zerocopy volatile = { git = "https://github.com/theseus-os/volatile" } -### use our own no_std-compatilbe getopts +### use our own no_std-compatible getopts getopts = { git = "https://github.com/theseus-os/getopts" } ### use the latest version of smoltcp from github; the one on crates.io is out of date smoltcp = { git = "https://github.com/m-labs/smoltcp" } +### num-traits 0.2.15 doesn't support u128/i128 by default, but the latest github version does. +num-traits = { git = "https://github.com/rust-num/num-traits" } ### Patch `libc` so we can use libc-specific types when using `cfg(target_os = "theseus")`. libc = { git = "https://github.com/theseus-os/libc", branch = "theseus" } diff --git a/applications/run_rhai/Cargo.toml b/applications/run_rhai/Cargo.toml new file mode 100644 index 0000000000..df91ef85f6 --- /dev/null +++ b/applications/run_rhai/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "run_rhai" +version = "0.1.0" +authors = ["Kevin Boos "] +edition = "2021" + +[dependencies] +getopts = "0.2.21" +log = "0.4.8" +rhai = { git = "https://github.com/rhaiscript/rhai", features = [ "no_std" ], default_features = false } +spin = "0.9.4" + +app_io = { path = "../../kernel/app_io" } +path = { path = "../../kernel/path" } +task = { path = "../../kernel/task" } \ No newline at end of file diff --git a/applications/run_rhai/src/lib.rs b/applications/run_rhai/src/lib.rs new file mode 100644 index 0000000000..39954531eb --- /dev/null +++ b/applications/run_rhai/src/lib.rs @@ -0,0 +1,156 @@ +//! A frontend for running Rhai scripts or an interactive Rhai REPL shell. + +#![no_std] + +extern crate alloc; + +use alloc::{string::{String, ToString}, vec::Vec, format}; +use app_io::println; +use getopts::{Matches, Options}; +use path::Path; +use rhai::{ + packages::{Package, CorePackage, BasicStringPackage}, + Engine, +}; +use spin::Once; + +fn print_usage(opts: Options) { + println!("{}", opts.usage(USAGE)); +} + +const USAGE: &str = "Usage: run_rhai [SCRIPT...] +Runs Rhai as an interactive REPL shell session, if no SCRIPTs are provided. +If SCRIPT paths are provided, each SCRIPT will be run sequentially."; + + +static QUIET: Once = Once::new(); +macro_rules! quiet { + () => (QUIET.get() == Some(&true)); +} + +static KEEP_GOING: Once = Once::new(); +macro_rules! keep_going { + () => (KEEP_GOING.get() == Some(&true)); +} + +pub fn main(args: Vec) -> isize { + let mut opts = Options::new(); + opts.optflag("h", "help", "print this help menu"); + opts.optflag("q", "quiet", "silence output to stdio"); + opts.optflag("", "keep-going", "continue executing SCRIPTs even if an error occurs."); + // opts.optflag("v", "verbose", "enable verbose output"); + + + let matches = match opts.parse(&args) { + Ok(m) => m, + Err(_f) => { + println!("{}", _f); + print_usage(opts); + return -1; + } + }; + + if matches.opt_present("h") { + print_usage(opts); + return 0; + } + + QUIET.call_once(|| matches.opt_present("q")); + KEEP_GOING.call_once(|| matches.opt_present("keep-going")); + + match rmain(matches) { + Ok(_) => 0, + Err(e) => { + println!("Error:\n{}", e); + -1 + } + } +} + + +fn rmain(matches: Matches) -> Result<(), String> { + // This is a raw engine with no loaded packages, + // so it can't really do much besides basic math. + let mut engine = Engine::new_raw(); + CorePackage::new().register_into_engine(&mut engine); + BasicStringPackage::new().register_into_engine(&mut engine); + + if matches.free.is_empty() { + run_interactive(engine) + } else { + run_scripts(engine, &matches.free) + } +} + + +fn run_interactive(_engine: Engine) -> Result<(), String> { + Err("Rhai interactive scripting isn't yet complete".to_string()) + + /* + println!("Starting interactive Rhai session:\n>>> "); + + let stdin = app_io::stdin().map_err(ToString::to_string)?; + let stdout = app_io::stdout().map_err(ToString::to_string)?; + let mut buf = [0u8; 256]; + let mut + loop { + let cnt = stdin.read(&mut buf).map_err(|e| + format!("Failed to read stdin: {:?}", e) + )?; + if cnt == 0 { break; } + stdout.write_all(&buf[0..cnt]).map_err(|e| + format!("Failed to write to stdout: {:?}", e) + )?; + + } + println!("Rhai returned {:?}", result); + */ +} + +fn run_scripts(engine: Engine, paths: &Vec) -> Result<(), String> { + let Ok(cwd) = task::with_current_task(|t| t.get_env().lock().working_dir.clone()) else { + return Err("failed to get current task".to_string()); + }; + + for path in paths { + let path = Path::new(path.to_string()); + let Some(file) = path.get_file(&cwd) else { + let err_msg = format!("Error: couldn't open file at '{}'", path); + if !quiet!() { println!("{}", err_msg); } + if keep_going!() { continue; } else { return Err(err_msg); } + }; + let mut file_locked = file.lock(); + let file_size = file_locked.len(); + let mut string_slice_as_bytes = alloc::vec![0; file_size]; + + let _num_bytes_read = match file_locked.read_at(&mut string_slice_as_bytes,0) { + Ok(num) => num, + Err(e) => { + let err_msg = format!("Failed to read '{}', error {:?}", path, e); + if !quiet!() { println!("{}", err_msg); } + if keep_going!() { continue; } else { return Err(err_msg); } + } + }; + let script_string = match core::str::from_utf8(&string_slice_as_bytes) { + Ok(string_slice) => string_slice, + Err(utf8_err) => { + let err_msg = format!("File {} was not a valid UTF-8 text file: {}", path, utf8_err); + if !quiet!() { println!("{}", err_msg); } + if keep_going!() { continue; } else { return Err(err_msg); } + } + }; + let rhai_result = engine.run(&script_string); + match rhai_result { + Ok(_) => { + if !quiet!() { println!("Successfully ran script at '{}'", path); } + } + Err(e) => { + let err_msg = format!("Error running script at '{}': {:?}", path, e); + if !quiet!() { println!("{}", err_msg); } + if keep_going!() { continue; } else { return Err(err_msg); } + } + } + } + + Ok(()) +} diff --git a/theseus_features/Cargo.toml b/theseus_features/Cargo.toml index 21c2215dfe..b56a1f8cbb 100644 --- a/theseus_features/Cargo.toml +++ b/theseus_features/Cargo.toml @@ -35,6 +35,8 @@ swap = { path = "../applications/swap", optional = true } upd = { path = "../applications/upd", optional = true } wasm = { path = "../applications/wasm", optional = true } +## Applications not included by default. +run_rhai = { path = "../applications/run_rhai", optional = true } ## Kernel crates used for only testing purposes. libtest = { path = "../kernel/libtest", optional = true } @@ -101,6 +103,11 @@ everything = [ "wasmtime", ] +## Includes `rhai`, a scripting environment and interpreter. +## Currently this is not included in any featureset by default, +## because rhai is very slow to build. +rhai = [ "run_rhai" ] + ## Includes `wasmtime`, the WebAssembly (WASM) runtime, in the build. wasmtime = [ "test_wasmtime" ]