aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--Cargo.lock250
-rw-r--r--Cargo.toml1
-rw-r--r--src/main.rs131
4 files changed, 336 insertions, 47 deletions
diff --git a/.gitignore b/.gitignore
index ea8c4bf..74cd5c7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
/target
+repl_history.txt
diff --git a/Cargo.lock b/Cargo.lock
index 621fef7..32b6cd5 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -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"
diff --git a/Cargo.toml b/Cargo.toml
index 3a40982..650b30b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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()),
}