Added BEGIN...UNTIL and BEGIN...WHILE..AGAIN loops

This commit is contained in:
Goren Barak 2023-12-31 12:42:17 -05:00
parent 2a73930576
commit bfc8d86b54
5 changed files with 81 additions and 12 deletions

View file

@ -15,6 +15,8 @@ struct Dictionary {
words: HashMap<String, String> words: HashMap<String, String>
} }
// fn paren_matching(source: &str, left: impl Fn(&str) -> bool, right: impl Fn(&str) -> bool) {}
impl<'a> Vm { impl<'a> Vm {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
@ -155,11 +157,11 @@ impl<'a> Vm {
"IF"|"if" => { "IF"|"if" => {
let expr = unwrap!(); let expr = unwrap!();
let mut content = String::new(); 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) { while !matches!(next, Some("THEN")|Some("then")|None) {
content.push_str(next.unwrap()); content.push_str(next.unwrap());
content.push_str(" "); content.push_str(" ");
next = parser.inner_next(); next = parser.inner_next_back();
} }
if expr == 0 { if expr == 0 {
@ -168,45 +170,105 @@ impl<'a> Vm {
self.vmrun(&mut Parser::new(content.as_str())); 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 { 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" => { "DO"|"do" => {
let start = unwrap!(); let start = unwrap!();
let limit = unwrap!(); let limit = unwrap!();
let mut action = String::new(); 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) { while !matches!(next, Some("LOOP")|Some("loop")|None) {
action.push_str(next.unwrap()); action.push_str(next.unwrap());
action.push_str(" "); action.push_str(" ");
next = parser.inner_next(); next = parser.inner_next_back();
} }
for i in start..limit { 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.dictionary.words.insert("i".to_string(), i.to_string());
self.vmrun(&mut Parser::new(action.as_str())); self.vmrun(&mut Parser::new(action.as_str()));
} }
self.dictionary.words.remove("I"); 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 mut word_content = String::new();
let Some(Word(word_name)) = parser.next() else { println!("ERROR: Word name not given."); std::process::exit(1); }; 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 { while next != Some(";") && next != None {
word_content.push_str(next.unwrap()); word_content.push_str(next.unwrap());
word_content.push_str(" "); word_content.push_str(" ");
next = parser.inner_next(); next = parser.inner_next_back();
} }
self.dictionary.words.insert(word_name.to_string(), word_content); self.dictionary.words.insert(word_name.to_string(), word_content);
}, },
";" => {},
"BYE"|"bye" => { "BYE"|"bye" => {
std::process::exit(0); std::process::exit(0);
} },
"clearstack" => {
self.stack = Vec::new();
},
word => { word => {
let words = self.dictionary.words.clone(); let words = self.dictionary.words.clone();
let Some(word_content) = words.get(word) else { let Some(word_content) = words.get(word) else {

View file

@ -8,15 +8,14 @@ use backend::Vm;
fn repl() { fn repl() {
println!("Fourth REPL:"); println!("Fourth REPL:");
println!("To exit, use the `bye` command"); println!("To exit, use the `bye` command");
let mut code = String::new(); let mut vm = Vm::new();
loop { loop {
print!("> "); print!("> ");
std::io::stdout().flush().unwrap(); std::io::stdout().flush().unwrap();
let mut line = String::new(); let mut line = String::new();
let _ = std::io::stdin().read_line(&mut line); let _ = std::io::stdin().read_line(&mut line);
code.push_str(line.as_str());
if !matches!(line.as_str(), "bye"|"BYE") { 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 { } else {
println!("Bye bye and have a good day!"); println!("Bye bye and have a good day!");
std::io::stdout().flush().unwrap(); std::io::stdout().flush().unwrap();

View file

@ -34,4 +34,7 @@ impl<'a> Parser<'a> {
pub fn inner_next(&mut self) -> Option<&'a str> { pub fn inner_next(&mut self) -> Option<&'a str> {
self.split_whitespace.next() self.split_whitespace.next()
} }
pub fn inner_next_back(&mut self) -> Option<&'a str> {
self.split_whitespace.next()
}
} }

4
until.fs Normal file
View file

@ -0,0 +1,4 @@
variable loopy
BEGIN 12 1 loopy +! WHILE 10 loopy @ <> REPEAT
trace stack

1
until.fs~ Normal file
View file

@ -0,0 +1 @@
BEGIN 12 1 UNTIL