1
0

Continue implementing the VM

This commit is contained in:
Jeff 2024-08-16 00:41:52 -04:00
parent b48b5d4369
commit 26348fb82e
3 changed files with 218 additions and 75 deletions

View File

@ -16,7 +16,7 @@ pub enum Expression {
FieldAccess(Node<Box<FieldAccess>>), FieldAccess(Node<Box<FieldAccess>>),
Grouped(Node<Box<Expression>>), Grouped(Node<Box<Expression>>),
Identifier(Node<Identifier>), Identifier(Node<Identifier>),
If(Node<Box<If>>), If(Node<Box<IfExpression>>),
List(Node<Box<ListExpression>>), List(Node<Box<ListExpression>>),
ListIndex(Node<Box<ListIndex>>), ListIndex(Node<Box<ListIndex>>),
Literal(Node<Box<LiteralExpression>>), Literal(Node<Box<LiteralExpression>>),
@ -197,7 +197,7 @@ impl Expression {
Self::ListIndex(Node::new(Box::new(list_index), position)) Self::ListIndex(Node::new(Box::new(list_index), position))
} }
pub fn r#if(r#if: If, position: Span) -> Self { pub fn r#if(r#if: IfExpression, position: Span) -> Self {
Self::If(Node::new(Box::new(r#if), position)) Self::If(Node::new(Box::new(r#if), position))
} }
@ -543,7 +543,7 @@ impl Display for LogicOperator {
} }
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum If { pub enum IfExpression {
If { If {
condition: Expression, condition: Expression,
if_block: Node<Block>, if_block: Node<Block>,
@ -558,7 +558,7 @@ pub enum If {
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum ElseExpression { pub enum ElseExpression {
Block(Node<Block>), Block(Node<Block>),
If(Box<If>), If(Node<Box<IfExpression>>),
} }
impl Display for ElseExpression { impl Display for ElseExpression {
@ -570,16 +570,16 @@ impl Display for ElseExpression {
} }
} }
impl Display for If { impl Display for IfExpression {
fn fmt(&self, f: &mut Formatter) -> fmt::Result { fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self { match self {
If::If { IfExpression::If {
condition, condition,
if_block, if_block,
} => { } => {
write!(f, "if {} {}", condition, if_block) write!(f, "if {} {}", condition, if_block)
} }
If::IfElse { IfExpression::IfElse {
condition, condition,
if_block, if_block,
r#else, r#else,

View File

@ -774,7 +774,7 @@ impl<'src> Parser<'src> {
} }
} }
fn parse_if(&mut self) -> Result<If, ParseError> { fn parse_if(&mut self) -> Result<IfExpression, ParseError> {
// Assume that the "if" token has already been consumed // Assume that the "if" token has already been consumed
self.mode = ParserMode::Condition; self.mode = ParserMode::Condition;
@ -788,27 +788,30 @@ impl<'src> Parser<'src> {
if let Token::Else = self.current_token { if let Token::Else = self.current_token {
self.next_token()?; self.next_token()?;
let if_keyword_start = self.current_position.0;
if let Token::If = self.current_token { if let Token::If = self.current_token {
self.next_token()?; self.next_token()?;
let else_if = self.parse_if()?; let if_expression = self.parse_if()?;
let position = (if_keyword_start, self.current_position.1);
Ok(If::IfElse { Ok(IfExpression::IfElse {
condition, condition,
if_block, if_block,
r#else: ElseExpression::If(Box::new(else_if)), r#else: ElseExpression::If(Node::new(Box::new(if_expression), position)),
}) })
} else { } else {
let else_block = self.parse_block()?; let else_block = self.parse_block()?;
Ok(If::IfElse { Ok(IfExpression::IfElse {
condition, condition,
if_block, if_block,
r#else: ElseExpression::Block(else_block), r#else: ElseExpression::Block(else_block),
}) })
} }
} else { } else {
Ok(If::If { Ok(IfExpression::If {
condition, condition,
if_block, if_block,
}) })
@ -1383,7 +1386,7 @@ mod tests {
parse(source), parse(source),
Ok(AbstractSyntaxTree::with_statements([ Ok(AbstractSyntaxTree::with_statements([
Statement::Expression(Expression::r#if( Statement::Expression(Expression::r#if(
If::If { IfExpression::If {
condition: Expression::identifier(Identifier::new("x"), (3, 4)), condition: Expression::identifier(Identifier::new("x"), (3, 4)),
if_block: Node::new( if_block: Node::new(
Block::Sync(vec![Statement::Expression(Expression::identifier( Block::Sync(vec![Statement::Expression(Expression::identifier(
@ -1407,7 +1410,7 @@ mod tests {
parse(source), parse(source),
Ok(AbstractSyntaxTree::with_statements([ Ok(AbstractSyntaxTree::with_statements([
Statement::Expression(Expression::r#if( Statement::Expression(Expression::r#if(
If::IfElse { IfExpression::IfElse {
condition: Expression::identifier(Identifier::new("x"), (3, 4)), condition: Expression::identifier(Identifier::new("x"), (3, 4)),
if_block: Node::new( if_block: Node::new(
Block::Sync(vec![Statement::Expression(Expression::identifier( Block::Sync(vec![Statement::Expression(Expression::identifier(
@ -1438,7 +1441,7 @@ mod tests {
parse(source), parse(source),
Ok(AbstractSyntaxTree::with_statements([ Ok(AbstractSyntaxTree::with_statements([
Statement::Expression(Expression::r#if( Statement::Expression(Expression::r#if(
If::IfElse { IfExpression::IfElse {
condition: Expression::identifier(Identifier::new("x"), (3, 4)), condition: Expression::identifier(Identifier::new("x"), (3, 4)),
if_block: Node::new( if_block: Node::new(
Block::Sync(vec![Statement::Expression(Expression::identifier( Block::Sync(vec![Statement::Expression(Expression::identifier(
@ -1447,23 +1450,24 @@ mod tests {
))]), ))]),
(5, 10) (5, 10)
), ),
r#else: ElseExpression::If(Box::new(If::IfElse { r#else: ElseExpression::If(Node::new(
condition: Expression::identifier(Identifier::new("z"), (19, 20)), Box::new(IfExpression::IfElse {
if_block: Node::new( condition: Expression::identifier(Identifier::new("z"), (19, 20)),
Block::Sync(vec![Statement::Expression(Expression::identifier( if_block: Node::new(
Identifier::new("a"), Block::Sync(vec![Statement::Expression(
(23, 24) Expression::identifier(Identifier::new("a"), (23, 24))
))]), )]),
(21, 26) (21, 26)
), ),
r#else: ElseExpression::Block(Node::new( r#else: ElseExpression::Block(Node::new(
Block::Sync(vec![Statement::Expression(Expression::identifier( Block::Sync(vec![Statement::Expression(
Identifier::new("b"), Expression::identifier(Identifier::new("b"), (34, 35))
(34, 35) )]),
))]), (32, 37)
(32, 37) )),
)), }),
})), (16, 37)
)),
}, },
(0, 37) (0, 37)
)) ))

View File

@ -12,9 +12,12 @@ use std::{
use rayon::iter::{IntoParallelIterator, ParallelIterator}; use rayon::iter::{IntoParallelIterator, ParallelIterator};
use crate::{ use crate::{
abstract_tree::{AbstractSyntaxTree, Block, CallExpression, FieldAccess, Node, Statement}, abstract_tree::{
AbstractSyntaxTree, Block, CallExpression, ElseExpression, FieldAccess, IfExpression,
ListExpression, Node, Statement,
},
parse, Analyzer, BuiltInFunctionError, Context, DustError, Expression, Identifier, ParseError, parse, Analyzer, BuiltInFunctionError, Context, DustError, Expression, Identifier, ParseError,
Span, Struct, StructType, Type, Value, ValueError, Span, Value, ValueError,
}; };
/// Run the source code and return the result. /// Run the source code and return the result.
@ -104,7 +107,8 @@ impl Vm {
} }
fn run_statement(&self, statement: Statement) -> Result<Option<Value>, VmError> { fn run_statement(&self, statement: Statement) -> Result<Option<Value>, VmError> {
match statement { let position = statement.position();
let result = match statement {
Statement::Expression(expression) => self.run_expression(expression), Statement::Expression(expression) => self.run_expression(expression),
Statement::ExpressionNullified(expression) => { Statement::ExpressionNullified(expression) => {
self.run_expression(expression.inner)?; self.run_expression(expression.inner)?;
@ -113,37 +117,18 @@ impl Vm {
} }
Statement::Let(_) => todo!(), Statement::Let(_) => todo!(),
Statement::StructDefinition(_) => todo!(), Statement::StructDefinition(_) => todo!(),
} };
result.map_err(|error| VmError::Trace {
error: Box::new(error),
position,
})
} }
fn run_expression(&self, expression: Expression) -> Result<Option<Value>, VmError> { fn run_expression(&self, expression: Expression) -> Result<Option<Value>, VmError> {
match expression { let position = expression.position();
Expression::Block(Node { inner, position }) => match *inner { let result = match expression {
Block::Async(statements) => { Expression::Block(Node { inner, .. }) => self.run_block(*inner),
let error_option = statements
.into_par_iter()
.find_map_any(|statement| self.run_statement(statement).err());
if let Some(error) = error_option {
Err(error)
} else {
Ok(None)
}
}
Block::Sync(statements) => {
let mut previous_value = None;
for statement in statements {
let position = statement.position();
previous_value = self.run_statement(statement)?;
self.context.collect_garbage(position.1);
}
Ok(previous_value)
}
},
Expression::Call(Node { inner, .. }) => { Expression::Call(Node { inner, .. }) => {
let CallExpression { invoker, arguments } = *inner; let CallExpression { invoker, arguments } = *inner;
@ -195,10 +180,18 @@ impl Vm {
Ok(container_value.get_field(&field.inner)) Ok(container_value.get_field(&field.inner))
} }
Expression::Grouped(_) => todo!(), Expression::Grouped(expression) => self.run_expression(*expression.inner),
Expression::Identifier(_) => todo!(), Expression::Identifier(identifier) => {
Expression::If(_) => todo!(), let value_option = self.context.get_value(&identifier.inner);
Expression::List(_) => todo!(),
if let Some(value) = value_option {
Ok(Some(value))
} else {
Err(VmError::UndefinedVariable { identifier })
}
}
Expression::If(if_expression) => self.run_if(*if_expression.inner),
Expression::List(list_expression) => self.run_list(*list_expression.inner),
Expression::ListIndex(_) => todo!(), Expression::ListIndex(_) => todo!(),
Expression::Literal(_) => todo!(), Expression::Literal(_) => todo!(),
Expression::Loop(_) => todo!(), Expression::Loop(_) => todo!(),
@ -206,6 +199,147 @@ impl Vm {
Expression::Range(_) => todo!(), Expression::Range(_) => todo!(),
Expression::Struct(_) => todo!(), Expression::Struct(_) => todo!(),
Expression::TupleAccess(_) => todo!(), Expression::TupleAccess(_) => todo!(),
};
result.map_err(|error| VmError::Trace {
error: Box::new(error),
position,
})
}
fn run_list(&self, list_expression: ListExpression) -> Result<Option<Value>, VmError> {
match list_expression {
ListExpression::AutoFill {
repeat_operand,
length_operand,
} => {
let position = length_operand.position();
let length = if let Some(value) = self.run_expression(length_operand)? {
if let Some(length) = value.as_integer() {
length
} else {
return Err(VmError::ExpectedInteger { position });
}
} else {
return Err(VmError::ExpectedValue { position });
};
let position = repeat_operand.position();
let value = if let Some(value) = self.run_expression(repeat_operand)? {
value
} else {
return Err(VmError::ExpectedValue { position });
};
Ok(Some(Value::list(vec![value; length as usize])))
}
ListExpression::Ordered(expressions) => {
let mut values = Vec::new();
for expression in expressions {
let position = expression.position();
if let Some(value) = self.run_expression(expression)? {
values.push(value);
} else {
return Err(VmError::ExpectedValue { position });
}
}
Ok(Some(Value::list(values)))
}
}
}
fn run_block(&self, block: Block) -> Result<Option<Value>, VmError> {
match block {
Block::Async(statements) => {
let error_option = statements
.into_par_iter()
.find_map_any(|statement| self.run_statement(statement).err());
if let Some(error) = error_option {
Err(error)
} else {
Ok(None)
}
}
Block::Sync(statements) => {
let mut previous_value = None;
for statement in statements {
let position = statement.position();
previous_value = self.run_statement(statement)?;
self.context.collect_garbage(position.1);
}
Ok(previous_value)
}
}
}
fn run_if(&self, if_expression: IfExpression) -> Result<Option<Value>, VmError> {
match if_expression {
IfExpression::If {
condition,
if_block,
} => {
let condition_position = condition.position();
let condition_value = if let Some(value) = self.run_expression(condition)? {
value
} else {
return Err(VmError::ExpectedValue {
position: condition_position,
});
};
if let Some(boolean) = condition_value.as_boolean() {
if boolean {
self.run_expression(Expression::block(if_block.inner, if_block.position))?;
}
} else {
return Err(VmError::ExpectedBoolean {
position: condition_position,
});
}
Ok(None)
}
IfExpression::IfElse {
condition,
if_block,
r#else,
} => {
let condition_position = condition.position();
let condition_value = if let Some(value) = self.run_expression(condition)? {
value
} else {
return Err(VmError::ExpectedValue {
position: condition_position,
});
};
if let Some(boolean) = condition_value.as_boolean() {
if boolean {
self.run_expression(Expression::block(if_block.inner, if_block.position))?;
}
} else {
return Err(VmError::ExpectedBoolean {
position: condition_position,
});
}
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))
}
}
}
} }
} }
} }
@ -213,6 +347,10 @@ impl Vm {
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
pub enum VmError { pub enum VmError {
ParseError(ParseError), ParseError(ParseError),
Trace {
error: Box<VmError>,
position: Span,
},
ValueError { ValueError {
error: ValueError, error: ValueError,
position: Span, position: Span,
@ -274,6 +412,7 @@ impl VmError {
pub fn position(&self) -> Span { pub fn position(&self) -> Span {
match self { match self {
Self::ParseError(parse_error) => parse_error.position(), Self::ParseError(parse_error) => parse_error.position(),
Self::Trace { position, .. } => *position,
Self::ValueError { position, .. } => *position, Self::ValueError { position, .. } => *position,
Self::CannotMutate { position, .. } => *position, Self::CannotMutate { position, .. } => *position,
Self::BuiltInFunctionError { position, .. } => *position, Self::BuiltInFunctionError { position, .. } => *position,
@ -305,6 +444,13 @@ impl Display for VmError {
fn fmt(&self, f: &mut Formatter) -> fmt::Result { fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self { match self {
Self::ParseError(parse_error) => write!(f, "{}", parse_error), Self::ParseError(parse_error) => write!(f, "{}", parse_error),
Self::Trace { error, position } => {
write!(
f,
"Error during execution at position: {:?}\n{}",
position, error
)
}
Self::ValueError { error, .. } => write!(f, "{}", error), Self::ValueError { error, .. } => write!(f, "{}", error),
Self::CannotMutate { value, .. } => { Self::CannotMutate { value, .. } => {
write!(f, "Cannot mutate immutable value {}", value) write!(f, "Cannot mutate immutable value {}", value)
@ -492,13 +638,6 @@ mod tests {
assert_eq!(run(input), Ok(Some(Value::integer(42)))); assert_eq!(run(input), Ok(Some(Value::integer(42))));
} }
#[test]
fn map_property_access_expression() {
let input = "{ foobar = 42 }.('foo' + 'bar')";
assert_eq!(run(input), Ok(Some(Value::integer(42))));
}
#[test] #[test]
fn list_index_range() { fn list_index_range() {
let input = "[1, 2, 3, 4, 5][1..3]"; let input = "[1, 2, 3, 4, 5][1..3]";