use crate::{
code::Code,
errors::{error::Error, error_kind::ErrorKind},
tokens::token::Token,
utils::{frames::Frame, stack::Stack},
values::{value::Value, value_kinds::ValueKind},
};
use std::{collections::VecDeque, rc::Rc};
#[derive(Debug)]
pub struct VM {
code: Code,
pub operand_stack: Stack<Rc<Value>>,
call_stack: Stack<Frame>,
}
impl VM {
pub fn new(tokens: VecDeque<Token>) -> Result<VM, Error> {
let code = Code::new(tokens)?;
let main_frame = Frame::new(0, "main", None);
let mut call_stack = Stack::new();
call_stack.push(main_frame);
Ok(VM {
code,
operand_stack: Stack::new(),
call_stack,
})
}
pub fn run(&mut self) -> Result<Option<Rc<Value>>, Error> {
loop {
if self.is_finished() {
return Ok(None);
}
let next = self.next().unwrap();
let result = self.evaluate_value(next)?;
if self.is_finished() && result.is_some() {
return Ok(result);
}
}
}
fn evaluate_value(&mut self, value: Rc<Value>) -> Result<Option<Rc<Value>>, Error> {
match &value.kind {
ValueKind::Void => Ok(None),
ValueKind::Any => Ok(None),
ValueKind::Int(_)
| ValueKind::Float(_)
| ValueKind::Boolean(_)
| ValueKind::String(_) => Ok(Some(value)),
ValueKind::Identifier(name) => self
.call_stack
.peek()
.unwrap()
.find(name, value.pos)
.map(Some),
ValueKind::Label(_) => {
let mut found_end = false;
while let Some(value) = self.next() {
if let ValueKind::End = value.kind {
found_end = true;
break;
}
}
if !found_end {
Err(Error::new(ErrorKind::NoEndOfLabel, value.pos))
} else {
Ok(None)
}
}
ValueKind::End => {
let frame = self.call_stack.pop(value.pos)?;
if let Some(error) = self
.code
.jump(frame.get_caller_position() as i64, value.pos)
{
Err(error)
} else {
Ok(None)
}
}
ValueKind::Push => self.push(value.pos),
ValueKind::Pop => self.pop(value.pos).map(|(_, value)| value),
ValueKind::Peek => self.operand_stack.peek().map_or(
Ok(Some(Rc::new(Value::new(value.pos, ValueKind::Void)))),
|peeked_value| Ok(Some(peeked_value.clone())),
),
ValueKind::Add => self.add(value.pos),
ValueKind::Sub => self.sub(value.pos),
ValueKind::Mul => self.mul(value.pos),
ValueKind::Div => self.div(value.pos),
ValueKind::LessThan => self.lt(value.pos),
ValueKind::LessThanEqual => self.lte(value.pos),
ValueKind::GreaterThan => self.gt(value.pos),
ValueKind::GreaterThanEqual => self.gte(value.pos),
ValueKind::Equal => self.eq(value.pos),
ValueKind::NotEqual => self.neq(value.pos),
ValueKind::Jump => self.jmp(value.pos),
ValueKind::RelativeJump => self.rjmp(value.pos),
ValueKind::JumpIfTrue => self.jmpt(value.pos),
ValueKind::JumpIfFalse => self.jmpf(value.pos),
ValueKind::Print => self.print(value.pos),
ValueKind::PrintNewLine => self.printn(value.pos),
ValueKind::Set => self.set(value.pos),
ValueKind::Call => self.call(value.pos),
}
}
fn push(&mut self, pos: usize) -> Result<Option<Rc<Value>>, Error> {
let (pos, arg) = self.get_arg(1, pos)?;
match arg {
Some(value) => self.operand_stack.push(value),
None => {
return Err(Error::new(
ErrorKind::ValueMismatch(
ValueKind::Any.get_value_name(),
ValueKind::Void.get_value_name(),
),
pos,
))
}
}
Ok(None)
}
fn pop(&mut self, pos: usize) -> Result<(usize, Option<Rc<Value>>), Error> {
self.operand_stack.pop(pos).map(|val| (val.pos, Some(val)))
}
fn add(&mut self, pos: usize) -> Result<Option<Rc<Value>>, Error> {
let (arg_pos_1, arg1) = self.pop(pos)?;
let (arg_pos_2, arg2) = self.pop(pos)?;
match (arg1, arg2) {
(Some(operand1), Some(operand2)) => operand1
.add(operand2.as_ref(), pos)
.map(|val| Some(Rc::new(val))),
(None, _) => Err(Error::new(
ErrorKind::ValueMismatch(
ValueKind::Any.get_value_name(),
ValueKind::Void.get_value_name(),
),
arg_pos_1,
)),
(_, None) => Err(Error::new(
ErrorKind::ValueMismatch(
ValueKind::Any.get_value_name(),
ValueKind::Void.get_value_name(),
),
arg_pos_2,
)),
}
}
fn sub(&mut self, pos: usize) -> Result<Option<Rc<Value>>, Error> {
let (arg_pos_1, arg1) = self.pop(pos)?;
let (arg_pos_2, arg2) = self.pop(pos)?;
match (arg1, arg2) {
(Some(operand1), Some(operand2)) => operand1
.sub(operand2.as_ref(), pos)
.map(|val| Some(Rc::new(val))),
(None, _) => Err(Error::new(
ErrorKind::ValueMismatch(
ValueKind::Any.get_value_name(),
ValueKind::Void.get_value_name(),
),
arg_pos_1,
)),
(_, None) => Err(Error::new(
ErrorKind::ValueMismatch(
ValueKind::Any.get_value_name(),
ValueKind::Void.get_value_name(),
),
arg_pos_2,
)),
}
}
fn mul(&mut self, pos: usize) -> Result<Option<Rc<Value>>, Error> {
let (arg_pos_1, arg1) = self.pop(pos)?;
let (arg_pos_2, arg2) = self.pop(pos)?;
match (arg1, arg2) {
(Some(operand1), Some(operand2)) => operand1
.mul(operand2.as_ref(), pos)
.map(|val| Some(Rc::new(val))),
(None, _) => Err(Error::new(
ErrorKind::ValueMismatch(
ValueKind::Any.get_value_name(),
ValueKind::Void.get_value_name(),
),
arg_pos_1,
)),
(_, None) => Err(Error::new(
ErrorKind::ValueMismatch(
ValueKind::Any.get_value_name(),
ValueKind::Void.get_value_name(),
),
arg_pos_2,
)),
}
}
fn div(&mut self, pos: usize) -> Result<Option<Rc<Value>>, Error> {
let (arg_pos_1, arg1) = self.pop(pos)?;
let (arg_pos_2, arg2) = self.pop(pos)?;
match (arg1, arg2) {
(Some(operand1), Some(operand2)) => operand1
.div(operand2.as_ref(), pos)
.map(|val| Some(Rc::new(val))),
(None, _) => Err(Error::new(
ErrorKind::ValueMismatch(
ValueKind::Any.get_value_name(),
ValueKind::Void.get_value_name(),
),
arg_pos_1,
)),
(_, None) => Err(Error::new(
ErrorKind::ValueMismatch(
ValueKind::Any.get_value_name(),
ValueKind::Void.get_value_name(),
),
arg_pos_2,
)),
}
}
fn lt(&mut self, pos: usize) -> Result<Option<Rc<Value>>, Error> {
let (arg_pos_1, arg1) = self.get_arg(2, pos)?;
let (arg_pos_2, arg2) = self.get_arg(1, pos)?;
match (arg1, arg2) {
(Some(operand1), Some(operand2)) => operand1
.lt(operand2.as_ref(), pos)
.map(|val| Some(Rc::new(val))),
(None, _) => Err(Error::new(
ErrorKind::ValueMismatch(
ValueKind::Any.get_value_name(),
ValueKind::Void.get_value_name(),
),
arg_pos_1,
)),
(_, None) => Err(Error::new(
ErrorKind::ValueMismatch(
ValueKind::Any.get_value_name(),
ValueKind::Void.get_value_name(),
),
arg_pos_2,
)),
}
}
fn lte(&mut self, pos: usize) -> Result<Option<Rc<Value>>, Error> {
let (arg_pos_1, arg1) = self.get_arg(2, pos)?;
let (arg_pos_2, arg2) = self.get_arg(1, pos)?;
match (arg1, arg2) {
(Some(operand1), Some(operand2)) => operand1
.lte(operand2.as_ref(), pos)
.map(|val| Some(Rc::new(val))),
(None, _) => Err(Error::new(
ErrorKind::ValueMismatch(
ValueKind::Any.get_value_name(),
ValueKind::Void.get_value_name(),
),
arg_pos_1,
)),
(_, None) => Err(Error::new(
ErrorKind::ValueMismatch(
ValueKind::Any.get_value_name(),
ValueKind::Void.get_value_name(),
),
arg_pos_2,
)),
}
}
fn gt(&mut self, pos: usize) -> Result<Option<Rc<Value>>, Error> {
let (arg_pos_1, arg1) = self.get_arg(2, pos)?;
let (arg_pos_2, arg2) = self.get_arg(1, pos)?;
match (arg1, arg2) {
(Some(operand1), Some(operand2)) => operand1
.gt(operand2.as_ref(), pos)
.map(|val| Some(Rc::new(val))),
(None, _) => Err(Error::new(
ErrorKind::ValueMismatch(
ValueKind::Any.get_value_name(),
ValueKind::Void.get_value_name(),
),
arg_pos_1,
)),
(_, None) => Err(Error::new(
ErrorKind::ValueMismatch(
ValueKind::Any.get_value_name(),
ValueKind::Void.get_value_name(),
),
arg_pos_2,
)),
}
}
fn gte(&mut self, pos: usize) -> Result<Option<Rc<Value>>, Error> {
let (arg_pos_1, arg1) = self.get_arg(2, pos)?;
let (arg_pos_2, arg2) = self.get_arg(1, pos)?;
match (arg1, arg2) {
(Some(operand1), Some(operand2)) => operand1
.gte(operand2.as_ref(), pos)
.map(|val| Some(Rc::new(val))),
(None, _) => Err(Error::new(
ErrorKind::ValueMismatch(
ValueKind::Any.get_value_name(),
ValueKind::Void.get_value_name(),
),
arg_pos_1,
)),
(_, None) => Err(Error::new(
ErrorKind::ValueMismatch(
ValueKind::Any.get_value_name(),
ValueKind::Void.get_value_name(),
),
arg_pos_2,
)),
}
}
fn eq(&mut self, pos: usize) -> Result<Option<Rc<Value>>, Error> {
let (arg_pos_1, arg1) = self.get_arg(2, pos)?;
let (arg_pos_2, arg2) = self.get_arg(1, pos)?;
match (arg1, arg2) {
(Some(operand1), Some(operand2)) => Ok(Some(Rc::new(operand1.equal(operand2.as_ref(), pos)))),
(None, _) => Err(Error::new(
ErrorKind::ValueMismatch(
ValueKind::Any.get_value_name(),
ValueKind::Void.get_value_name(),
),
arg_pos_1,
)),
(_, None) => Err(Error::new(
ErrorKind::ValueMismatch(
ValueKind::Any.get_value_name(),
ValueKind::Void.get_value_name(),
),
arg_pos_2,
)),
}
}
fn neq(&mut self, pos: usize) -> Result<Option<Rc<Value>>, Error> {
let (arg_pos_1, arg1) = self.get_arg(2, pos)?;
let (arg_pos_2, arg2) = self.get_arg(1, pos)?;
match (arg1, arg2) {
(Some(operand1), Some(operand2)) => Ok(Some(Rc::new(operand1.not_equal(operand2.as_ref(), pos)))),
(None, _) => Err(Error::new(
ErrorKind::ValueMismatch(
ValueKind::Any.get_value_name(),
ValueKind::Void.get_value_name(),
),
arg_pos_1,
)),
(_, None) => Err(Error::new(
ErrorKind::ValueMismatch(
ValueKind::Any.get_value_name(),
ValueKind::Void.get_value_name(),
),
arg_pos_2,
)),
}
}
fn jmp(&mut self, pos: usize) -> Result<Option<Rc<Value>>, Error> {
let (arg_pos_1, arg1) = self.get_arg(1, pos)?;
match arg1 {
Some(value) => {
if let ValueKind::Int(jump_location) = value.kind {
if let Some(error) = self.code.jump(jump_location, pos) {
Err(error)
} else {
Ok(None)
}
} else {
Err(Error::new(
ErrorKind::ValueMismatch(
ValueKind::Int(0).get_value_name(),
value.kind.get_value_name(),
),
arg_pos_1,
))
}
}
None => Err(Error::new(
ErrorKind::ValueMismatch(
ValueKind::Int(0).get_value_name(),
ValueKind::Void.get_value_name(),
),
arg_pos_1,
)),
}
}
fn rjmp(&mut self, pos: usize) -> Result<Option<Rc<Value>>, Error> {
let (arg_pos_1, arg1) = self.get_arg(1, pos)?;
match arg1 {
Some(value) => {
if let ValueKind::Int(jump_location) = value.kind {
if let Some(error) = self.code.relative_jump(jump_location, pos) {
Err(error)
} else {
Ok(None)
}
} else {
Err(Error::new(
ErrorKind::ValueMismatch(
ValueKind::Int(0).get_value_name(),
value.kind.get_value_name(),
),
arg_pos_1,
))
}
}
None => Err(Error::new(
ErrorKind::ValueMismatch(
ValueKind::Int(0).get_value_name(),
ValueKind::Void.get_value_name(),
),
arg_pos_1,
)),
}
}
fn jmpt(&mut self, pos: usize) -> Result<Option<Rc<Value>>, Error> {
match self.operand_stack.peek() {
Some(value) if value.is_truthy() => self.jmp(pos),
None => Err(Error::new(ErrorKind::EmptyStack, pos)),
_ => Ok(None),
}
}
fn jmpf(&mut self, pos: usize) -> Result<Option<Rc<Value>>, Error> {
match self.operand_stack.peek() {
Some(value) if !value.is_truthy() => self.jmp(pos),
None => Err(Error::new(ErrorKind::EmptyStack, pos)),
_ => Ok(None),
}
}
fn print(&mut self, pos: usize) -> Result<Option<Rc<Value>>, Error> {
let (arg_pos_1, arg1) = self.get_arg(1, pos)?;
match arg1 {
Some(value) => {
print!("{:#?}", value);
Ok(None)
}
None => Err(Error::new(
ErrorKind::ValueMismatch(
ValueKind::Any.get_value_name(),
ValueKind::Void.get_value_name(),
),
arg_pos_1,
)),
}
}
fn printn(&mut self, pos: usize) -> Result<Option<Rc<Value>>, Error> {
let (arg_pos_1, arg1) = self.get_arg(1, pos)?;
match arg1 {
Some(value) => {
println!("{:#?}", value);
Ok(None)
}
None => Err(Error::new(
ErrorKind::ValueMismatch(
ValueKind::Any.get_value_name(),
ValueKind::Void.get_value_name(),
),
arg_pos_1,
)),
}
}
fn set(&mut self, pos: usize) -> Result<Option<Rc<Value>>, Error> {
let (arg_pos_1, arg1) = self.get_arg_unevaluated(2, pos)?;
let (arg_pos_2, arg2) = self.get_arg(1, pos)?;
match &arg1.kind {
ValueKind::Identifier(name) => {
if let Some(value) = arg2 {
self.call_stack.peek_mut().unwrap().define(name, value);
Ok(None)
} else {
Err(Error::new(
ErrorKind::ValueMismatch(
ValueKind::Any.get_value_name(),
ValueKind::Void.get_value_name(),
),
arg_pos_2,
))
}
}
kind => Err(Error::new(
ErrorKind::ValueMismatch(
ValueKind::Identifier("".to_owned()).get_value_name(),
kind.get_value_name(),
),
arg_pos_1,
)),
}
}
fn call(&mut self, pos: usize) -> Result<Option<Rc<Value>>, Error> {
let (arg_pos_1, arg1) = self.get_arg_unevaluated(1, pos)?;
match &arg1.kind {
ValueKind::Identifier(label_name) => {
let caller_pos = self.code.get_current_pos();
let (start, end) = self.code.set_label_location(label_name, arg_pos_1)?;
let store = self.call_stack.peek().filter(|frame| {
if let Some((cur_start, cur_end)) = self.code.get_label_start_end(&frame.name) {
cur_start < start && end < cur_end
} else {
false
}
}).map(|frame| &frame.current_store);
let new_frame = Frame::new(caller_pos, label_name, store);
self.call_stack.push(new_frame);
Ok(None)
},
kind => Err(Error::new(
ErrorKind::ValueMismatch(
ValueKind::Label("".to_owned()).get_value_name(),
kind.get_value_name(),
),
arg_pos_1,
)),
}
}
fn get_arg(
&mut self,
expected_args: usize,
pos: usize,
) -> Result<(usize, Option<Rc<Value>>), Error> {
let arg = self
.next()
.ok_or_else(|| Error::new(ErrorKind::ExpectedArgs(expected_args), pos))?;
Ok((arg.pos, self.evaluate_value(arg)?))
}
fn get_arg_unevaluated(
&mut self,
expected_args: usize,
pos: usize,
) -> Result<(usize, Rc<Value>), Error> {
let arg = self
.next()
.ok_or_else(|| Error::new(ErrorKind::ExpectedArgs(expected_args), pos))?;
Ok((arg.pos, arg))
}
fn next(&mut self) -> Option<Rc<Value>> {
self.code.next()
}
fn is_finished(&self) -> bool {
self.code.is_finished() || self.call_stack.is_empty()
}
}