From 2a73930576e7dfd84a5c20e2cc494a3ed96f45a2 Mon Sep 17 00:00:00 2001 From: Goren Barak Date: Sat, 30 Dec 2023 19:28:11 -0500 Subject: [PATCH] Added REPL. --- src/backend.rs | 29 ++++++++++++++++++++++++++++- src/main.rs | 25 ++++++++++++++++++++++--- 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/src/backend.rs b/src/backend.rs index b8150a9..b11612c 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -156,7 +156,7 @@ impl<'a> Vm { let expr = unwrap!(); let mut content = String::new(); let mut next = parser.inner_next(); - while next != Some("THEN") && next != None { + while !matches!(next, Some("THEN")|Some("then")|None) { content.push_str(next.unwrap()); content.push_str(" "); next = parser.inner_next(); @@ -168,6 +168,30 @@ impl<'a> Vm { self.vmrun(&mut Parser::new(content.as_str())); } }, + "(" => { + let mut next = parser.inner_next(); + while next != Some(")") && next != None { + next = parser.inner_next(); + } + }, + "DO"|"do" => { + let start = unwrap!(); + let limit = unwrap!(); + let mut action = String::new(); + + let mut next = parser.inner_next(); + while !matches!(next, Some("LOOP")|Some("loop")|None) { + action.push_str(next.unwrap()); + action.push_str(" "); + next = parser.inner_next(); + } + + for i in start..limit { + self.dictionary.words.insert("I".to_string(), i.to_string()); + self.vmrun(&mut Parser::new(action.as_str())); + } + self.dictionary.words.remove("I"); + }, ":" => { let mut word_content = String::new(); let Some(Word(word_name)) = parser.next() else { println!("ERROR: Word name not given."); std::process::exit(1); }; @@ -180,6 +204,9 @@ impl<'a> Vm { self.dictionary.words.insert(word_name.to_string(), word_content); }, + "BYE"|"bye" => { + std::process::exit(0); + } word => { let words = self.dictionary.words.clone(); let Some(word_content) = words.get(word) else { diff --git a/src/main.rs b/src/main.rs index 3a4ec95..8b3f0fc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,19 +1,38 @@ +use std::io::Write; use std::fs::read_to_string; pub mod parse; pub mod backend; use parse::Parser; use backend::Vm; +fn repl() { + println!("Fourth REPL:"); + println!("To exit, use the `bye` command"); + let mut code = String::new(); + loop { + print!("> "); + std::io::stdout().flush().unwrap(); + let mut line = String::new(); + let _ = std::io::stdin().read_line(&mut line); + code.push_str(line.as_str()); + if !matches!(line.as_str(), "bye"|"BYE") { + Vm::new().vmrun(&mut Parser::new(format!("{} trace stack\n", code).as_str())); + } else { + println!("Bye bye and have a good day!"); + std::io::stdout().flush().unwrap(); + std::process::exit(1); + } + } +} fn main() -> std::io::Result<()> { let mut args = std::env::args(); - let command = args.next().unwrap(); + let _command = args.next().unwrap(); if let Some(filename) = args.next() { let contents = read_to_string(filename)?; let contents = contents.as_str(); Vm::new().vmrun(&mut Parser::new(contents)); } else { - eprintln!("Usage: {} filename", command); - std::process::exit(1); + repl(); } Ok(()) }