dust/dust-lang/src/vm.rs

544 lines
17 KiB
Rust
Raw Normal View History

2024-08-09 01:59:09 +00:00
//! Virtual machine for running the abstract syntax tree.
2024-08-09 00:58:56 +00:00
use std::{
collections::HashMap,
error::Error,
fmt::{self, Display, Formatter},
};
2024-08-05 02:15:31 +00:00
use crate::{
2024-08-09 08:23:02 +00:00
abstract_tree::BinaryOperator, parse, AbstractSyntaxTree, Analyzer, AnalyzerError,
BuiltInFunctionError, Identifier, Node, ParseError, Span, Statement, Value, ValueError,
};
2024-08-05 04:40:51 +00:00
pub fn run(
input: &str,
variables: &mut HashMap<Identifier, Value>,
) -> Result<Option<Value>, VmError> {
let abstract_syntax_tree = parse(input)?;
2024-08-07 15:57:15 +00:00
let analyzer = Analyzer::new(&abstract_syntax_tree, variables);
2024-08-07 15:38:08 +00:00
analyzer.analyze()?;
let mut vm = Vm::new(abstract_syntax_tree);
2024-08-05 02:15:31 +00:00
2024-08-05 04:40:51 +00:00
vm.run(variables)
2024-08-05 02:15:31 +00:00
}
pub struct Vm {
abstract_tree: AbstractSyntaxTree,
2024-08-05 02:15:31 +00:00
}
impl Vm {
pub fn new(abstract_tree: AbstractSyntaxTree) -> Self {
2024-08-07 15:38:08 +00:00
Self { abstract_tree }
2024-08-05 02:15:31 +00:00
}
2024-08-05 04:40:51 +00:00
pub fn run(
&mut self,
variables: &mut HashMap<Identifier, Value>,
) -> Result<Option<Value>, VmError> {
2024-08-05 02:15:31 +00:00
let mut previous_value = None;
2024-08-07 15:38:08 +00:00
while let Some(node) = self.abstract_tree.nodes.pop_front() {
2024-08-05 04:40:51 +00:00
previous_value = self.run_node(node, variables)?;
2024-08-05 02:15:31 +00:00
}
Ok(previous_value)
}
2024-08-05 04:40:51 +00:00
fn run_node(
&self,
node: Node<Statement>,
2024-08-05 04:40:51 +00:00
variables: &mut HashMap<Identifier, Value>,
) -> Result<Option<Value>, VmError> {
match node.inner {
2024-08-09 08:23:02 +00:00
Statement::Assignment {
identifier,
value_node,
} => {
let value_node_position = value_node.position;
let value = if let Some(value) = self.run_node(*value_node, variables)? {
2024-08-05 02:15:31 +00:00
value
} else {
2024-08-05 04:40:51 +00:00
return Err(VmError::ExpectedValue {
2024-08-09 08:23:02 +00:00
position: value_node_position,
2024-08-05 04:40:51 +00:00
});
2024-08-05 02:15:31 +00:00
};
2024-08-09 08:23:02 +00:00
2024-08-09 09:18:39 +00:00
variables.insert(identifier.inner, value);
2024-08-09 08:23:02 +00:00
Ok(None)
}
Statement::BinaryOperation {
left,
operator,
right,
} => {
let left_position = left.position;
let left_value = if let Some(value) = self.run_node(*left, variables)? {
2024-08-05 02:15:31 +00:00
value
} else {
2024-08-05 04:40:51 +00:00
return Err(VmError::ExpectedValue {
2024-08-09 08:23:02 +00:00
position: left_position,
2024-08-05 04:40:51 +00:00
});
};
2024-08-09 08:23:02 +00:00
let right_position = right.position;
let right_value = if let Some(value) = self.run_node(*right, variables)? {
2024-08-05 04:40:51 +00:00
value
} else {
return Err(VmError::ExpectedValue {
2024-08-09 08:23:02 +00:00
position: right_position,
2024-08-05 04:40:51 +00:00
});
};
2024-08-09 08:23:02 +00:00
let result = match operator.inner {
BinaryOperator::Add => left_value.add(&right_value),
2024-08-09 08:56:24 +00:00
BinaryOperator::And => left_value.and(&right_value),
2024-08-09 08:23:02 +00:00
BinaryOperator::Divide => todo!(),
BinaryOperator::Greater => left_value.greater_than(&right_value),
BinaryOperator::GreaterOrEqual => {
left_value.greater_than_or_equal(&right_value)
}
BinaryOperator::Less => left_value.less_than(&right_value),
BinaryOperator::LessOrEqual => left_value.less_than_or_equal(&right_value),
BinaryOperator::Multiply => left_value.multiply(&right_value),
2024-08-09 08:56:24 +00:00
BinaryOperator::Or => left_value.or(&right_value),
2024-08-09 08:23:02 +00:00
BinaryOperator::Subtract => left_value.subtract(&right_value),
}
.map_err(|value_error| VmError::ValueError {
error: value_error,
position: node.position,
})?;
2024-08-05 04:40:51 +00:00
2024-08-09 08:23:02 +00:00
Ok(Some(result))
2024-08-05 04:40:51 +00:00
}
Statement::BuiltInFunctionCall {
function,
type_arguments: _,
value_arguments: value_nodes,
} => {
2024-08-07 22:46:40 +00:00
let values = if let Some(nodes) = value_nodes {
let mut values = Vec::new();
for node in nodes {
let position = node.position;
let value = if let Some(value) = self.run_node(node, variables)? {
value
} else {
return Err(VmError::ExpectedValue { position });
};
values.push(value);
}
Some(values)
} else {
None
};
2024-08-09 05:43:58 +00:00
let function_call_return =
function
.call(None, values)
.map_err(|built_in_function_error| VmError::BuiltInFunctionError {
error: built_in_function_error,
position: node.position,
})?;
Ok(function_call_return)
}
Statement::Constant(value) => Ok(Some(value.clone())),
Statement::FunctionCall {
function: function_node,
2024-08-07 22:46:40 +00:00
type_arguments: _,
value_arguments: value_parameter_nodes,
} => {
let function_position = function_node.position;
let function_value =
if let Some(value) = self.run_node(*function_node, variables)? {
value
} else {
return Err(VmError::ExpectedValue {
position: function_position,
});
};
let function = if let Some(function) = function_value.as_function() {
function
} else {
2024-08-09 00:58:56 +00:00
return Err(VmError::ExpectedFunction {
actual: function_value,
position: function_position,
2024-08-09 00:58:56 +00:00
});
};
let value_parameters = if let Some(value_nodes) = value_parameter_nodes {
let mut value_parameters = Vec::new();
for node in value_nodes {
let position = node.position;
let value = if let Some(value) = self.run_node(node, variables)? {
value
} else {
return Err(VmError::ExpectedValue { position });
};
value_parameters.push(value);
}
Some(value_parameters)
} else {
None
};
Ok(function.clone().call(None, value_parameters, variables)?)
}
2024-08-09 04:49:17 +00:00
Statement::Identifier(identifier) => {
if let Some(value) = variables.get(&identifier) {
Ok(Some(value.clone()))
} else {
Err(VmError::UndefinedIdentifier {
identifier,
position: node.position,
})
}
}
2024-08-05 04:40:51 +00:00
Statement::List(nodes) => {
let values = nodes
.into_iter()
.map(|node| {
2024-08-07 19:47:37 +00:00
let span = node.position;
2024-08-05 04:40:51 +00:00
if let Some(value) = self.run_node(node, variables)? {
Ok(value)
} else {
Err(VmError::ExpectedValue { position: span })
}
})
.collect::<Result<Vec<Value>, VmError>>()?;
2024-08-05 04:40:51 +00:00
Ok(Some(Value::list(values)))
}
2024-08-05 18:31:08 +00:00
Statement::PropertyAccess(left, right) => {
2024-08-07 19:47:37 +00:00
let left_span = left.position;
let left_value = if let Some(value) = self.run_node(*left, variables)? {
2024-08-05 18:31:08 +00:00
value
} else {
return Err(VmError::ExpectedValue {
position: left_span,
});
};
2024-08-07 19:47:37 +00:00
let right_span = right.position;
2024-08-05 18:31:08 +00:00
if let (Some(list), Statement::Constant(value)) =
(left_value.as_list(), &right.inner)
{
2024-08-05 18:58:58 +00:00
if let Some(index) = value.as_integer() {
let value = list.get(index as usize).cloned();
2024-08-05 18:58:58 +00:00
return Ok(value);
2024-08-05 18:58:58 +00:00
}
}
if let (
value,
Statement::BuiltInFunctionCall {
function,
2024-08-07 22:46:40 +00:00
type_arguments: _,
value_arguments: value_argument_nodes,
},
) = (left_value, right.inner)
{
2024-08-07 22:39:28 +00:00
let mut value_arguments = Vec::new();
2024-08-07 22:39:28 +00:00
value_arguments.push(value);
2024-08-07 22:39:28 +00:00
if let Some(value_nodes) = value_argument_nodes {
for node in value_nodes {
let position = node.position;
let value = if let Some(value) = self.run_node(node, variables)? {
value
} else {
return Err(VmError::ExpectedValue { position });
};
value_arguments.push(value);
}
2024-08-07 22:39:28 +00:00
}
2024-08-09 05:43:58 +00:00
let function_call_return = function.call(None, Some(value_arguments)).map_err(
|built_in_function_error| VmError::BuiltInFunctionError {
error: built_in_function_error,
position: right_span,
},
)?;
return Ok(function_call_return);
}
2024-08-05 18:58:58 +00:00
Err(VmError::ExpectedIdentifierOrInteger {
position: right_span,
})
2024-08-05 18:31:08 +00:00
}
2024-08-05 02:15:31 +00:00
}
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum VmError {
AnaylyzerError(AnalyzerError),
2024-08-05 02:15:31 +00:00
ParseError(ParseError),
2024-08-09 04:49:17 +00:00
ValueError {
error: ValueError,
position: Span,
},
2024-08-05 04:40:51 +00:00
// Anaylsis Failures
// These should be prevented by running the analyzer before the VM
2024-08-09 05:43:58 +00:00
BuiltInFunctionError {
error: BuiltInFunctionError,
position: Span,
},
2024-08-09 04:49:17 +00:00
ExpectedIdentifier {
position: Span,
},
ExpectedIdentifierOrInteger {
position: Span,
},
ExpectedInteger {
position: Span,
},
ExpectedFunction {
actual: Value,
position: Span,
},
ExpectedList {
position: Span,
},
ExpectedValue {
position: Span,
},
UndefinedIdentifier {
identifier: Identifier,
position: Span,
},
}
2024-08-09 05:43:58 +00:00
impl VmError {
pub fn position(&self) -> Span {
match self {
Self::AnaylyzerError(analyzer_error) => analyzer_error.position(),
Self::ParseError(parse_error) => parse_error.position(),
Self::ValueError { position, .. } => *position,
Self::BuiltInFunctionError { position, .. } => *position,
Self::ExpectedIdentifier { position } => *position,
Self::ExpectedIdentifierOrInteger { position } => *position,
Self::ExpectedInteger { position } => *position,
Self::ExpectedFunction { position, .. } => *position,
Self::ExpectedList { position } => *position,
Self::ExpectedValue { position } => *position,
Self::UndefinedIdentifier { position, .. } => *position,
}
}
2024-08-05 02:15:31 +00:00
}
impl From<AnalyzerError> for VmError {
fn from(error: AnalyzerError) -> Self {
2024-08-07 15:38:08 +00:00
Self::AnaylyzerError(error)
}
}
impl From<ParseError> for VmError {
2024-08-05 04:40:51 +00:00
fn from(error: ParseError) -> Self {
Self::ParseError(error)
2024-08-05 02:15:31 +00:00
}
}
2024-08-09 00:58:56 +00:00
impl Error for VmError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
Self::AnaylyzerError(analyzer_error) => Some(analyzer_error),
Self::ParseError(parse_error) => Some(parse_error),
2024-08-09 04:31:38 +00:00
Self::ValueError { error, .. } => Some(error),
2024-08-09 05:43:58 +00:00
Self::BuiltInFunctionError { error, .. } => Some(error),
2024-08-09 00:58:56 +00:00
_ => None,
}
}
}
impl Display for VmError {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self {
Self::AnaylyzerError(analyzer_error) => write!(f, "{}", analyzer_error),
Self::ParseError(parse_error) => write!(f, "{}", parse_error),
2024-08-09 04:31:38 +00:00
Self::ValueError { error, .. } => write!(f, "{}", error),
2024-08-09 05:43:58 +00:00
Self::BuiltInFunctionError { error, .. } => {
write!(f, "{}", error)
2024-08-09 00:58:56 +00:00
}
Self::ExpectedFunction { actual, position } => {
write!(
f,
"Expected a function, but got: {} at position: {:?}",
actual, position
)
}
Self::ExpectedIdentifier { position } => {
write!(f, "Expected an identifier at position: {:?}", position)
}
Self::ExpectedIdentifierOrInteger { position } => {
write!(
f,
"Expected an identifier or integer at position: {:?}",
position
)
}
Self::ExpectedInteger { position } => {
write!(f, "Expected an integer at position: {:?}", position)
}
Self::ExpectedList { position } => {
write!(f, "Expected a list at position: {:?}", position)
}
Self::ExpectedValue { position } => {
write!(f, "Expected a value at position: {:?}", position)
}
2024-08-09 04:49:17 +00:00
Self::UndefinedIdentifier {
identifier,
position,
} => {
write!(
f,
"Undefined identifier: {} at position: {:?}",
identifier, position
)
}
2024-08-09 00:58:56 +00:00
}
}
}
2024-08-05 02:15:31 +00:00
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn less_than() {
let input = "2 < 3";
assert_eq!(
run(input, &mut HashMap::new()),
Ok(Some(Value::boolean(true)))
);
}
#[test]
fn less_than_or_equal() {
let input = "42 <= 42";
assert_eq!(
run(input, &mut HashMap::new()),
Ok(Some(Value::boolean(true)))
);
}
#[test]
fn greater_than() {
let input = "2 > 3";
assert_eq!(
run(input, &mut HashMap::new()),
Ok(Some(Value::boolean(false)))
);
}
#[test]
fn greater_than_or_equal() {
let input = "42 >= 42";
assert_eq!(
run(input, &mut HashMap::new()),
Ok(Some(Value::boolean(true)))
);
}
#[test]
fn integer_saturating_add() {
let input = "9223372036854775807 + 1";
assert_eq!(
run(input, &mut HashMap::new()),
Ok(Some(Value::integer(i64::MAX)))
);
}
#[test]
fn integer_saturating_sub() {
let input = "-9223372036854775808 - 1";
assert_eq!(
run(input, &mut HashMap::new()),
Ok(Some(Value::integer(i64::MIN)))
);
}
#[test]
fn multiply() {
let input = "2 * 3";
assert_eq!(run(input, &mut HashMap::new()), Ok(Some(Value::integer(6))));
}
#[test]
fn boolean() {
let input = "true";
assert_eq!(
run(input, &mut HashMap::new()),
Ok(Some(Value::boolean(true)))
);
}
#[test]
fn is_even() {
let input = "42.is_even()";
assert_eq!(
run(input, &mut HashMap::new()),
Ok(Some(Value::boolean(true)))
);
}
#[test]
fn is_odd() {
let input = "42.is_odd()";
assert_eq!(
run(input, &mut HashMap::new()),
Ok(Some(Value::boolean(false)))
);
}
2024-08-05 18:58:58 +00:00
#[test]
fn length() {
let input = "[1, 2, 3].length()";
2024-08-05 18:58:58 +00:00
assert_eq!(run(input, &mut HashMap::new()), Ok(Some(Value::integer(3))));
2024-08-05 18:58:58 +00:00
}
2024-08-05 18:31:08 +00:00
#[test]
fn list_access() {
let input = "[1, 2, 3].1";
2024-08-05 18:31:08 +00:00
assert_eq!(run(input, &mut HashMap::new()), Ok(Some(Value::integer(2))));
2024-08-05 18:31:08 +00:00
}
2024-08-05 02:15:31 +00:00
#[test]
fn add() {
let input = "1 + 2";
2024-08-05 04:40:51 +00:00
assert_eq!(run(input, &mut HashMap::new()), Ok(Some(Value::integer(3))));
2024-08-05 02:15:31 +00:00
}
2024-08-05 03:11:04 +00:00
#[test]
fn add_multiple() {
2024-08-05 04:40:51 +00:00
let input = "1 + 2 + 3";
2024-08-05 03:11:04 +00:00
2024-08-05 04:40:51 +00:00
assert_eq!(run(input, &mut HashMap::new()), Ok(Some(Value::integer(6))));
2024-08-05 03:11:04 +00:00
}
2024-08-05 02:15:31 +00:00
}