Prepare for value overhaul
This commit is contained in:
parent
7d721beb31
commit
8bff39a7db
@ -168,8 +168,12 @@ impl<'a> Analyzer<'a> {
|
||||
self.analyze_expression(modifier)?;
|
||||
}
|
||||
OperatorExpression::ErrorPropagation(_) => todo!(),
|
||||
OperatorExpression::Negation(_) => todo!(),
|
||||
OperatorExpression::Not(_) => todo!(),
|
||||
OperatorExpression::Negation(expression) => {
|
||||
self.analyze_expression(expression)?;
|
||||
}
|
||||
OperatorExpression::Not(expression) => {
|
||||
self.analyze_expression(expression)?;
|
||||
}
|
||||
OperatorExpression::Math { left, right, .. } => {
|
||||
self.analyze_expression(left)?;
|
||||
self.analyze_expression(right)?;
|
||||
|
@ -22,7 +22,7 @@ pub enum Expression {
|
||||
Literal(Node<Box<LiteralExpression>>),
|
||||
Loop(Node<Box<LoopExpression>>),
|
||||
Operator(Node<Box<OperatorExpression>>),
|
||||
Range(Node<Box<Range>>),
|
||||
Range(Node<Box<RangeExpression>>),
|
||||
Struct(Node<Box<StructExpression>>),
|
||||
TupleAccess(Node<Box<TupleAccess>>),
|
||||
}
|
||||
@ -32,8 +32,18 @@ impl Expression {
|
||||
Self::Operator(Node::new(Box::new(operator_expression), position))
|
||||
}
|
||||
|
||||
pub fn range(start: Expression, end: Expression, position: Span) -> Self {
|
||||
Self::Range(Node::new(Box::new(Range { start, end }), position))
|
||||
pub fn exclusive_range(start: Expression, end: Expression, position: Span) -> Self {
|
||||
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 {
|
||||
@ -391,14 +401,17 @@ impl Display for TupleAccess {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||
pub struct Range {
|
||||
pub start: Expression,
|
||||
pub end: Expression,
|
||||
pub enum RangeExpression {
|
||||
Exclusive { start: Expression, end: Expression },
|
||||
Inclusive { start: Expression, end: Expression },
|
||||
}
|
||||
|
||||
impl Display for Range {
|
||||
impl Display for RangeExpression {
|
||||
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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -633,7 +633,7 @@ impl<'src> Parser<'src> {
|
||||
let end = self.parse_expression(operator_precedence)?;
|
||||
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 =
|
||||
@ -1335,7 +1335,7 @@ mod tests {
|
||||
assert_eq!(
|
||||
parse(source),
|
||||
Ok(AbstractSyntaxTree::with_statements([
|
||||
Statement::Expression(Expression::range(
|
||||
Statement::Expression(Expression::exclusive_range(
|
||||
Expression::literal(LiteralExpression::Integer(0), (0, 1)),
|
||||
Expression::literal(LiteralExpression::Integer(42), (3, 5)),
|
||||
(0, 5)
|
||||
|
@ -4,7 +4,7 @@ use std::{
|
||||
collections::BTreeMap,
|
||||
error::Error,
|
||||
fmt::{self, Display, Formatter},
|
||||
ops::Range,
|
||||
ops::{Range, RangeInclusive},
|
||||
sync::{Arc, RwLock, RwLockWriteGuard},
|
||||
};
|
||||
|
||||
@ -80,7 +80,7 @@ impl Value {
|
||||
}
|
||||
|
||||
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 {
|
||||
@ -1137,7 +1137,8 @@ pub enum ValueData {
|
||||
Integer(i64),
|
||||
List(Vec<Value>),
|
||||
Map(BTreeMap<Identifier, Value>),
|
||||
Range(Range<i64>),
|
||||
RangeExclusive(Range<Value>),
|
||||
RangeInclusive(RangeInclusive<Value>),
|
||||
String(String),
|
||||
Struct(Struct),
|
||||
}
|
||||
@ -1172,7 +1173,8 @@ impl ValueData {
|
||||
|
||||
Type::Map(type_map)
|
||||
}
|
||||
ValueData::Range(_) => Type::Range,
|
||||
ValueData::RangeExclusive(_) => Type::Range,
|
||||
ValueData::RangeInclusive(_) => Type::Range,
|
||||
ValueData::String(_) => Type::String,
|
||||
ValueData::Struct(r#struct) => match r#struct {
|
||||
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 {
|
||||
return list.get(index).cloned();
|
||||
}
|
||||
|
||||
if let ValueData::Range(range) = self {
|
||||
if let ValueData::RangeExclusive(range) = self {
|
||||
if range.contains(&(index as i64)) {
|
||||
return Some(Value::integer(index as i64));
|
||||
}
|
||||
@ -1271,7 +1273,8 @@ impl Display for ValueData {
|
||||
|
||||
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::Struct(r#struct) => write!(f, "{struct}"),
|
||||
}
|
||||
@ -1303,7 +1306,7 @@ impl Ord for ValueData {
|
||||
(List(_), _) => Ordering::Greater,
|
||||
(Map(left), Map(right)) => left.cmp(right),
|
||||
(Map(_), _) => Ordering::Greater,
|
||||
(Range(left), Range(right)) => {
|
||||
(RangeExclusive(left), RangeExclusive(right)) => {
|
||||
let start_cmp = left.start.cmp(&right.start);
|
||||
|
||||
if start_cmp.is_eq() {
|
||||
@ -1312,7 +1315,17 @@ impl Ord for ValueData {
|
||||
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(_), _) => Ordering::Greater,
|
||||
(Struct(left), Struct(right)) => left.cmp(right),
|
||||
@ -1349,7 +1362,7 @@ impl Serialize for ValueData {
|
||||
|
||||
map_ser.end()
|
||||
}
|
||||
ValueData::Range(range) => {
|
||||
ValueData::RangeExclusive(range) => {
|
||||
let mut tuple_ser = serializer.serialize_tuple(2)?;
|
||||
|
||||
tuple_ser.serialize_element(&range.start)?;
|
||||
@ -1357,6 +1370,14 @@ impl Serialize for ValueData {
|
||||
|
||||
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::Struct(r#struct) => r#struct.serialize(serializer),
|
||||
}
|
||||
@ -1626,7 +1647,7 @@ impl Function {
|
||||
if let (Some(value_parameters), Some(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);
|
||||
}
|
||||
}
|
||||
@ -1743,6 +1764,7 @@ pub enum ValueError {
|
||||
CannotDivide(Value, Value),
|
||||
CannotGreaterThan(Value, Value),
|
||||
CannotGreaterThanOrEqual(Value, Value),
|
||||
CannotIndex { value: Value, index: Value },
|
||||
CannotLessThan(Value, Value),
|
||||
CannotLessThanOrEqual(Value, Value),
|
||||
CannotMakeMutable,
|
||||
@ -1770,6 +1792,9 @@ impl Display for ValueError {
|
||||
ValueError::CannotDivide(left, right) => {
|
||||
write!(f, "Cannot divide {} by {}", left, right)
|
||||
}
|
||||
ValueError::CannotIndex { value, index } => {
|
||||
write!(f, "Cannot index {} with {}", value, index)
|
||||
}
|
||||
ValueError::CannotModulo(left, right) => {
|
||||
write!(f, "Cannot modulo {} by {}", left, right)
|
||||
}
|
||||
|
@ -6,6 +6,7 @@
|
||||
//! - `Vm` struct that can be used to run an abstract syntax tree
|
||||
use std::{
|
||||
fmt::{self, Display, Formatter},
|
||||
ops::Range,
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
|
||||
@ -16,7 +17,7 @@ use crate::{
|
||||
AbstractSyntaxTree, BlockExpression, CallExpression, ComparisonOperator, ElseExpression,
|
||||
FieldAccessExpression, IfExpression, LetStatement, ListExpression, ListIndexExpression,
|
||||
LiteralExpression, LogicOperator, LoopExpression, MathOperator, Node, OperatorExpression,
|
||||
Statement,
|
||||
RangeExpression, Statement,
|
||||
},
|
||||
parse, Analyzer, BuiltInFunctionError, Context, DustError, Expression, Identifier, ParseError,
|
||||
Span, Value, ValueError,
|
||||
@ -93,32 +94,38 @@ impl Vm {
|
||||
let mut previous_value = None;
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
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 result = match statement {
|
||||
Statement::Expression(expression) => self
|
||||
.run_expression(expression)
|
||||
.run_expression(expression, collect_garbage)
|
||||
.map(|evaluation| evaluation.value()),
|
||||
Statement::ExpressionNullified(expression) => {
|
||||
self.run_expression(expression.inner)?;
|
||||
self.run_expression(expression.inner, collect_garbage)?;
|
||||
|
||||
Ok(None)
|
||||
}
|
||||
Statement::Let(let_statement) => {
|
||||
self.run_let_statement(let_statement.inner)?;
|
||||
self.run_let_statement(let_statement.inner, collect_garbage)?;
|
||||
|
||||
Ok(None)
|
||||
}
|
||||
Statement::StructDefinition(_) => todo!(),
|
||||
};
|
||||
|
||||
if collect_garbage {
|
||||
self.context.collect_garbage(position.1);
|
||||
}
|
||||
|
||||
result.map_err(|error| VmError::Trace {
|
||||
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 {
|
||||
LetStatement::Let { identifier, value } => {
|
||||
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);
|
||||
|
||||
@ -138,7 +151,9 @@ impl Vm {
|
||||
}
|
||||
LetStatement::LetMut { identifier, value } => {
|
||||
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 {
|
||||
error,
|
||||
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 evaluation_result = match expression {
|
||||
Expression::Block(Node { inner, .. }) => self.run_block(*inner),
|
||||
Expression::Call(call) => self.run_call(*call.inner),
|
||||
Expression::FieldAccess(field_access) => self.run_field_access(*field_access.inner),
|
||||
Expression::Grouped(expression) => self.run_expression(*expression.inner),
|
||||
Expression::Block(Node { inner, .. }) => self.run_block(*inner, collect_garbage),
|
||||
Expression::Call(call) => self.run_call(*call.inner, collect_garbage),
|
||||
Expression::FieldAccess(field_access) => {
|
||||
self.run_field_access(*field_access.inner, collect_garbage)
|
||||
}
|
||||
Expression::Grouped(expression) => {
|
||||
self.run_expression(*expression.inner, collect_garbage)
|
||||
}
|
||||
Expression::Identifier(identifier) => {
|
||||
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::List(list_expression) => self.run_list(*list_expression.inner),
|
||||
Expression::ListIndex(list_index) => self.run_list_index(*list_index.inner),
|
||||
Expression::If(if_expression) => self.run_if(*if_expression.inner, collect_garbage),
|
||||
Expression::List(list_expression) => {
|
||||
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::Loop(loop_expression) => self.run_loop(*loop_expression.inner),
|
||||
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::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 {
|
||||
OperatorExpression::Assignment { assignee, value } => {
|
||||
let assignee_position = assignee.position();
|
||||
let assignee = self
|
||||
.run_expression(assignee)?
|
||||
.run_expression(assignee, collect_garbage)?
|
||||
.expect_value(assignee_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
|
||||
.mutate(value)
|
||||
@ -218,9 +265,13 @@ impl Vm {
|
||||
right,
|
||||
} => {
|
||||
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_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 {
|
||||
ComparisonOperator::Equal => left_value.equal(&right_value),
|
||||
@ -264,11 +315,11 @@ impl Vm {
|
||||
} => {
|
||||
let assignee_position = assignee.position();
|
||||
let assignee = self
|
||||
.run_expression(assignee)?
|
||||
.run_expression(assignee, collect_garbage)?
|
||||
.expect_value(assignee_position)?;
|
||||
let modifier_position = modifier.position();
|
||||
let modifier = self
|
||||
.run_expression(modifier)?
|
||||
.run_expression(modifier, collect_garbage)?
|
||||
.expect_value(modifier_position)?;
|
||||
|
||||
match operator.inner {
|
||||
@ -287,17 +338,43 @@ impl Vm {
|
||||
Ok(Evaluation::Return(None))
|
||||
}
|
||||
OperatorExpression::ErrorPropagation(_) => todo!(),
|
||||
OperatorExpression::Negation(_) => todo!(),
|
||||
OperatorExpression::Not(_) => todo!(),
|
||||
OperatorExpression::Negation(expression) => {
|
||||
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 {
|
||||
left,
|
||||
operator,
|
||||
right,
|
||||
} => {
|
||||
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_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 {
|
||||
MathOperator::Add => left_value.add(&right_value),
|
||||
MathOperator::Subtract => left_value.subtract(&right_value),
|
||||
@ -319,9 +396,13 @@ impl Vm {
|
||||
right,
|
||||
} => {
|
||||
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_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 {
|
||||
LogicOperator::And => left_value.and(&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> {
|
||||
match loop_expression {
|
||||
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 {
|
||||
identifier,
|
||||
iterator,
|
||||
@ -363,14 +457,22 @@ impl Vm {
|
||||
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 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_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() {
|
||||
index as usize
|
||||
@ -385,11 +487,16 @@ impl Vm {
|
||||
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 invoker_position = invoker.position();
|
||||
let invoker_value = if let Some(value) = self.run_expression(invoker)?.value() {
|
||||
let invoker_value =
|
||||
if let Some(value) = self.run_expression(invoker, collect_garbage)?.value() {
|
||||
value
|
||||
} else {
|
||||
return Err(VmError::ExpectedValue {
|
||||
@ -411,7 +518,7 @@ impl Vm {
|
||||
for argument in arguments {
|
||||
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);
|
||||
} else {
|
||||
return Err(VmError::ExpectedValue { position });
|
||||
@ -425,11 +532,16 @@ impl Vm {
|
||||
.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 container_position = container.position();
|
||||
let container_value = if let Some(value) = self.run_expression(container)?.value() {
|
||||
let container_value =
|
||||
if let Some(value) = self.run_expression(container, collect_garbage)?.value() {
|
||||
value
|
||||
} else {
|
||||
return Err(VmError::ExpectedValue {
|
||||
@ -440,7 +552,11 @@ impl Vm {
|
||||
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 {
|
||||
ListExpression::AutoFill {
|
||||
repeat_operand,
|
||||
@ -448,14 +564,14 @@ impl Vm {
|
||||
} => {
|
||||
let position = length_operand.position();
|
||||
let length = self
|
||||
.run_expression(length_operand)?
|
||||
.run_expression(length_operand, collect_garbage)?
|
||||
.expect_value(position)?
|
||||
.as_integer()
|
||||
.ok_or(VmError::ExpectedInteger { position })?;
|
||||
|
||||
let position = repeat_operand.position();
|
||||
let value = self
|
||||
.run_expression(repeat_operand)?
|
||||
.run_expression(repeat_operand, collect_garbage)?
|
||||
.expect_value(position)?;
|
||||
|
||||
Ok(Evaluation::Return(Some(Value::list(vec![
|
||||
@ -468,7 +584,9 @@ impl Vm {
|
||||
|
||||
for expression in expressions {
|
||||
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);
|
||||
}
|
||||
@ -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 {
|
||||
BlockExpression::Async(statements) => {
|
||||
let final_result = Arc::new(Mutex::new(None));
|
||||
@ -488,7 +610,7 @@ impl Vm {
|
||||
.into_par_iter()
|
||||
.enumerate()
|
||||
.find_map_any(|(i, statement)| {
|
||||
let evaluation_result = self.run_statement(statement);
|
||||
let evaluation_result = self.run_statement(statement, false);
|
||||
|
||||
match evaluation_result {
|
||||
Ok(evaluation) => {
|
||||
@ -516,7 +638,7 @@ impl Vm {
|
||||
for statement in statements {
|
||||
let position = statement.position();
|
||||
|
||||
previous_value = self.run_statement(statement)?;
|
||||
previous_value = self.run_statement(statement, collect_garbage)?;
|
||||
|
||||
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 {
|
||||
IfExpression::If {
|
||||
condition,
|
||||
@ -534,13 +660,13 @@ impl Vm {
|
||||
} => {
|
||||
let position = condition.position();
|
||||
let boolean = self
|
||||
.run_expression(condition)?
|
||||
.run_expression(condition, collect_garbage)?
|
||||
.expect_value(position)?
|
||||
.as_boolean()
|
||||
.ok_or(VmError::ExpectedBoolean { position })?;
|
||||
|
||||
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))
|
||||
@ -552,22 +678,20 @@ impl Vm {
|
||||
} => {
|
||||
let position = condition.position();
|
||||
let boolean = self
|
||||
.run_expression(condition)?
|
||||
.run_expression(condition, collect_garbage)?
|
||||
.expect_value(position)?
|
||||
.as_boolean()
|
||||
.ok_or(VmError::ExpectedBoolean { position })?;
|
||||
|
||||
if boolean {
|
||||
self.run_expression(Expression::block(if_block.inner, if_block.position))?;
|
||||
self.run_block(if_block.inner, collect_garbage)?;
|
||||
}
|
||||
|
||||
match r#else {
|
||||
ElseExpression::If(if_expression) => {
|
||||
self.run_expression(Expression::If(if_expression))
|
||||
}
|
||||
ElseExpression::Block(block) => {
|
||||
self.run_expression(Expression::block(block.inner, block.position))
|
||||
self.run_expression(Expression::If(if_expression), collect_garbage)
|
||||
}
|
||||
ElseExpression::Block(block) => self.run_block(block.inner, collect_garbage),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -907,7 +1031,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn negate_expression() {
|
||||
let input = "x = -42; -x";
|
||||
let input = "let x = -42; -x";
|
||||
|
||||
assert_eq!(run(input), Ok(Some(Value::integer(42))));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user