diff options
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | Cargo.lock | 250 | ||||
| -rw-r--r-- | Cargo.toml | 1 | ||||
| -rw-r--r-- | src/main.rs | 131 |
4 files changed, 336 insertions, 47 deletions
@@ -1 +1,2 @@ /target +repl_history.txt @@ -3,10 +3,16 @@ version = 3 [[package]] +name = "autocfg" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" + +[[package]] name = "bitflags" -version = "1.3.2" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" [[package]] name = "block-buffer" @@ -42,12 +48,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] +name = "cc" +version = "1.0.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" + +[[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] +name = "clipboard-win" +version = "4.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3db8340083d28acb43451166543b98c838299b7e0863621be53a338adceea0ed" +dependencies = [ + "error-code", + "str-buf", + "winapi", +] + +[[package]] name = "digest" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -57,12 +80,60 @@ dependencies = [ ] [[package]] +name = "dirs-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "endian-type" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" + +[[package]] +name = "error-code" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5115567ac25674e0043e472be13d14e537f37ea8aa4bdc4aef0c89add1db1ff" +dependencies = [ + "libc", + "str-buf", +] + +[[package]] name = "fake-simd" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" [[package]] +name = "fd-lock" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfc110fe50727d46a428eed832df40affe9bf74d077cac1bf3f2718e823f14c5" +dependencies = [ + "cfg-if", + "libc", + "windows-sys", +] + +[[package]] name = "generic-array" version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -72,6 +143,17 @@ dependencies = [ ] [[package]] +name = "getrandom" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] name = "instant" version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -102,12 +184,58 @@ dependencies = [ ] [[package]] +name = "log" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +dependencies = [ + "cfg-if", +] + +[[package]] name = "maplit" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" [[package]] +name = "memchr" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" + +[[package]] +name = "memoffset" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9" +dependencies = [ + "autocfg", +] + +[[package]] +name = "nibble_vec" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a5d83df9f36fe23f0c3648c6bbb8b0298bb5f1939c8f2704431371f4b84d43" +dependencies = [ + "smallvec", +] + +[[package]] +name = "nix" +version = "0.22.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3bb9a13fa32bc5aeb64150cd3f32d6cf4c748f8f8a417cce5d2eb976a8370ba" +dependencies = [ + "bitflags", + "cc", + "cfg-if", + "libc", + "memoffset", +] + +[[package]] name = "opaque-debug" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -200,6 +328,16 @@ dependencies = [ ] [[package]] +name = "radix_trie" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c069c179fcdc6a2fe24d8d18305cf085fdbd4f922c041943e203685d6a1c58fd" +dependencies = [ + "endian-type", + "nibble_vec", +] + +[[package]] name = "redox_syscall" version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -209,6 +347,40 @@ dependencies = [ ] [[package]] +name = "redox_users" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" +dependencies = [ + "getrandom", + "redox_syscall", +] + +[[package]] +name = "rustyline" +version = "9.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "790487c3881a63489ae77126f57048b42d62d3b2bafbf37453ea19eedb6340d6" +dependencies = [ + "bitflags", + "cfg-if", + "clipboard-win", + "dirs-next", + "fd-lock", + "libc", + "log", + "memchr", + "nix", + "radix_trie", + "scopeguard", + "smallvec", + "unicode-segmentation", + "unicode-width", + "utf8parse", + "winapi", +] + +[[package]] name = "scopeguard" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -255,6 +427,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" [[package]] +name = "str-buf" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d44a3643b4ff9caf57abcee9c2c621d6c03d9135e0d8b589bd9afb5992cb176a" + +[[package]] name = "syn" version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -271,6 +449,7 @@ version = "0.1.0" dependencies = [ "pest", "pest_derive", + "rustyline", "serial_test", ] @@ -287,12 +466,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" [[package]] +name = "unicode-segmentation" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" + +[[package]] +name = "unicode-width" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" + +[[package]] name = "unicode-xid" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" [[package]] +name = "utf8parse" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "936e4b492acfd135421d8dca4b1aa80a7bfc26e702ef3af710e0752684df5372" + +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" + +[[package]] name = "winapi" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -313,3 +516,46 @@ 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.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82ca39602d5cbfa692c4b67e3bcbb2751477355141c1ed434c94da4186836ff6" +dependencies = [ + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_msvc" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52695a41e536859d5308cc613b4a022261a274390b25bd29dfff4bf08505f3c2" + +[[package]] +name = "windows_i686_gnu" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f54725ac23affef038fecb177de6c9bf065787c2f432f79e3c373da92f3e1d8a" + +[[package]] +name = "windows_i686_msvc" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d5158a43cc43623c0729d1ad6647e62fa384a3d135fd15108d37c683461f64" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc31f409f565611535130cfe7ee8e6655d3fa99c1c61013981e491921b5ce954" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f2b8c7cbd3bfdddd9ab98769f9746a7fad1bca236554cd032b78d768bc0e89f" @@ -11,6 +11,7 @@ debug = [] [dependencies] pest = "2.0" pest_derive = "2.0" +rustyline = "9.0.0" [dev-dependencies] serial_test = "0.5.1" diff --git a/src/main.rs b/src/main.rs index 85c7435..d27f1d5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -21,6 +21,8 @@ macro_rules! extract_enum_value { }; } +const REPL_HISTORY_FILENAME: &str = "repl_history.txt"; + fn main() -> Result<(), String> { use ast::Program; use pest::Parser; @@ -56,62 +58,101 @@ fn main() -> Result<(), String> { } "repl" => { use runtime::*; + use rustyline::error::ReadlineError; + use rustyline::Editor; use std::collections::HashMap; - use std::io::{stdin, stdout, Write}; use std::rc::Rc; println!("Tunk REPL"); - println!("\"#exit\" to exit"); - println!("\"#symbols\" to display symbol table\n"); + println!("\nCommands:"); + println!("#exit exit REPL"); + println!("#symbols display symbol table\n"); + + let mut rl = Editor::<()>::new(); + if rl.load_history(REPL_HISTORY_FILENAME).is_err() { + println!( + "[repl] no history file found, will store REPL history in {}", + REPL_HISTORY_FILENAME + ); + } let mut symbol_table: HashMap<String, Rc<Term>> = HashMap::new(); - let mut s = String::new(); - let mut appending_input = false; + let mut line: String = "".to_owned(); + let mut is_appending = false; loop { - if appending_input { - s.push('\n'); - print!("| "); + let readline = if is_appending { + line.push('\n'); + rl.readline("| ") } else { - s.clear(); - print!("> "); - } - let _ = stdout().flush(); - let read_line_result = stdin().read_line(&mut s); - if read_line_result.is_err() { - println!("{}\n", read_line_result.unwrap_err()); - continue; - } - s = s.trim().to_owned(); - if s.starts_with("#exit") { - return Ok(()); - } else if s.starts_with("#symbols") { - if symbol_table.is_empty() { - println!("[repl] symbol table is empty"); + line.clear(); + rl.readline("> ") + }; + + match readline { + Ok(raw_line) => { + line.push_str(raw_line.trim()); + + if line.starts_with("#exit") { + rl.add_history_entry(line.as_str()); + rl.save_history(REPL_HISTORY_FILENAME).unwrap(); + break; + } else if line.starts_with("#symbols") { + if symbol_table.is_empty() { + println!("[repl] symbol table is empty"); + } + for (symbol, expr) in &symbol_table { + println!("{}:\n{}\n", symbol, *expr); + } + + rl.add_history_entry(line.as_str()); + rl.save_history(REPL_HISTORY_FILENAME).unwrap(); + continue; + } else if !line.ends_with(';') && !line.is_empty() && !line.starts_with('#') + { + is_appending = true; + continue; + } else { + is_appending = false; + } + + rl.add_history_entry(line.as_str()); + // Regular execution + let parse_tree_result = + lparser::LParser::parse(lparser::Rule::program, &line); + if let Err(err) = parse_tree_result { + println!("{}\n", err); + + rl.save_history(REPL_HISTORY_FILENAME).unwrap(); + continue; + } + + let mut parse_tree = parse_tree_result.unwrap(); + let syntax_tree: Program = ast::from_parse_tree(&mut parse_tree); + + let process_result = + runtime::process(&syntax_tree, Some(&mut symbol_table)); + if let Err(err) = process_result { + println!("{}\n", err); + } + + rl.save_history(REPL_HISTORY_FILENAME).unwrap(); } - for (symbol, expr) in &symbol_table { - println!("{}:\n{}\n", symbol, *expr); + Err(ReadlineError::Interrupted) => { + println!("CTRL-C"); + break; } - continue; - } else if !s.ends_with(';') && !s.is_empty() && !s.starts_with('#') { - appending_input = true; - continue; - } else { - appending_input = false; - } - - let parse_tree_result = lparser::LParser::parse(lparser::Rule::program, &s); - if parse_tree_result.is_err() { - println!("{}\n", parse_tree_result.unwrap_err()); - continue; - } - let mut parse_tree = parse_tree_result.unwrap(); - let syntax_tree: Program = ast::from_parse_tree(&mut parse_tree); - let process_result = runtime::process(&syntax_tree, Some(&mut symbol_table)); - if process_result.is_err() { - println!("{}\n", process_result.unwrap_err()); - continue; - } + Err(ReadlineError::Eof) => { + println!("CTRL-D"); + break; + } + Err(err) => { + println!("{:?}", err); + break; + } + }; } + + Ok(()) } _ => Err("invalid subcommand".to_owned()), } |
