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)?;
}
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)?;

View File

@ -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),
}
}
}

View File

@ -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)

View File

@ -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)
}

View File

@ -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))));
}