1
0

Prepare for value overhaul

This commit is contained in:
Jeff 2024-08-16 11:21:20 -04:00
parent 7d721beb31
commit 8bff39a7db
5 changed files with 261 additions and 95 deletions

View File

@ -168,8 +168,12 @@ impl<'a> Analyzer<'a> {
self.analyze_expression(modifier)?; self.analyze_expression(modifier)?;
} }
OperatorExpression::ErrorPropagation(_) => todo!(), OperatorExpression::ErrorPropagation(_) => todo!(),
OperatorExpression::Negation(_) => todo!(), OperatorExpression::Negation(expression) => {
OperatorExpression::Not(_) => todo!(), self.analyze_expression(expression)?;
}
OperatorExpression::Not(expression) => {
self.analyze_expression(expression)?;
}
OperatorExpression::Math { left, right, .. } => { OperatorExpression::Math { left, right, .. } => {
self.analyze_expression(left)?; self.analyze_expression(left)?;
self.analyze_expression(right)?; self.analyze_expression(right)?;

View File

@ -22,7 +22,7 @@ pub enum Expression {
Literal(Node<Box<LiteralExpression>>), Literal(Node<Box<LiteralExpression>>),
Loop(Node<Box<LoopExpression>>), Loop(Node<Box<LoopExpression>>),
Operator(Node<Box<OperatorExpression>>), Operator(Node<Box<OperatorExpression>>),
Range(Node<Box<Range>>), Range(Node<Box<RangeExpression>>),
Struct(Node<Box<StructExpression>>), Struct(Node<Box<StructExpression>>),
TupleAccess(Node<Box<TupleAccess>>), TupleAccess(Node<Box<TupleAccess>>),
} }
@ -32,8 +32,18 @@ impl Expression {
Self::Operator(Node::new(Box::new(operator_expression), position)) Self::Operator(Node::new(Box::new(operator_expression), position))
} }
pub fn range(start: Expression, end: Expression, position: Span) -> Self { pub fn exclusive_range(start: Expression, end: Expression, position: Span) -> Self {
Self::Range(Node::new(Box::new(Range { start, end }), position)) Self::Range(Node::new(
Box::new(RangeExpression::Exclusive { start, end }),
position,
))
}
pub fn inclusive_range(start: Expression, end: Expression, position: Span) -> Self {
Self::Range(Node::new(
Box::new(RangeExpression::Inclusive { start, end }),
position,
))
} }
pub fn call(invoker: Expression, arguments: Vec<Expression>, position: Span) -> Self { pub fn call(invoker: Expression, arguments: Vec<Expression>, position: Span) -> Self {
@ -391,14 +401,17 @@ impl Display for TupleAccess {
} }
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct Range { pub enum RangeExpression {
pub start: Expression, Exclusive { start: Expression, end: Expression },
pub end: Expression, Inclusive { start: Expression, end: Expression },
} }
impl Display for Range { impl Display for RangeExpression {
fn fmt(&self, f: &mut Formatter) -> fmt::Result { fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "{}..{}", self.start, self.end) match self {
RangeExpression::Exclusive { start, end } => write!(f, "{}..{}", start, end),
RangeExpression::Inclusive { start, end } => write!(f, "{}..={}", start, end),
}
} }
} }

View File

@ -633,7 +633,7 @@ impl<'src> Parser<'src> {
let end = self.parse_expression(operator_precedence)?; let end = self.parse_expression(operator_precedence)?;
let position = (left_start, end.position().1); let position = (left_start, end.position().1);
return Ok(Expression::range(left, end, position)); return Ok(Expression::exclusive_range(left, end, position));
} }
if let Token::Minus | Token::Plus | Token::Star | Token::Slash | Token::Percent = if let Token::Minus | Token::Plus | Token::Star | Token::Slash | Token::Percent =
@ -1335,7 +1335,7 @@ mod tests {
assert_eq!( assert_eq!(
parse(source), parse(source),
Ok(AbstractSyntaxTree::with_statements([ Ok(AbstractSyntaxTree::with_statements([
Statement::Expression(Expression::range( Statement::Expression(Expression::exclusive_range(
Expression::literal(LiteralExpression::Integer(0), (0, 1)), Expression::literal(LiteralExpression::Integer(0), (0, 1)),
Expression::literal(LiteralExpression::Integer(42), (3, 5)), Expression::literal(LiteralExpression::Integer(42), (3, 5)),
(0, 5) (0, 5)

View File

@ -4,7 +4,7 @@ use std::{
collections::BTreeMap, collections::BTreeMap,
error::Error, error::Error,
fmt::{self, Display, Formatter}, fmt::{self, Display, Formatter},
ops::Range, ops::{Range, RangeInclusive},
sync::{Arc, RwLock, RwLockWriteGuard}, sync::{Arc, RwLock, RwLockWriteGuard},
}; };
@ -80,7 +80,7 @@ impl Value {
} }
pub fn range(range: Range<i64>) -> Self { pub fn range(range: Range<i64>) -> Self {
Value::Immutable(Arc::new(ValueData::Range(range))) Value::Immutable(Arc::new(ValueData::RangeExclusive(range)))
} }
pub fn string<T: ToString>(to_string: T) -> Self { pub fn string<T: ToString>(to_string: T) -> Self {
@ -1137,7 +1137,8 @@ pub enum ValueData {
Integer(i64), Integer(i64),
List(Vec<Value>), List(Vec<Value>),
Map(BTreeMap<Identifier, Value>), Map(BTreeMap<Identifier, Value>),
Range(Range<i64>), RangeExclusive(Range<Value>),
RangeInclusive(RangeInclusive<Value>),
String(String), String(String),
Struct(Struct), Struct(Struct),
} }
@ -1172,7 +1173,8 @@ impl ValueData {
Type::Map(type_map) Type::Map(type_map)
} }
ValueData::Range(_) => Type::Range, ValueData::RangeExclusive(_) => Type::Range,
ValueData::RangeInclusive(_) => Type::Range,
ValueData::String(_) => Type::String, ValueData::String(_) => Type::String,
ValueData::Struct(r#struct) => match r#struct { ValueData::Struct(r#struct) => match r#struct {
Struct::Unit { name } => Type::Struct(StructType::Unit { name: name.clone() }), Struct::Unit { name } => Type::Struct(StructType::Unit { name: name.clone() }),
@ -1196,12 +1198,12 @@ impl ValueData {
} }
} }
fn get_index(&self, index: usize) -> Option<Value> { fn get_index(&self, index: Value) -> Option<Value> {
if let ValueData::List(list) = self { if let ValueData::List(list) = self {
return list.get(index).cloned(); return list.get(index).cloned();
} }
if let ValueData::Range(range) = self { if let ValueData::RangeExclusive(range) = self {
if range.contains(&(index as i64)) { if range.contains(&(index as i64)) {
return Some(Value::integer(index as i64)); return Some(Value::integer(index as i64));
} }
@ -1271,7 +1273,8 @@ impl Display for ValueData {
write!(f, " }}") write!(f, " }}")
} }
ValueData::Range(range) => write!(f, "{}..{}", range.start, range.end), ValueData::RangeExclusive(range) => write!(f, "{}..{}", range.start, range.end),
ValueData::RangeInclusive(range) => write!(f, "{}..={}", range.start(), range.end()),
ValueData::String(string) => write!(f, "{string}"), ValueData::String(string) => write!(f, "{string}"),
ValueData::Struct(r#struct) => write!(f, "{struct}"), ValueData::Struct(r#struct) => write!(f, "{struct}"),
} }
@ -1303,7 +1306,7 @@ impl Ord for ValueData {
(List(_), _) => Ordering::Greater, (List(_), _) => Ordering::Greater,
(Map(left), Map(right)) => left.cmp(right), (Map(left), Map(right)) => left.cmp(right),
(Map(_), _) => Ordering::Greater, (Map(_), _) => Ordering::Greater,
(Range(left), Range(right)) => { (RangeExclusive(left), RangeExclusive(right)) => {
let start_cmp = left.start.cmp(&right.start); let start_cmp = left.start.cmp(&right.start);
if start_cmp.is_eq() { if start_cmp.is_eq() {
@ -1312,7 +1315,17 @@ impl Ord for ValueData {
start_cmp start_cmp
} }
} }
(Range(_), _) => Ordering::Greater, (RangeExclusive(_), _) => Ordering::Greater,
(RangeInclusive(left), RangeInclusive(right)) => {
let start_cmp = left.start().cmp(right.start());
if start_cmp.is_eq() {
left.end().cmp(right.end())
} else {
start_cmp
}
}
(RangeInclusive(_), _) => Ordering::Greater,
(String(left), String(right)) => left.cmp(right), (String(left), String(right)) => left.cmp(right),
(String(_), _) => Ordering::Greater, (String(_), _) => Ordering::Greater,
(Struct(left), Struct(right)) => left.cmp(right), (Struct(left), Struct(right)) => left.cmp(right),
@ -1349,7 +1362,7 @@ impl Serialize for ValueData {
map_ser.end() map_ser.end()
} }
ValueData::Range(range) => { ValueData::RangeExclusive(range) => {
let mut tuple_ser = serializer.serialize_tuple(2)?; let mut tuple_ser = serializer.serialize_tuple(2)?;
tuple_ser.serialize_element(&range.start)?; tuple_ser.serialize_element(&range.start)?;
@ -1357,6 +1370,14 @@ impl Serialize for ValueData {
tuple_ser.end() tuple_ser.end()
} }
ValueData::RangeInclusive(range) => {
let mut tuple_ser = serializer.serialize_tuple(2)?;
tuple_ser.serialize_element(&range.start())?;
tuple_ser.serialize_element(&range.end())?;
tuple_ser.end()
}
ValueData::String(string) => serializer.serialize_str(string), ValueData::String(string) => serializer.serialize_str(string),
ValueData::Struct(r#struct) => r#struct.serialize(serializer), ValueData::Struct(r#struct) => r#struct.serialize(serializer),
} }
@ -1626,7 +1647,7 @@ impl Function {
if let (Some(value_parameters), Some(value_arguments)) = if let (Some(value_parameters), Some(value_arguments)) =
(&self.value_parameters, value_arguments) (&self.value_parameters, value_arguments)
{ {
for ((identifier, _), value) in value_parameters.into_iter().zip(value_arguments) { for ((identifier, _), value) in value_parameters.iter().zip(value_arguments) {
new_context.set_value(identifier.clone(), value); new_context.set_value(identifier.clone(), value);
} }
} }
@ -1743,6 +1764,7 @@ pub enum ValueError {
CannotDivide(Value, Value), CannotDivide(Value, Value),
CannotGreaterThan(Value, Value), CannotGreaterThan(Value, Value),
CannotGreaterThanOrEqual(Value, Value), CannotGreaterThanOrEqual(Value, Value),
CannotIndex { value: Value, index: Value },
CannotLessThan(Value, Value), CannotLessThan(Value, Value),
CannotLessThanOrEqual(Value, Value), CannotLessThanOrEqual(Value, Value),
CannotMakeMutable, CannotMakeMutable,
@ -1770,6 +1792,9 @@ impl Display for ValueError {
ValueError::CannotDivide(left, right) => { ValueError::CannotDivide(left, right) => {
write!(f, "Cannot divide {} by {}", left, right) write!(f, "Cannot divide {} by {}", left, right)
} }
ValueError::CannotIndex { value, index } => {
write!(f, "Cannot index {} with {}", value, index)
}
ValueError::CannotModulo(left, right) => { ValueError::CannotModulo(left, right) => {
write!(f, "Cannot modulo {} by {}", left, right) write!(f, "Cannot modulo {} by {}", left, right)
} }

View File

@ -6,6 +6,7 @@
//! - `Vm` struct that can be used to run an abstract syntax tree //! - `Vm` struct that can be used to run an abstract syntax tree
use std::{ use std::{
fmt::{self, Display, Formatter}, fmt::{self, Display, Formatter},
ops::Range,
sync::{Arc, Mutex}, sync::{Arc, Mutex},
}; };
@ -16,7 +17,7 @@ use crate::{
AbstractSyntaxTree, BlockExpression, CallExpression, ComparisonOperator, ElseExpression, AbstractSyntaxTree, BlockExpression, CallExpression, ComparisonOperator, ElseExpression,
FieldAccessExpression, IfExpression, LetStatement, ListExpression, ListIndexExpression, FieldAccessExpression, IfExpression, LetStatement, ListExpression, ListIndexExpression,
LiteralExpression, LogicOperator, LoopExpression, MathOperator, Node, OperatorExpression, LiteralExpression, LogicOperator, LoopExpression, MathOperator, Node, OperatorExpression,
Statement, RangeExpression, Statement,
}, },
parse, Analyzer, BuiltInFunctionError, Context, DustError, Expression, Identifier, ParseError, parse, Analyzer, BuiltInFunctionError, Context, DustError, Expression, Identifier, ParseError,
Span, Value, ValueError, Span, Value, ValueError,
@ -93,32 +94,38 @@ impl Vm {
let mut previous_value = None; let mut previous_value = None;
while let Some(statement) = self.abstract_tree.statements.pop_front() { while let Some(statement) = self.abstract_tree.statements.pop_front() {
previous_value = self.run_statement(statement)?; previous_value = self.run_statement(statement, true)?;
} }
Ok(previous_value) Ok(previous_value)
} }
fn run_statement(&self, statement: Statement) -> Result<Option<Value>, VmError> { fn run_statement(
&self,
statement: Statement,
collect_garbage: bool,
) -> Result<Option<Value>, VmError> {
let position = statement.position(); let position = statement.position();
let result = match statement { let result = match statement {
Statement::Expression(expression) => self Statement::Expression(expression) => self
.run_expression(expression) .run_expression(expression, collect_garbage)
.map(|evaluation| evaluation.value()), .map(|evaluation| evaluation.value()),
Statement::ExpressionNullified(expression) => { Statement::ExpressionNullified(expression) => {
self.run_expression(expression.inner)?; self.run_expression(expression.inner, collect_garbage)?;
Ok(None) Ok(None)
} }
Statement::Let(let_statement) => { Statement::Let(let_statement) => {
self.run_let_statement(let_statement.inner)?; self.run_let_statement(let_statement.inner, collect_garbage)?;
Ok(None) Ok(None)
} }
Statement::StructDefinition(_) => todo!(), Statement::StructDefinition(_) => todo!(),
}; };
self.context.collect_garbage(position.1); if collect_garbage {
self.context.collect_garbage(position.1);
}
result.map_err(|error| VmError::Trace { result.map_err(|error| VmError::Trace {
error: Box::new(error), error: Box::new(error),
@ -126,11 +133,17 @@ impl Vm {
}) })
} }
fn run_let_statement(&self, let_statement: LetStatement) -> Result<(), VmError> { fn run_let_statement(
&self,
let_statement: LetStatement,
collect_garbage: bool,
) -> Result<(), VmError> {
match let_statement { match let_statement {
LetStatement::Let { identifier, value } => { LetStatement::Let { identifier, value } => {
let value_position = value.position(); let value_position = value.position();
let value = self.run_expression(value)?.expect_value(value_position)?; let value = self
.run_expression(value, collect_garbage)?
.expect_value(value_position)?;
self.context.set_value(identifier.inner, value); self.context.set_value(identifier.inner, value);
@ -138,7 +151,9 @@ impl Vm {
} }
LetStatement::LetMut { identifier, value } => { LetStatement::LetMut { identifier, value } => {
let value_position = value.position(); let value_position = value.position();
let value = self.run_expression(value)?.expect_value(value_position)?; let value = self
.run_expression(value, collect_garbage)?
.expect_value(value_position)?;
let mutable_value = value.to_mut().map_err(|error| VmError::ValueError { let mutable_value = value.to_mut().map_err(|error| VmError::ValueError {
error, error,
left_position: identifier.position, left_position: identifier.position,
@ -154,13 +169,21 @@ impl Vm {
} }
} }
fn run_expression(&self, expression: Expression) -> Result<Evaluation, VmError> { fn run_expression(
&self,
expression: Expression,
collect_garbage: bool,
) -> Result<Evaluation, VmError> {
let position = expression.position(); let position = expression.position();
let evaluation_result = match expression { let evaluation_result = match expression {
Expression::Block(Node { inner, .. }) => self.run_block(*inner), Expression::Block(Node { inner, .. }) => self.run_block(*inner, collect_garbage),
Expression::Call(call) => self.run_call(*call.inner), Expression::Call(call) => self.run_call(*call.inner, collect_garbage),
Expression::FieldAccess(field_access) => self.run_field_access(*field_access.inner), Expression::FieldAccess(field_access) => {
Expression::Grouped(expression) => self.run_expression(*expression.inner), self.run_field_access(*field_access.inner, collect_garbage)
}
Expression::Grouped(expression) => {
self.run_expression(*expression.inner, collect_garbage)
}
Expression::Identifier(identifier) => { Expression::Identifier(identifier) => {
let get_value = self.context.get_value(&identifier.inner); let get_value = self.context.get_value(&identifier.inner);
@ -173,15 +196,33 @@ impl Vm {
}) })
} }
} }
Expression::If(if_expression) => self.run_if(*if_expression.inner), Expression::If(if_expression) => self.run_if(*if_expression.inner, collect_garbage),
Expression::List(list_expression) => self.run_list(*list_expression.inner), Expression::List(list_expression) => {
Expression::ListIndex(list_index) => self.run_list_index(*list_index.inner), self.run_list(*list_expression.inner, collect_garbage)
}
Expression::ListIndex(list_index) => {
self.run_list_index(*list_index.inner, collect_garbage)
}
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(operator_expression) => { Expression::Operator(operator_expression) => {
self.run_operator(*operator_expression.inner) self.run_operator(*operator_expression.inner, collect_garbage)
} }
Expression::Range(_) => todo!(), Expression::Range(range_expression) => match range_expression.inner.as_ref() {
RangeExpression::Exclusive { start, end } => {
let start_position = start.position();
let start = self
.run_expression(*start.inner, collect_garbage)?
.expect_value(start_position)?;
let end_position = end.position();
let end = self
.run_expression(*end.inner, collect_garbage)?
.expect_value(end_position)?;
Ok(Evaluation::Return(Some(Value::range(start..end))))
}
RangeExpression::Inclusive { start, end } => todo!(),
},
Expression::Struct(_) => todo!(), Expression::Struct(_) => todo!(),
Expression::TupleAccess(_) => todo!(), Expression::TupleAccess(_) => todo!(),
}; };
@ -192,15 +233,21 @@ impl Vm {
}) })
} }
fn run_operator(&self, operator: OperatorExpression) -> Result<Evaluation, VmError> { fn run_operator(
&self,
operator: OperatorExpression,
collect_garbage: bool,
) -> Result<Evaluation, VmError> {
match operator { match operator {
OperatorExpression::Assignment { assignee, value } => { OperatorExpression::Assignment { assignee, value } => {
let assignee_position = assignee.position(); let assignee_position = assignee.position();
let assignee = self let assignee = self
.run_expression(assignee)? .run_expression(assignee, collect_garbage)?
.expect_value(assignee_position)?; .expect_value(assignee_position)?;
let value_position = value.position(); let value_position = value.position();
let value = self.run_expression(value)?.expect_value(value_position)?; let value = self
.run_expression(value, collect_garbage)?
.expect_value(value_position)?;
assignee assignee
.mutate(value) .mutate(value)
@ -218,9 +265,13 @@ impl Vm {
right, right,
} => { } => {
let left_position = left.position(); let left_position = left.position();
let left_value = self.run_expression(left)?.expect_value(left_position)?; let left_value = self
.run_expression(left, collect_garbage)?
.expect_value(left_position)?;
let right_position = right.position(); let right_position = right.position();
let right_value = self.run_expression(right)?.expect_value(right_position)?; let right_value = self
.run_expression(right, collect_garbage)?
.expect_value(right_position)?;
let outcome = let outcome =
match operator.inner { match operator.inner {
ComparisonOperator::Equal => left_value.equal(&right_value), ComparisonOperator::Equal => left_value.equal(&right_value),
@ -264,11 +315,11 @@ impl Vm {
} => { } => {
let assignee_position = assignee.position(); let assignee_position = assignee.position();
let assignee = self let assignee = self
.run_expression(assignee)? .run_expression(assignee, collect_garbage)?
.expect_value(assignee_position)?; .expect_value(assignee_position)?;
let modifier_position = modifier.position(); let modifier_position = modifier.position();
let modifier = self let modifier = self
.run_expression(modifier)? .run_expression(modifier, collect_garbage)?
.expect_value(modifier_position)?; .expect_value(modifier_position)?;
match operator.inner { match operator.inner {
@ -287,17 +338,43 @@ impl Vm {
Ok(Evaluation::Return(None)) Ok(Evaluation::Return(None))
} }
OperatorExpression::ErrorPropagation(_) => todo!(), OperatorExpression::ErrorPropagation(_) => todo!(),
OperatorExpression::Negation(_) => todo!(), OperatorExpression::Negation(expression) => {
OperatorExpression::Not(_) => todo!(), let position = expression.position();
let value = self
.run_expression(expression, collect_garbage)?
.expect_value(position)?;
let integer = value
.as_integer()
.ok_or(VmError::ExpectedBoolean { position })?;
let negated = Value::integer(-integer);
Ok(Evaluation::Return(Some(negated)))
}
OperatorExpression::Not(expression) => {
let position = expression.position();
let value = self
.run_expression(expression, collect_garbage)?
.expect_value(position)?;
let boolean = value
.as_boolean()
.ok_or(VmError::ExpectedBoolean { position })?;
let not = Value::boolean(!boolean);
Ok(Evaluation::Return(Some(not)))
}
OperatorExpression::Math { OperatorExpression::Math {
left, left,
operator, operator,
right, right,
} => { } => {
let left_position = left.position(); let left_position = left.position();
let left_value = self.run_expression(left)?.expect_value(left_position)?; let left_value = self
.run_expression(left, collect_garbage)?
.expect_value(left_position)?;
let right_position = right.position(); let right_position = right.position();
let right_value = self.run_expression(right)?.expect_value(right_position)?; let right_value = self
.run_expression(right, collect_garbage)?
.expect_value(right_position)?;
let outcome = match operator.inner { let outcome = match operator.inner {
MathOperator::Add => left_value.add(&right_value), MathOperator::Add => left_value.add(&right_value),
MathOperator::Subtract => left_value.subtract(&right_value), MathOperator::Subtract => left_value.subtract(&right_value),
@ -319,9 +396,13 @@ impl Vm {
right, right,
} => { } => {
let left_position = left.position(); let left_position = left.position();
let left_value = self.run_expression(left)?.expect_value(left_position)?; let left_value = self
.run_expression(left, collect_garbage)?
.expect_value(left_position)?;
let right_position = right.position(); let right_position = right.position();
let right_value = self.run_expression(right)?.expect_value(right_position)?; let right_value = self
.run_expression(right, collect_garbage)?
.expect_value(right_position)?;
let outcome = match operator.inner { let outcome = match operator.inner {
LogicOperator::And => left_value.and(&right_value), LogicOperator::And => left_value.and(&right_value),
LogicOperator::Or => left_value.or(&right_value), LogicOperator::Or => left_value.or(&right_value),
@ -340,9 +421,22 @@ impl Vm {
fn run_loop(&self, loop_expression: LoopExpression) -> Result<Evaluation, VmError> { fn run_loop(&self, loop_expression: LoopExpression) -> Result<Evaluation, VmError> {
match loop_expression { match loop_expression {
LoopExpression::Infinite { block } => loop { LoopExpression::Infinite { block } => loop {
self.run_expression(Expression::block(block.inner.clone(), block.position))?; self.run_block(block.inner.clone(), false)?;
}, },
LoopExpression::While { condition, block } => todo!(), LoopExpression::While { condition, block } => {
while self
.run_expression(condition.clone(), false)?
.expect_value(condition.position())?
.as_boolean()
.ok_or_else(|| VmError::ExpectedBoolean {
position: condition.position(),
})?
{
self.run_block(block.inner.clone(), false)?;
}
Ok(Evaluation::Return(None))
}
LoopExpression::For { LoopExpression::For {
identifier, identifier,
iterator, iterator,
@ -363,14 +457,22 @@ impl Vm {
Ok(Evaluation::Return(Some(value))) Ok(Evaluation::Return(Some(value)))
} }
fn run_list_index(&self, list_index: ListIndexExpression) -> Result<Evaluation, VmError> { fn run_list_index(
&self,
list_index: ListIndexExpression,
collect_garbage: bool,
) -> Result<Evaluation, VmError> {
let ListIndexExpression { list, index } = list_index; let ListIndexExpression { list, index } = list_index;
let list_position = list.position(); let list_position = list.position();
let list_value = self.run_expression(list)?.expect_value(list_position)?; let list_value = self
.run_expression(list, collect_garbage)?
.expect_value(list_position)?;
let index_position = index.position(); let index_position = index.position();
let index_value = self.run_expression(index)?.expect_value(index_position)?; let index_value = self
.run_expression(index, collect_garbage)?
.expect_value(index_position)?;
let index = if let Some(index) = index_value.as_integer() { let index = if let Some(index) = index_value.as_integer() {
index as usize index as usize
@ -385,17 +487,22 @@ impl Vm {
Ok(Evaluation::Return(value_option)) Ok(Evaluation::Return(value_option))
} }
fn run_call(&self, call_expression: CallExpression) -> Result<Evaluation, VmError> { fn run_call(
&self,
call_expression: CallExpression,
collect_garbage: bool,
) -> Result<Evaluation, VmError> {
let CallExpression { invoker, arguments } = call_expression; let CallExpression { invoker, arguments } = call_expression;
let invoker_position = invoker.position(); let invoker_position = invoker.position();
let invoker_value = if let Some(value) = self.run_expression(invoker)?.value() { let invoker_value =
value if let Some(value) = self.run_expression(invoker, collect_garbage)?.value() {
} else { value
return Err(VmError::ExpectedValue { } else {
position: invoker_position, return Err(VmError::ExpectedValue {
}); position: invoker_position,
}; });
};
let function = if let Some(function) = invoker_value.as_function() { let function = if let Some(function) = invoker_value.as_function() {
function function
@ -411,7 +518,7 @@ impl Vm {
for argument in arguments { for argument in arguments {
let position = argument.position(); let position = argument.position();
if let Some(value) = self.run_expression(argument)?.value() { if let Some(value) = self.run_expression(argument, collect_garbage)?.value() {
value_arguments.push(value); value_arguments.push(value);
} else { } else {
return Err(VmError::ExpectedValue { position }); return Err(VmError::ExpectedValue { position });
@ -425,22 +532,31 @@ impl Vm {
.map(Evaluation::Return) .map(Evaluation::Return)
} }
fn run_field_access(&self, field_access: FieldAccessExpression) -> Result<Evaluation, VmError> { fn run_field_access(
&self,
field_access: FieldAccessExpression,
collect_garbage: bool,
) -> Result<Evaluation, VmError> {
let FieldAccessExpression { container, field } = field_access; let FieldAccessExpression { container, field } = field_access;
let container_position = container.position(); let container_position = container.position();
let container_value = if let Some(value) = self.run_expression(container)?.value() { let container_value =
value if let Some(value) = self.run_expression(container, collect_garbage)?.value() {
} else { value
return Err(VmError::ExpectedValue { } else {
position: container_position, return Err(VmError::ExpectedValue {
}); position: container_position,
}; });
};
Ok(Evaluation::Return(container_value.get_field(&field.inner))) Ok(Evaluation::Return(container_value.get_field(&field.inner)))
} }
fn run_list(&self, list_expression: ListExpression) -> Result<Evaluation, VmError> { fn run_list(
&self,
list_expression: ListExpression,
collect_garbage: bool,
) -> Result<Evaluation, VmError> {
match list_expression { match list_expression {
ListExpression::AutoFill { ListExpression::AutoFill {
repeat_operand, repeat_operand,
@ -448,14 +564,14 @@ impl Vm {
} => { } => {
let position = length_operand.position(); let position = length_operand.position();
let length = self let length = self
.run_expression(length_operand)? .run_expression(length_operand, collect_garbage)?
.expect_value(position)? .expect_value(position)?
.as_integer() .as_integer()
.ok_or(VmError::ExpectedInteger { position })?; .ok_or(VmError::ExpectedInteger { position })?;
let position = repeat_operand.position(); let position = repeat_operand.position();
let value = self let value = self
.run_expression(repeat_operand)? .run_expression(repeat_operand, collect_garbage)?
.expect_value(position)?; .expect_value(position)?;
Ok(Evaluation::Return(Some(Value::list(vec![ Ok(Evaluation::Return(Some(Value::list(vec![
@ -468,7 +584,9 @@ impl Vm {
for expression in expressions { for expression in expressions {
let position = expression.position(); let position = expression.position();
let value = self.run_expression(expression)?.expect_value(position)?; let value = self
.run_expression(expression, collect_garbage)?
.expect_value(position)?;
values.push(value); values.push(value);
} }
@ -478,7 +596,11 @@ impl Vm {
} }
} }
fn run_block(&self, block: BlockExpression) -> Result<Evaluation, VmError> { fn run_block(
&self,
block: BlockExpression,
collect_garbage: bool,
) -> Result<Evaluation, VmError> {
match block { match block {
BlockExpression::Async(statements) => { BlockExpression::Async(statements) => {
let final_result = Arc::new(Mutex::new(None)); let final_result = Arc::new(Mutex::new(None));
@ -488,7 +610,7 @@ impl Vm {
.into_par_iter() .into_par_iter()
.enumerate() .enumerate()
.find_map_any(|(i, statement)| { .find_map_any(|(i, statement)| {
let evaluation_result = self.run_statement(statement); let evaluation_result = self.run_statement(statement, false);
match evaluation_result { match evaluation_result {
Ok(evaluation) => { Ok(evaluation) => {
@ -516,7 +638,7 @@ impl Vm {
for statement in statements { for statement in statements {
let position = statement.position(); let position = statement.position();
previous_value = self.run_statement(statement)?; previous_value = self.run_statement(statement, collect_garbage)?;
self.context.collect_garbage(position.1); self.context.collect_garbage(position.1);
} }
@ -526,7 +648,11 @@ impl Vm {
} }
} }
fn run_if(&self, if_expression: IfExpression) -> Result<Evaluation, VmError> { fn run_if(
&self,
if_expression: IfExpression,
collect_garbage: bool,
) -> Result<Evaluation, VmError> {
match if_expression { match if_expression {
IfExpression::If { IfExpression::If {
condition, condition,
@ -534,13 +660,13 @@ impl Vm {
} => { } => {
let position = condition.position(); let position = condition.position();
let boolean = self let boolean = self
.run_expression(condition)? .run_expression(condition, collect_garbage)?
.expect_value(position)? .expect_value(position)?
.as_boolean() .as_boolean()
.ok_or(VmError::ExpectedBoolean { position })?; .ok_or(VmError::ExpectedBoolean { position })?;
if boolean { if boolean {
self.run_expression(Expression::block(if_block.inner, if_block.position))?; self.run_block(if_block.inner, collect_garbage)?;
} }
Ok(Evaluation::Return(None)) Ok(Evaluation::Return(None))
@ -552,22 +678,20 @@ impl Vm {
} => { } => {
let position = condition.position(); let position = condition.position();
let boolean = self let boolean = self
.run_expression(condition)? .run_expression(condition, collect_garbage)?
.expect_value(position)? .expect_value(position)?
.as_boolean() .as_boolean()
.ok_or(VmError::ExpectedBoolean { position })?; .ok_or(VmError::ExpectedBoolean { position })?;
if boolean { if boolean {
self.run_expression(Expression::block(if_block.inner, if_block.position))?; self.run_block(if_block.inner, collect_garbage)?;
} }
match r#else { match r#else {
ElseExpression::If(if_expression) => { ElseExpression::If(if_expression) => {
self.run_expression(Expression::If(if_expression)) self.run_expression(Expression::If(if_expression), collect_garbage)
}
ElseExpression::Block(block) => {
self.run_expression(Expression::block(block.inner, block.position))
} }
ElseExpression::Block(block) => self.run_block(block.inner, collect_garbage),
} }
} }
} }
@ -907,7 +1031,7 @@ mod tests {
#[test] #[test]
fn negate_expression() { fn negate_expression() {
let input = "x = -42; -x"; let input = "let x = -42; -x";
assert_eq!(run(input), Ok(Some(Value::integer(42)))); assert_eq!(run(input), Ok(Some(Value::integer(42))));
} }