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)?;
|
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)?;
|
||||||
|
@ -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),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if collect_garbage {
|
||||||
self.context.collect_garbage(position.1);
|
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,11 +487,16 @@ 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 =
|
||||||
|
if let Some(value) = self.run_expression(invoker, collect_garbage)?.value() {
|
||||||
value
|
value
|
||||||
} else {
|
} else {
|
||||||
return Err(VmError::ExpectedValue {
|
return Err(VmError::ExpectedValue {
|
||||||
@ -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,11 +532,16 @@ 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 =
|
||||||
|
if let Some(value) = self.run_expression(container, collect_garbage)?.value() {
|
||||||
value
|
value
|
||||||
} else {
|
} else {
|
||||||
return Err(VmError::ExpectedValue {
|
return Err(VmError::ExpectedValue {
|
||||||
@ -440,7 +552,11 @@ impl Vm {
|
|||||||
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))));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user