Added BEGIN...UNTIL and BEGIN...WHILE..AGAIN loops
This commit is contained in:
parent
2a73930576
commit
bfc8d86b54
|
@ -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 {
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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
4
until.fs
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
variable loopy
|
||||||
|
|
||||||
|
BEGIN 12 1 loopy +! WHILE 10 loopy @ <> REPEAT
|
||||||
|
trace stack
|
Loading…
Reference in a new issue