From bfc8d86b54b904bb2aa5aa5fed9c0a7aa2586ce6 Mon Sep 17 00:00:00 2001 From: Goren Barak Date: Sun, 31 Dec 2023 12:42:17 -0500 Subject: [PATCH] Added BEGIN...UNTIL and BEGIN...WHILE..AGAIN loops --- src/backend.rs | 80 ++++++++++++++++++++++++++++++++++++++++++++------ src/main.rs | 5 ++-- src/parse.rs | 3 ++ until.fs | 4 +++ until.fs~ | 1 + 5 files changed, 81 insertions(+), 12 deletions(-) create mode 100644 until.fs create mode 100644 until.fs~ diff --git a/src/backend.rs b/src/backend.rs index b11612c..d6a6ea0 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -15,6 +15,8 @@ struct Dictionary { words: HashMap } +// fn paren_matching(source: &str, left: impl Fn(&str) -> bool, right: impl Fn(&str) -> bool) {} + impl<'a> Vm { pub fn new() -> Self { Self { @@ -155,11 +157,11 @@ impl<'a> Vm { "IF"|"if" => { let expr = unwrap!(); let mut content = String::new(); - let mut next = parser.inner_next(); + let mut next = parser.inner_next_back(); while !matches!(next, Some("THEN")|Some("then")|None) { content.push_str(next.unwrap()); content.push_str(" "); - next = parser.inner_next(); + next = parser.inner_next_back(); } if expr == 0 { @@ -168,45 +170,105 @@ impl<'a> Vm { self.vmrun(&mut Parser::new(content.as_str())); } }, + + "THEN"|"then" => {} "(" => { - let mut next = parser.inner_next(); + let mut next = parser.inner_next_back(); while next != Some(")") && next != None { - next = parser.inner_next(); + next = parser.inner_next_back(); } }, + "stacklen" => { + self.stack.push(self.stack.len() as u64); + } "DO"|"do" => { let start = unwrap!(); let limit = unwrap!(); let mut action = String::new(); - let mut next = parser.inner_next(); + let mut next = parser.inner_next_back(); while !matches!(next, Some("LOOP")|Some("loop")|None) { action.push_str(next.unwrap()); action.push_str(" "); - next = parser.inner_next(); + next = parser.inner_next_back(); } for i in start..limit { self.dictionary.words.insert("I".to_string(), i.to_string()); + self.dictionary.words.insert("i".to_string(), i.to_string()); self.vmrun(&mut Parser::new(action.as_str())); } self.dictionary.words.remove("I"); + self.dictionary.words.remove("i"); }, + "+!" => { + let addr = unwrap!(); + let amnt = unwrap!(); + self.dictionary.data.insert(addr, self.dictionary.data.get(&addr).unwrap_or(&0) + amnt); + }, + "LOOP"|"loop" => {}, + "BEGIN"|"begin" => { + let mut action = String::new(); + + let mut next = parser.inner_next_back(); + while !matches!(next, Some("UNTIL")|Some("until")|Some("WHILE")|Some("while")|None) { + action.push_str(next.unwrap()); + action.push_str(" "); + next = parser.inner_next_back(); + } + + match next { + Some("UNTIL")|Some("until") => { + self.vmrun(&mut Parser::new(action.as_str())); + + while unwrap!() == 0 { + self.vmrun(&mut Parser::new(action.as_str())); + } + }, + Some("WHILE")|Some("while") => { + let mut condition = String::new(); + let mut next = parser.inner_next_back(); + while !matches!(next, Some("REPEAT")|Some("repeat")|None) { + condition.push_str(next.unwrap()); + condition.push_str(" "); + next = parser.inner_next_back(); + } + self.vmrun(&mut Parser::new(condition.as_str())); + let mut cond_bool = unwrap!(); + while cond_bool != 0 { + self.vmrun(&mut Parser::new(action.as_str())); + self.vmrun(&mut Parser::new(condition.as_str())); + cond_bool = unwrap!(); + } + }, + _ => { + println!("ERROR: BEGIN without UNTIL or WHILE"); + std::process::exit(1); + } + } + }, + "UNTIL"|"until" => {}, + "WHILE"|"while" => {}, + "REPEAT"|"repeat" => {}, ":" => { let mut word_content = String::new(); let Some(Word(word_name)) = parser.next() else { println!("ERROR: Word name not given."); std::process::exit(1); }; - let mut next = parser.inner_next(); + let mut next = parser.inner_next_back(); while next != Some(";") && next != None { word_content.push_str(next.unwrap()); word_content.push_str(" "); - next = parser.inner_next(); + next = parser.inner_next_back(); } self.dictionary.words.insert(word_name.to_string(), word_content); }, + ";" => {}, "BYE"|"bye" => { std::process::exit(0); - } + }, + "clearstack" => { + self.stack = Vec::new(); + }, 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 8b3f0fc..f384a3b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,15 +8,14 @@ use backend::Vm; fn repl() { println!("Fourth REPL:"); println!("To exit, use the `bye` command"); - let mut code = String::new(); + let mut vm = Vm::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())); + vm.vmrun(&mut Parser::new(format!("{} trace stack\n", line).as_str())); } else { println!("Bye bye and have a good day!"); std::io::stdout().flush().unwrap(); diff --git a/src/parse.rs b/src/parse.rs index d735c61..363d09d 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -34,4 +34,7 @@ impl<'a> Parser<'a> { pub fn inner_next(&mut self) -> Option<&'a str> { self.split_whitespace.next() } + pub fn inner_next_back(&mut self) -> Option<&'a str> { + self.split_whitespace.next() + } } diff --git a/until.fs b/until.fs new file mode 100644 index 0000000..b3ca488 --- /dev/null +++ b/until.fs @@ -0,0 +1,4 @@ +variable loopy + +BEGIN 12 1 loopy +! WHILE 10 loopy @ <> REPEAT +trace stack diff --git a/until.fs~ b/until.fs~ new file mode 100644 index 0000000..126326b --- /dev/null +++ b/until.fs~ @@ -0,0 +1 @@ +BEGIN 12 1 UNTIL