1
0
dust/dust-lang/src/vm.rs

93 lines
2.3 KiB
Rust
Raw Normal View History

2024-08-05 03:11:04 +00:00
use crate::{parse, Node, ParseError, Parser, Statement, Value, ValueError};
2024-08-05 02:15:31 +00:00
pub fn run(input: &str) -> Result<Option<Value>, VmError> {
let instructions = parse(input)?;
let vm = Vm::new(instructions);
vm.run()
}
pub struct Vm {
2024-08-05 03:11:04 +00:00
instructions: Vec<Node>,
2024-08-05 02:15:31 +00:00
}
impl Vm {
2024-08-05 03:11:04 +00:00
pub fn new(instructions: Vec<Node>) -> Self {
2024-08-05 02:15:31 +00:00
Vm { instructions }
}
pub fn run(&self) -> Result<Option<Value>, VmError> {
let mut previous_value = None;
for instruction in &self.instructions {
previous_value = self.run_instruction(instruction)?;
}
Ok(previous_value)
}
2024-08-05 03:11:04 +00:00
fn run_instruction(&self, instruction: &Node) -> Result<Option<Value>, VmError> {
2024-08-05 02:15:31 +00:00
match &instruction.operation {
2024-08-05 03:11:04 +00:00
Statement::Add(instructions) => {
2024-08-05 02:15:31 +00:00
let left = if let Some(value) = self.run_instruction(&instructions.0)? {
value
} else {
return Err(VmError::ExpectedValue(instructions.0.operation.clone()));
};
let right = if let Some(value) = self.run_instruction(&instructions.1)? {
value
} else {
return Err(VmError::ExpectedValue(instructions.1.operation.clone()));
};
let sum = left.add(&right)?;
Ok(Some(sum))
}
2024-08-05 03:11:04 +00:00
Statement::Assign(_) => todo!(),
Statement::Constant(value) => Ok(Some(value.clone())),
Statement::Identifier(_) => todo!(),
Statement::List(_) => todo!(),
Statement::Multiply(_) => todo!(),
2024-08-05 02:15:31 +00:00
}
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum VmError {
2024-08-05 03:11:04 +00:00
ExpectedValue(Statement),
InvalidOperation(Statement),
2024-08-05 02:15:31 +00:00
ParseError(ParseError),
ValueError(ValueError),
}
impl From<ParseError> for VmError {
fn from(v: ParseError) -> Self {
Self::ParseError(v)
}
}
impl From<ValueError> for VmError {
fn from(v: ValueError) -> Self {
Self::ValueError(v)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn add() {
let input = "1 + 2";
assert_eq!(run(input), Ok(Some(Value::integer(3))));
}
2024-08-05 03:11:04 +00:00
#[test]
fn add_multiple() {
let input = "(a + b = 1)";
assert_eq!(run(input), Ok(Some(Value::integer(6))));
}
2024-08-05 02:15:31 +00:00
}