1
0

Implement operator expressions in the VM

This commit is contained in:
Jeff 2024-08-16 06:43:29 -04:00
parent e911853cb5
commit 84429ef187
2 changed files with 230 additions and 40 deletions

View File

@ -114,18 +114,18 @@ impl Value {
} }
} }
pub fn mutate(&self, other: &Value) { pub fn mutate(&self, other: Value) -> Result<(), ValueError> {
let other_data = match other { let mut inner = match self {
Value::Immutable(inner) => inner.as_ref().clone(), Value::Immutable(_) => return Err(ValueError::CannotMutate(self.clone())),
Value::Mutable(inner_locked) => inner_locked.read().unwrap().clone(), Value::Mutable(inner) => inner.write().unwrap(),
}; };
match self { match other {
Value::Mutable(locked) => { Value::Immutable(other) => *inner = other.as_ref().clone(),
*locked.write().unwrap() = other_data; Value::Mutable(other) => *inner = other.read().unwrap().clone(),
}
Value::Immutable(_) => todo!(),
} }
Ok(())
} }
pub fn r#type(&self) -> Type { pub fn r#type(&self) -> Type {
@ -627,6 +627,36 @@ impl Value {
Err(ValueError::CannotModulo(self.clone(), other.clone())) Err(ValueError::CannotModulo(self.clone(), other.clone()))
} }
pub fn equal(&self, other: &Value) -> Value {
let is_equal = match (self, other) {
(Value::Immutable(left), Value::Immutable(right)) => left == right,
(Value::Mutable(left), Value::Mutable(right)) => {
*left.read().unwrap() == *right.read().unwrap()
}
(Value::Immutable(arc), Value::Mutable(arc_locked))
| (Value::Mutable(arc_locked), Value::Immutable(arc)) => {
*arc_locked.read().unwrap() == *arc.as_ref()
}
};
Value::boolean(is_equal)
}
pub fn not_equal(&self, other: &Value) -> Value {
let is_not_equal = match (self, other) {
(Value::Immutable(left), Value::Immutable(right)) => left != right,
(Value::Mutable(left), Value::Mutable(right)) => {
*left.read().unwrap() != *right.read().unwrap()
}
(Value::Immutable(arc), Value::Mutable(arc_locked))
| (Value::Mutable(arc_locked), Value::Immutable(arc)) => {
*arc_locked.read().unwrap() != *arc.as_ref()
}
};
Value::boolean(is_not_equal)
}
pub fn less_than(&self, other: &Value) -> Result<Value, ValueError> { pub fn less_than(&self, other: &Value) -> Result<Value, ValueError> {
match (self, other) { match (self, other) {
(Value::Immutable(left), Value::Immutable(right)) => { (Value::Immutable(left), Value::Immutable(right)) => {

View File

@ -13,9 +13,10 @@ use rayon::iter::{IndexedParallelIterator, IntoParallelIterator, ParallelIterato
use crate::{ use crate::{
ast::{ ast::{
AbstractSyntaxTree, BlockExpression, CallExpression, ElseExpression, FieldAccessExpression, AbstractSyntaxTree, BlockExpression, CallExpression, ComparisonOperator, ElseExpression,
IfExpression, ListExpression, ListIndexExpression, LiteralExpression, LoopExpression, Node, FieldAccessExpression, IfExpression, ListExpression, ListIndexExpression,
OperatorExpression, Statement, LiteralExpression, LogicOperator, LoopExpression, MathOperator, Node, OperatorExpression,
Statement,
}, },
parse, Analyzer, BuiltInFunctionError, Context, DustError, Expression, Identifier, ParseError, parse, Analyzer, BuiltInFunctionError, Context, DustError, Expression, Identifier, ParseError,
Span, Type, Value, ValueError, Span, Type, Value, ValueError,
@ -135,13 +136,26 @@ impl Vm {
Expression::Call(call) => self.run_call(*call.inner), Expression::Call(call) => self.run_call(*call.inner),
Expression::FieldAccess(field_access) => self.run_field_access(*field_access.inner), Expression::FieldAccess(field_access) => self.run_field_access(*field_access.inner),
Expression::Grouped(expression) => self.run_expression(*expression.inner), Expression::Grouped(expression) => self.run_expression(*expression.inner),
Expression::Identifier(identifier) => self.run_identifier(identifier.inner), Expression::Identifier(identifier) => {
let get_value = self.context.get_value(&identifier.inner);
if let Some(value) = get_value {
Ok(Evaluation::Return(Some(value)))
} else {
Err(VmError::UndefinedVariable {
identifier: identifier.inner,
position: identifier.position,
})
}
}
Expression::If(if_expression) => self.run_if(*if_expression.inner), Expression::If(if_expression) => self.run_if(*if_expression.inner),
Expression::List(list_expression) => self.run_list(*list_expression.inner), Expression::List(list_expression) => self.run_list(*list_expression.inner),
Expression::ListIndex(list_index) => self.run_list_index(*list_index.inner), Expression::ListIndex(list_index) => self.run_list_index(*list_index.inner),
Expression::Literal(literal) => self.run_literal(*literal.inner), Expression::Literal(literal) => self.run_literal(*literal.inner),
Expression::Loop(loop_expression) => self.run_loop(*loop_expression.inner), Expression::Loop(loop_expression) => self.run_loop(*loop_expression.inner),
Expression::Operator(_) => todo!(), Expression::Operator(operator_expression) => {
self.run_operator(*operator_expression.inner)
}
Expression::Range(_) => todo!(), Expression::Range(_) => todo!(),
Expression::Struct(_) => todo!(), Expression::Struct(_) => todo!(),
Expression::TupleAccess(_) => todo!(), Expression::TupleAccess(_) => todo!(),
@ -155,12 +169,63 @@ impl Vm {
fn run_operator(&self, operator: OperatorExpression) -> Result<Evaluation, VmError> { fn run_operator(&self, operator: OperatorExpression) -> Result<Evaluation, VmError> {
match operator { match operator {
OperatorExpression::Assignment { assignee, value } => todo!(), OperatorExpression::Assignment { assignee, value } => {
let assignee_position = assignee.position();
let assignee = self
.run_expression(assignee)?
.expect_value(assignee_position)?;
let value_position = value.position();
let value = self.run_expression(value)?.expect_value(value_position)?;
assignee.mutate(value);
Ok(Evaluation::Return(None))
}
OperatorExpression::Comparison { OperatorExpression::Comparison {
left, left,
operator, operator,
right, right,
} => todo!(), } => {
let left_position = left.position();
let left_value = self.run_expression(left)?.expect_value(left_position)?;
let right_position = right.position();
let right_value = self.run_expression(right)?.expect_value(right_position)?;
let outcome =
match operator.inner {
ComparisonOperator::Equal => left_value.equal(&right_value),
ComparisonOperator::NotEqual => left_value.not_equal(&right_value),
ComparisonOperator::GreaterThan => left_value
.greater_than(&right_value)
.map_err(|error| VmError::ValueError {
error,
left_position,
right_position,
})?,
ComparisonOperator::GreaterThanOrEqual => left_value
.greater_than_or_equal(&right_value)
.map_err(|error| VmError::ValueError {
error,
left_position,
right_position,
})?,
ComparisonOperator::LessThan => left_value
.less_than(&right_value)
.map_err(|error| VmError::ValueError {
error,
left_position,
right_position,
})?,
ComparisonOperator::LessThanOrEqual => left_value
.less_than_or_equal(&right_value)
.map_err(|error| VmError::ValueError {
error,
left_position,
right_position,
})?,
};
Ok(Evaluation::Return(Some(outcome)))
}
OperatorExpression::CompoundAssignment { OperatorExpression::CompoundAssignment {
assignee, assignee,
operator, operator,
@ -173,12 +238,47 @@ impl Vm {
left, left,
operator, operator,
right, right,
} => todo!(), } => {
let left_position = left.position();
let left_value = self.run_expression(left)?.expect_value(left_position)?;
let right_position = right.position();
let right_value = self.run_expression(right)?.expect_value(right_position)?;
let outcome = match operator.inner {
MathOperator::Add => left_value.add(&right_value),
MathOperator::Subtract => left_value.subtract(&right_value),
MathOperator::Multiply => left_value.multiply(&right_value),
MathOperator::Divide => left_value.divide(&right_value),
MathOperator::Modulo => left_value.modulo(&right_value),
}
.map_err(|value_error| VmError::ValueError {
error: value_error,
left_position,
right_position,
})?;
Ok(Evaluation::Return(Some(outcome)))
}
OperatorExpression::Logic { OperatorExpression::Logic {
left, left,
operator, operator,
right, right,
} => todo!(), } => {
let left_position = left.position();
let left_value = self.run_expression(left)?.expect_value(left_position)?;
let right_position = right.position();
let right_value = self.run_expression(right)?.expect_value(right_position)?;
let outcome = match operator.inner {
LogicOperator::And => left_value.and(&right_value),
LogicOperator::Or => left_value.or(&right_value),
}
.map_err(|value_error| VmError::ValueError {
error: value_error,
left_position,
right_position,
})?;
Ok(Evaluation::Return(Some(outcome)))
}
} }
} }
@ -267,7 +367,7 @@ impl Vm {
function function
.call(None, Some(value_arguments), &context) .call(None, Some(value_arguments), &context)
.map(|value_option| Evaluation::Return(value_option)) .map(Evaluation::Return)
} }
fn run_field_access(&self, field_access: FieldAccessExpression) -> Result<Evaluation, VmError> { fn run_field_access(&self, field_access: FieldAccessExpression) -> Result<Evaluation, VmError> {
@ -285,16 +385,6 @@ impl Vm {
Ok(Evaluation::Return(container_value.get_field(&field.inner))) Ok(Evaluation::Return(container_value.get_field(&field.inner)))
} }
fn run_identifier(&self, identifier: Identifier) -> Result<Evaluation, VmError> {
let value_option = self.context.get_value(&identifier);
if let Some(value) = value_option {
Ok(Evaluation::Return(Some(value)))
} else {
Err(VmError::UndefinedVariable { identifier })
}
}
fn run_list(&self, list_expression: ListExpression) -> Result<Evaluation, VmError> { fn run_list(&self, list_expression: ListExpression) -> Result<Evaluation, VmError> {
match list_expression { match list_expression {
ListExpression::AutoFill { ListExpression::AutoFill {
@ -336,19 +426,33 @@ impl Vm {
fn run_block(&self, block: BlockExpression) -> Result<Evaluation, VmError> { fn run_block(&self, block: BlockExpression) -> Result<Evaluation, VmError> {
match block { match block {
BlockExpression::Async(statements) => { BlockExpression::Async(statements) => {
let expected_return = statements.last().unwrap().expected_type();
let final_result = Arc::new(Mutex::new(None)); let final_result = Arc::new(Mutex::new(None));
let statements_length = statements.len();
let error_option = statements let error_option =
statements
.into_par_iter() .into_par_iter()
.enumerate() .enumerate()
.find_map_any(|statement| self.run_statement(statement).err()); .find_map_any(|(i, statement)| {
let evaluation_result = self.run_statement(statement);
match evaluation_result {
Ok(evaluation) => {
if i == statements_length - 1 {
let mut final_result = final_result.lock().unwrap();
*final_result = evaluation;
}
None
}
Err(error) => Some(error),
}
});
if let Some(error) = error_option { if let Some(error) = error_option {
Err(error) Err(error)
} else { } else {
Ok(Evaluation::Return(None)) Ok(Evaluation::Return(final_result.lock().unwrap().clone()))
} }
} }
BlockExpression::Sync(statements) => { BlockExpression::Sync(statements) => {
@ -446,7 +550,8 @@ pub enum VmError {
}, },
ValueError { ValueError {
error: ValueError, error: ValueError,
position: Span, left_position: Span,
right_position: Span,
}, },
// Anaylsis Failures // Anaylsis Failures
@ -492,6 +597,7 @@ pub enum VmError {
}, },
UndefinedVariable { UndefinedVariable {
identifier: Identifier, identifier: Identifier,
position: Span,
}, },
UndefinedProperty { UndefinedProperty {
value: Value, value: Value,
@ -501,6 +607,36 @@ pub enum VmError {
}, },
} }
impl VmError {
pub fn position(&self) -> Span {
match self {
Self::ParseError(parse_error) => parse_error.position(),
Self::Trace { position, .. } => *position,
Self::ValueError {
left_position,
right_position,
..
} => (left_position.0, right_position.1),
Self::BuiltInFunctionError { position, .. } => *position,
Self::CannotMutate { position, .. } => *position,
Self::ExpectedBoolean { position } => *position,
Self::ExpectedIdentifier { position } => *position,
Self::ExpectedIntegerOrRange { position } => *position,
Self::ExpectedIdentifierOrString { position } => *position,
Self::ExpectedInteger { position } => *position,
Self::ExpectedNumber { position } => *position,
Self::ExpectedMap { position } => *position,
Self::ExpectedFunction { position, .. } => *position,
Self::ExpectedList { position } => *position,
Self::ExpectedValue { position } => *position,
Self::UndefinedVariable { position, .. } => *position,
Self::UndefinedProperty {
property_position, ..
} => *property_position,
}
}
}
impl From<ParseError> for VmError { impl From<ParseError> for VmError {
fn from(error: ParseError) -> Self { fn from(error: ParseError) -> Self {
Self::ParseError(error) Self::ParseError(error)
@ -518,7 +654,17 @@ impl Display for VmError {
position, error position, error
) )
} }
Self::ValueError { error, .. } => write!(f, "{}", error), Self::ValueError {
error,
left_position,
right_position,
} => {
write!(
f,
"Value error with values at positions: {:?} and {:?} {}",
left_position, right_position, error
)
}
Self::CannotMutate { value, .. } => { Self::CannotMutate { value, .. } => {
write!(f, "Cannot mutate immutable value {}", value) write!(f, "Cannot mutate immutable value {}", value)
} }
@ -571,8 +717,15 @@ impl Display for VmError {
Self::ExpectedValue { position } => { Self::ExpectedValue { position } => {
write!(f, "Expected a value at position: {:?}", position) write!(f, "Expected a value at position: {:?}", position)
} }
Self::UndefinedVariable { identifier } => { Self::UndefinedVariable {
write!(f, "Undefined identifier: {}", identifier) identifier,
position,
} => {
write!(
f,
"Undefined variable {} at position: {:?}",
identifier, position
)
} }
Self::UndefinedProperty { Self::UndefinedProperty {
value, property, .. value, property, ..
@ -816,6 +969,13 @@ mod tests {
assert_eq!(run(input), Ok(Some(Value::integer(2)))); assert_eq!(run(input), Ok(Some(Value::integer(2))));
} }
#[test]
fn and() {
let input = "true && true";
assert_eq!(run(input), Ok(Some(Value::boolean(true))));
}
#[test] #[test]
fn or() { fn or() {
let input = "true || false"; let input = "true || false";