152 lines
3.9 KiB
Rust
152 lines
3.9 KiB
Rust
use std::collections::HashMap;
|
|
use crate::parse::Parser;
|
|
use crate::parse::TokenType::*;
|
|
|
|
#[derive(Debug)]
|
|
pub struct Vm {
|
|
stack: Vec<u64>,
|
|
dictionary: Dictionary
|
|
}
|
|
|
|
#[derive(Debug, Default)]
|
|
struct Dictionary {
|
|
dp: u64,
|
|
data: HashMap<u64, u64>,
|
|
words: HashMap<String, String>
|
|
}
|
|
|
|
impl<'a> Vm {
|
|
pub fn new() -> Self {
|
|
Self {
|
|
stack: Vec::new(),
|
|
dictionary: Default::default()
|
|
}
|
|
}
|
|
|
|
pub fn vmrun(&mut self, parser: &mut Parser) {
|
|
macro_rules! unwrap {
|
|
() => {
|
|
match self.stack.pop() {
|
|
Some(v) => {
|
|
v
|
|
},
|
|
None => {
|
|
println!("ERROR: stack empty");
|
|
std::process::exit(1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
while let Some(item) = parser.next() {
|
|
match item {
|
|
Number(n) => self.stack.push(n),
|
|
Word(w) => {
|
|
match w {
|
|
"." => {
|
|
println!("{:?} ok", unwrap!());
|
|
},
|
|
"+" => {
|
|
let sum = unwrap!().wrapping_add(unwrap!());
|
|
self.stack.push(sum);
|
|
},
|
|
"*" => {
|
|
let prod = unwrap!().wrapping_mul(unwrap!());
|
|
self.stack.push(prod);
|
|
},
|
|
"/" => {
|
|
let stack_top = unwrap!();
|
|
let stack_second = unwrap!();
|
|
let quo = stack_second.wrapping_div(stack_top);
|
|
self.stack.push(quo);
|
|
},
|
|
"=" => {
|
|
if unwrap!() == unwrap!() {
|
|
self.stack.push(1);
|
|
} else {
|
|
self.stack.push(0);
|
|
}
|
|
},
|
|
"MOD"|"mod" => {
|
|
let stack_top = unwrap!();
|
|
let stack_second = unwrap!();
|
|
let rem = stack_second.wrapping_rem(stack_top);
|
|
self.stack.push(rem);
|
|
},
|
|
"/MOD"|"/mod" => {
|
|
let stack_top = unwrap!();
|
|
let stack_second = unwrap!();
|
|
let rem = stack_second.wrapping_rem(stack_top);
|
|
let quo = stack_second.wrapping_div(stack_top);
|
|
self.stack.push(rem);
|
|
self.stack.push(quo);
|
|
},
|
|
"SWAP"|"swap" => {
|
|
let stack_top = unwrap!();
|
|
let stack_second = unwrap!();
|
|
self.stack.push(stack_top);
|
|
self.stack.push(stack_second);
|
|
},
|
|
"HERE"|"here" => {
|
|
self.stack.push(self.dictionary.dp);
|
|
},
|
|
"@" => {
|
|
let addr = unwrap!();
|
|
self.stack.push(*self.dictionary.data.get(&addr).unwrap_or(&0));
|
|
},
|
|
"!" => {
|
|
let addr = unwrap!();
|
|
let content = unwrap!();
|
|
self.dictionary.data.insert(addr, content);
|
|
},
|
|
"," => {
|
|
let content = unwrap!();
|
|
self.dictionary.dp += 1;
|
|
self.dictionary.data.insert(self.dictionary.dp, content);
|
|
},
|
|
"ALLOT"|"allot" => {
|
|
self.dictionary.dp += unwrap!();
|
|
},
|
|
"CREATE"|"create" => {
|
|
self.dictionary.dp += 1;
|
|
let Some(Word(word_name)) = parser.next() else { println!("ERROR: Word name not given."); std::process::exit(1) };
|
|
self.dictionary.words.insert(word_name.to_string(), self.dictionary.dp.to_string());
|
|
},
|
|
"VARIABLE"|"variable" => {
|
|
self.dictionary.dp += 1;
|
|
let Some(Word(word_name)) = parser.next() else { println!("ERROR: Word name not given."); std::process::exit(1) };
|
|
self.dictionary.words.insert(word_name.to_string(), self.dictionary.dp.to_string());
|
|
|
|
},
|
|
"DUP"|"dup" => {
|
|
let stack_top = unwrap!();
|
|
self.stack.push(stack_top);
|
|
self.stack.push(stack_top);
|
|
},
|
|
":" => {
|
|
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();
|
|
while next != Some(";") && next != None {
|
|
word_content.push_str(next.unwrap());
|
|
word_content.push_str(" ");
|
|
next = parser.inner_next();
|
|
}
|
|
|
|
self.dictionary.words.insert(word_name.to_string(), word_content);
|
|
},
|
|
word => {
|
|
let words = self.dictionary.words.clone();
|
|
let Some(word_content) = words.get(word) else {
|
|
println!("word {:?} does not exist", word);
|
|
std::process::exit(1);
|
|
};
|
|
self.vmrun(&mut Parser::new(word_content));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|