From bfb07047a5f36ed94ad3a8f7864ee57b13cac75c Mon Sep 17 00:00:00 2001 From: Jeff Date: Fri, 16 Aug 2024 05:14:00 -0400 Subject: [PATCH] Implement VM --- dust-lang/src/abstract_tree/expression.rs | 205 ++++++++++-- dust-lang/src/abstract_tree/mod.rs | 13 +- dust-lang/src/parser.rs | 54 ++- dust-lang/src/type.rs | 4 +- dust-lang/src/value.rs | 8 +- dust-lang/src/vm.rs | 387 +++++++++++++--------- 6 files changed, 443 insertions(+), 228 deletions(-) diff --git a/dust-lang/src/abstract_tree/expression.rs b/dust-lang/src/abstract_tree/expression.rs index 9d01ad8..5613a81 100644 --- a/dust-lang/src/abstract_tree/expression.rs +++ b/dust-lang/src/abstract_tree/expression.rs @@ -5,22 +5,22 @@ use std::{ use serde::{Deserialize, Serialize}; -use crate::{Identifier, Span, Value}; +use crate::{Context, Identifier, Span, StructType, Type, Value}; use super::{Node, Statement}; #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub enum Expression { - Block(Node>), + Block(Node>), Call(Node>), - FieldAccess(Node>), + FieldAccess(Node>), Grouped(Node>), Identifier(Node), If(Node>), List(Node>), - ListIndex(Node>), + ListIndex(Node>), Literal(Node>), - Loop(Node>), + Loop(Node>), Operator(Node>), Range(Node>), Struct(Node>), @@ -45,7 +45,7 @@ impl Expression { pub fn field_access(container: Expression, field: Node, position: Span) -> Self { Self::FieldAccess(Node::new( - Box::new(FieldAccess { container, field }), + Box::new(FieldAccessExpression { container, field }), position, )) } @@ -146,13 +146,16 @@ impl Expression { )) } - pub fn infinite_loop(block: Node, position: Span) -> Self { - Self::Loop(Node::new(Box::new(Loop::Infinite { block }), position)) + pub fn infinite_loop(block: Node, position: Span) -> Self { + Self::Loop(Node::new( + Box::new(LoopExpression::Infinite { block }), + position, + )) } - pub fn while_loop(condition: Expression, block: Node, position: Span) -> Self { + pub fn while_loop(condition: Expression, block: Node, position: Span) -> Self { Self::Loop(Node::new( - Box::new(Loop::While { condition, block }), + Box::new(LoopExpression::While { condition, block }), position, )) } @@ -160,11 +163,11 @@ impl Expression { pub fn for_loop( identifier: Node, iterator: Expression, - block: Node, + block: Node, position: Span, ) -> Self { Self::Loop(Node::new( - Box::new(Loop::For { + Box::new(LoopExpression::For { identifier, iterator, block, @@ -173,7 +176,7 @@ impl Expression { )) } - pub fn block(block: Block, position: Span) -> Self { + pub fn block(block: BlockExpression, position: Span) -> Self { Self::Block(Node::new(Box::new(block), position)) } @@ -193,7 +196,7 @@ impl Expression { Self::List(Node::new(Box::new(list_expression), position)) } - pub fn list_index(list_index: ListIndex, position: Span) -> Self { + pub fn list_index(list_index: ListIndexExpression, position: Span) -> Self { Self::ListIndex(Node::new(Box::new(list_index), position)) } @@ -213,6 +216,127 @@ impl Expression { } } + pub fn return_type(&self, context: &Context) -> Option { + match self { + Expression::Block(block_expression) => { + block_expression.inner.as_ref().return_type(context) + } + Expression::Call(call_expression) => { + let CallExpression { invoker, .. } = call_expression.inner.as_ref(); + + let invoker_type = invoker.return_type(context)?; + + if let Type::Function { return_type, .. } = invoker_type { + return_type.map(|r#type| *r#type) + } else if let Type::Struct(_) = invoker_type { + Some(invoker_type) + } else { + None + } + } + Expression::FieldAccess(field_access_expression) => { + let FieldAccessExpression { container, field } = + field_access_expression.inner.as_ref(); + + let container_type = container.return_type(context)?; + + if let Type::Struct(StructType::Fields { fields, .. }) = container_type { + fields + .into_iter() + .find(|(name, _)| name == &field.inner) + .map(|(_, r#type)| r#type) + } else { + None + } + } + Expression::Grouped(expression) => expression.inner.return_type(context), + Expression::Identifier(identifier) => context.get_type(&identifier.inner), + Expression::If(if_expression) => match if_expression.inner.as_ref() { + IfExpression::If { .. } => None, + IfExpression::IfElse { if_block, .. } => if_block.inner.return_type(context), + }, + + Expression::List(list_expression) => match list_expression.inner.as_ref() { + ListExpression::AutoFill { repeat_operand, .. } => { + let item_type = repeat_operand.return_type(context)?; + + Some(Type::ListOf { + item_type: Box::new(item_type), + }) + } + ListExpression::Ordered(expressions) => { + if expressions.is_empty() { + return Some(Type::EmptyList); + } + + let item_type = expressions.last().unwrap().return_type(context)?; + let length = expressions.len(); + + Some(Type::List { + item_type: Box::new(item_type), + length, + }) + } + }, + Expression::ListIndex(list_index_expression) => { + let ListIndexExpression { list, .. } = list_index_expression.inner.as_ref(); + + let list_type = list.return_type(context)?; + + if let Type::List { item_type, .. } = list_type { + Some(*item_type) + } else { + None + } + } + Expression::Literal(literal_expression) => match literal_expression.inner.as_ref() { + LiteralExpression::Boolean(_) => Some(Type::Boolean), + LiteralExpression::Float(_) => Some(Type::Float), + LiteralExpression::Integer(_) => Some(Type::Integer), + LiteralExpression::String(_) => Some(Type::String), + LiteralExpression::Value(value) => Some(value.r#type()), + }, + Expression::Loop(loop_expression) => match loop_expression.inner.as_ref() { + LoopExpression::For { block, .. } => block.inner.return_type(context), + LoopExpression::Infinite { .. } => None, + LoopExpression::While { block, .. } => block.inner.return_type(context), + }, + Expression::Operator(operator_expression) => match operator_expression.inner.as_ref() { + OperatorExpression::Assignment { .. } => None, + OperatorExpression::Comparison { .. } => Some(Type::Boolean), + OperatorExpression::CompoundAssignment { .. } => None, + OperatorExpression::ErrorPropagation(expression) => expression.return_type(context), + OperatorExpression::Negation(expression) => expression.return_type(context), + OperatorExpression::Not(_) => Some(Type::Boolean), + OperatorExpression::Math { left, .. } => left.return_type(context), + OperatorExpression::Logic { .. } => Some(Type::Boolean), + }, + Expression::Range(_) => Some(Type::Range), + Expression::Struct(struct_expression) => match struct_expression.inner.as_ref() { + StructExpression::Fields { name, fields } => { + let mut field_types = Vec::with_capacity(fields.len()); + + for (name, expression) in fields { + let r#type = expression.return_type(context)?; + + field_types.push((name.inner.clone(), r#type)); + } + + Some(Type::Struct(StructType::Fields { + name: name.inner.clone(), + fields: field_types, + })) + } + StructExpression::Unit { name } => Some(Type::Struct(StructType::Unit { + name: name.inner.clone(), + })), + }, + Expression::TupleAccess(tuple_access_expression) => { + todo!() + } + } + } + pub fn position(&self) -> Span { match self { Expression::Block(block) => block.position, @@ -279,12 +403,12 @@ impl Display for Range { } #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] -pub struct ListIndex { +pub struct ListIndexExpression { pub list: Expression, pub index: Expression, } -impl Display for ListIndex { +impl Display for ListIndexExpression { fn fmt(&self, f: &mut Formatter) -> fmt::Result { write!(f, "{}[{}]", self.list, self.index) } @@ -313,12 +437,12 @@ impl Display for CallExpression { } #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] -pub struct FieldAccess { +pub struct FieldAccessExpression { pub container: Expression, pub field: Node, } -impl Display for FieldAccess { +impl Display for FieldAccessExpression { fn fmt(&self, f: &mut Formatter) -> fmt::Result { write!(f, "{}.{}", self.container, self.field) } @@ -546,18 +670,18 @@ impl Display for LogicOperator { pub enum IfExpression { If { condition: Expression, - if_block: Node, + if_block: Node, }, IfElse { condition: Expression, - if_block: Node, + if_block: Node, r#else: ElseExpression, }, } #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub enum ElseExpression { - Block(Node), + Block(Node), If(Node>), } @@ -591,15 +715,28 @@ impl Display for IfExpression { } #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] -pub enum Block { +pub enum BlockExpression { Async(Vec), Sync(Vec), } -impl Display for Block { +impl BlockExpression { + fn return_type(&self, context: &Context) -> Option { + match self { + BlockExpression::Async(statements) => statements + .last() + .and_then(|statement| statement.return_type(context)), + BlockExpression::Sync(statements) => statements + .last() + .and_then(|statement| statement.return_type(context)), + } + } +} + +impl Display for BlockExpression { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { match self { - Block::Async(statements) => { + BlockExpression::Async(statements) => { writeln!(f, "async {{ ")?; for (i, statement) in statements.iter().enumerate() { @@ -612,7 +749,7 @@ impl Display for Block { write!(f, " }}") } - Block::Sync(statements) => { + BlockExpression::Sync(statements) => { writeln!(f, "{{ ")?; for (i, statement) in statements.iter().enumerate() { @@ -630,27 +767,29 @@ impl Display for Block { } #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] -pub enum Loop { +pub enum LoopExpression { Infinite { - block: Node, + block: Node, }, While { condition: Expression, - block: Node, + block: Node, }, For { identifier: Node, iterator: Expression, - block: Node, + block: Node, }, } -impl Display for Loop { +impl Display for LoopExpression { fn fmt(&self, f: &mut Formatter) -> fmt::Result { match self { - Loop::Infinite { block } => write!(f, "loop {}", block), - Loop::While { condition, block } => write!(f, "while {} {}", condition, block), - Loop::For { + LoopExpression::Infinite { block } => write!(f, "loop {}", block), + LoopExpression::While { condition, block } => { + write!(f, "while {} {}", condition, block) + } + LoopExpression::For { identifier, iterator, block, diff --git a/dust-lang/src/abstract_tree/mod.rs b/dust-lang/src/abstract_tree/mod.rs index 87d78d3..111a742 100644 --- a/dust-lang/src/abstract_tree/mod.rs +++ b/dust-lang/src/abstract_tree/mod.rs @@ -10,7 +10,7 @@ use std::{ use serde::{Deserialize, Serialize}; -use crate::{Identifier, Span, Type}; +use crate::{Context, Identifier, Span, Type}; /// In-memory representation of a Dust program. #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] @@ -69,6 +69,17 @@ impl Statement { Statement::StructDefinition(Node::new(struct_definition, position)) } + pub fn return_type(&self, context: &Context) -> Option { + match self { + Statement::Expression(expression) => expression.return_type(context), + Statement::ExpressionNullified(expression_node) => { + expression_node.inner.return_type(context) + } + Statement::Let(_) => None, + Statement::StructDefinition(_) => None, + } + } + pub fn position(&self) -> Span { match self { Statement::Expression(expression) => expression.position(), diff --git a/dust-lang/src/parser.rs b/dust-lang/src/parser.rs index 6881feb..cc8ef4d 100644 --- a/dust-lang/src/parser.rs +++ b/dust-lang/src/parser.rs @@ -757,7 +757,7 @@ impl<'src> Parser<'src> { let position = (left.position().0, operator_end); - Expression::list_index(ListIndex { list: left, index }, position) + Expression::list_index(ListIndexExpression { list: left, index }, position) } _ => { return Err(ParseError::UnexpectedToken { @@ -834,7 +834,7 @@ impl<'src> Parser<'src> { } } - fn parse_block(&mut self) -> Result, ParseError> { + fn parse_block(&mut self) -> Result, ParseError> { let left_start = self.current_position.0; let is_async = if let Token::Async = self.current_token { self.next_token()?; @@ -863,9 +863,9 @@ impl<'src> Parser<'src> { self.next_token()?; return if is_async { - Ok(Node::new(Block::Async(statements), position)) + Ok(Node::new(BlockExpression::Async(statements), position)) } else { - Ok(Node::new(Block::Sync(statements), position)) + Ok(Node::new(BlockExpression::Sync(statements), position)) }; } @@ -1041,7 +1041,7 @@ mod tests { parse(source), Ok(AbstractSyntaxTree { statements: [Statement::Expression(Expression::block( - Block::Async(vec![ + BlockExpression::Async(vec![ Statement::ExpressionNullified(Node::new( Expression::operator( OperatorExpression::Assignment { @@ -1230,9 +1230,9 @@ mod tests { parse(source), Ok(AbstractSyntaxTree::with_statements([ Statement::Expression(Expression::list_index( - ListIndex { + ListIndexExpression { list: Expression::list_index( - ListIndex { + ListIndexExpression { list: Expression::list( ListExpression::Ordered(vec![ Expression::literal(LiteralExpression::Integer(1), (1, 2)), @@ -1389,10 +1389,9 @@ mod tests { IfExpression::If { condition: Expression::identifier(Identifier::new("x"), (3, 4)), if_block: Node::new( - Block::Sync(vec![Statement::Expression(Expression::identifier( - Identifier::new("y"), - (7, 8) - ))]), + BlockExpression::Sync(vec![Statement::Expression( + Expression::identifier(Identifier::new("y"), (7, 8)) + )]), (5, 10) ) }, @@ -1413,17 +1412,15 @@ mod tests { IfExpression::IfElse { condition: Expression::identifier(Identifier::new("x"), (3, 4)), if_block: Node::new( - Block::Sync(vec![Statement::Expression(Expression::identifier( - Identifier::new("y"), - (7, 8) - ))]), + BlockExpression::Sync(vec![Statement::Expression( + Expression::identifier(Identifier::new("y"), (7, 8)) + )]), (5, 10) ), r#else: ElseExpression::Block(Node::new( - Block::Sync(vec![Statement::Expression(Expression::identifier( - Identifier::new("z"), - (18, 19) - ))]), + BlockExpression::Sync(vec![Statement::Expression( + Expression::identifier(Identifier::new("z"), (18, 19)) + )]), (16, 21) )) }, @@ -1444,23 +1441,22 @@ mod tests { IfExpression::IfElse { condition: Expression::identifier(Identifier::new("x"), (3, 4)), if_block: Node::new( - Block::Sync(vec![Statement::Expression(Expression::identifier( - Identifier::new("y"), - (7, 8) - ))]), + BlockExpression::Sync(vec![Statement::Expression( + Expression::identifier(Identifier::new("y"), (7, 8)) + )]), (5, 10) ), r#else: ElseExpression::If(Node::new( Box::new(IfExpression::IfElse { condition: Expression::identifier(Identifier::new("z"), (19, 20)), if_block: Node::new( - Block::Sync(vec![Statement::Expression( + BlockExpression::Sync(vec![Statement::Expression( Expression::identifier(Identifier::new("a"), (23, 24)) )]), (21, 26) ), r#else: ElseExpression::Block(Node::new( - Block::Sync(vec![Statement::Expression( + BlockExpression::Sync(vec![Statement::Expression( Expression::identifier(Identifier::new("b"), (34, 35)) )]), (32, 37) @@ -1492,7 +1488,7 @@ mod tests { (6, 12) ), Node::new( - Block::Sync(vec![Statement::Expression(Expression::operator( + BlockExpression::Sync(vec![Statement::Expression(Expression::operator( OperatorExpression::CompoundAssignment { assignee: Expression::identifier(Identifier::new("x"), (15, 16)), operator: Node::new(MathOperator::Add, (17, 19)), @@ -1557,7 +1553,7 @@ mod tests { parse(source), Ok(AbstractSyntaxTree::with_statements([ Statement::Expression(Expression::block( - Block::Sync(vec![Statement::Expression(Expression::operator( + BlockExpression::Sync(vec![Statement::Expression(Expression::operator( OperatorExpression::Math { left: Expression::literal(LiteralExpression::Integer(40), (2, 4)), operator: Node::new(MathOperator::Add, (5, 6)), @@ -1579,7 +1575,7 @@ mod tests { parse(source), Ok(AbstractSyntaxTree::with_statements([ Statement::Expression(Expression::block( - Block::Sync(vec![ + BlockExpression::Sync(vec![ Statement::ExpressionNullified(Node::new( Expression::operator( OperatorExpression::Assignment { @@ -1844,7 +1840,7 @@ mod tests { parse(source), Ok(AbstractSyntaxTree::with_statements([ Statement::Expression(Expression::list_index( - ListIndex { + ListIndexExpression { list: Expression::list( ListExpression::Ordered(vec![ Expression::literal(LiteralExpression::Integer(1), (1, 2)), diff --git a/dust-lang/src/type.rs b/dust-lang/src/type.rs index 1fdb90e..300e007 100644 --- a/dust-lang/src/type.rs +++ b/dust-lang/src/type.rs @@ -31,6 +31,7 @@ pub struct TypeConflict { pub enum Type { Any, Boolean, + EmptyList, Enum { name: Identifier, type_parameters: Option>, @@ -251,6 +252,7 @@ impl Display for Type { match self { Type::Any => write!(f, "any"), Type::Boolean => write!(f, "bool"), + Type::EmptyList => write!(f, "[]"), Type::Enum { variants, .. } => { write!(f, "enum ")?; @@ -282,7 +284,7 @@ impl Display for Type { } Type::Integer => write!(f, "int"), Type::List { item_type, length } => write!(f, "[{item_type}; {length}]"), - Type::ListOf { item_type } => write!(f, "list_of({item_type})"), + Type::ListOf { item_type } => write!(f, "[{item_type}]"), Type::Map(map) => { write!(f, "{{ ")?; diff --git a/dust-lang/src/value.rs b/dust-lang/src/value.rs index 01ccd9e..2d29cbe 100644 --- a/dust-lang/src/value.rs +++ b/dust-lang/src/value.rs @@ -241,17 +241,17 @@ impl Value { } pub fn get_field(&self, field: &Identifier) -> Option { - return match self { + match self { Value::Immutable(inner) => inner.get_field(field), Value::Mutable(inner) => inner.read().unwrap().get_field(field), - }; + } } pub fn get_index(&self, index: usize) -> Option { - return match self { + match self { Value::Immutable(inner) => inner.get_index(index), Value::Mutable(inner) => inner.read().unwrap().get_index(index), - }; + } } pub fn add(&self, other: &Value) -> Result { diff --git a/dust-lang/src/vm.rs b/dust-lang/src/vm.rs index beb949f..77dc301 100644 --- a/dust-lang/src/vm.rs +++ b/dust-lang/src/vm.rs @@ -5,19 +5,20 @@ //! - `run_with_context` convenience function that takes a source code string and a context //! - `Vm` struct that can be used to run an abstract syntax tree use std::{ - collections::BTreeMap, fmt::{self, Display, Formatter}, + sync::{Arc, Mutex}, }; -use rayon::iter::{IntoParallelIterator, ParallelIterator}; +use rayon::iter::{IndexedParallelIterator, IntoParallelIterator, ParallelIterator}; use crate::{ abstract_tree::{ - AbstractSyntaxTree, Block, CallExpression, ElseExpression, FieldAccess, IfExpression, - ListExpression, Node, Statement, + AbstractSyntaxTree, BlockExpression, CallExpression, ElseExpression, FieldAccessExpression, + IfExpression, ListExpression, ListIndexExpression, LiteralExpression, LoopExpression, Node, + OperatorExpression, Statement, }, parse, Analyzer, BuiltInFunctionError, Context, DustError, Expression, Identifier, ParseError, - Span, Value, ValueError, + Span, Type, Value, ValueError, }; /// Run the source code and return the result. @@ -109,7 +110,9 @@ impl Vm { fn run_statement(&self, statement: Statement) -> Result, VmError> { let position = statement.position(); let result = match statement { - Statement::Expression(expression) => self.run_expression(expression), + Statement::Expression(expression) => self + .run_expression(expression) + .map(|evaluation| evaluation.value()), Statement::ExpressionNullified(expression) => { self.run_expression(expression.inner)?; @@ -125,146 +128,230 @@ impl Vm { }) } - fn run_expression(&self, expression: Expression) -> Result, VmError> { + fn run_expression(&self, expression: Expression) -> Result { let position = expression.position(); - let result = match expression { + let evaluation_result = match expression { Expression::Block(Node { inner, .. }) => self.run_block(*inner), - Expression::Call(Node { inner, .. }) => { - let CallExpression { invoker, arguments } = *inner; - - let invoker_position = invoker.position(); - let invoker_value = if let Some(value) = self.run_expression(invoker)? { - value - } else { - return Err(VmError::ExpectedValue { - position: invoker_position, - }); - }; - - let function = if let Some(function) = invoker_value.as_function() { - function - } else { - return Err(VmError::ExpectedFunction { - actual: invoker_value, - position: invoker_position, - }); - }; - - let mut value_arguments = Vec::new(); - - for argument in arguments { - let position = argument.position(); - - if let Some(value) = self.run_expression(argument)? { - value_arguments.push(value); - } else { - return Err(VmError::ExpectedValue { position }); - } - } - - let context = Context::new(); - - function.call(None, Some(value_arguments), &context) - } - Expression::FieldAccess(Node { inner, .. }) => { - let FieldAccess { container, field } = *inner; - - let container_position = container.position(); - let container_value = if let Some(value) = self.run_expression(container)? { - value - } else { - return Err(VmError::ExpectedValue { - position: container_position, - }); - }; - - Ok(container_value.get_field(&field.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::Identifier(identifier) => { - let value_option = self.context.get_value(&identifier.inner); - - if let Some(value) = value_option { - Ok(Some(value)) - } else { - Err(VmError::UndefinedVariable { identifier }) - } - } + Expression::Identifier(identifier) => self.run_identifier(identifier.inner), Expression::If(if_expression) => self.run_if(*if_expression.inner), Expression::List(list_expression) => self.run_list(*list_expression.inner), - Expression::ListIndex(_) => todo!(), - Expression::Literal(_) => todo!(), - Expression::Loop(_) => todo!(), + Expression::ListIndex(list_index) => self.run_list_index(*list_index.inner), + Expression::Literal(literal) => self.run_literal(*literal.inner), + Expression::Loop(loop_expression) => self.run_loop(*loop_expression.inner), Expression::Operator(_) => todo!(), Expression::Range(_) => todo!(), Expression::Struct(_) => todo!(), Expression::TupleAccess(_) => todo!(), }; - result.map_err(|error| VmError::Trace { + evaluation_result.map_err(|error| VmError::Trace { error: Box::new(error), position, }) } - fn run_list(&self, list_expression: ListExpression) -> Result, VmError> { + fn run_operator(&self, operator: OperatorExpression) -> Result { + match operator { + OperatorExpression::Assignment { assignee, value } => todo!(), + OperatorExpression::Comparison { + left, + operator, + right, + } => todo!(), + OperatorExpression::CompoundAssignment { + assignee, + operator, + modifier, + } => todo!(), + OperatorExpression::ErrorPropagation(_) => todo!(), + OperatorExpression::Negation(_) => todo!(), + OperatorExpression::Not(_) => todo!(), + OperatorExpression::Math { + left, + operator, + right, + } => todo!(), + OperatorExpression::Logic { + left, + operator, + right, + } => todo!(), + } + } + + fn run_loop(&self, loop_expression: LoopExpression) -> Result { + match loop_expression { + LoopExpression::Infinite { block } => loop { + self.run_expression(Expression::block(block.inner.clone(), block.position))?; + }, + LoopExpression::While { condition, block } => todo!(), + LoopExpression::For { + identifier, + iterator, + block, + } => todo!(), + } + } + + fn run_literal(&self, literal: LiteralExpression) -> Result { + let value = match literal { + LiteralExpression::Boolean(boolean) => Value::boolean(boolean), + LiteralExpression::Float(float) => Value::float(float), + LiteralExpression::Integer(integer) => Value::integer(integer), + LiteralExpression::String(string) => Value::string(string), + LiteralExpression::Value(value) => value, + }; + + Ok(Evaluation::Return(Some(value))) + } + + fn run_list_index(&self, list_index: ListIndexExpression) -> Result { + let ListIndexExpression { list, index } = list_index; + + let list_position = list.position(); + let list_value = self.run_expression(list)?.expect_value(list_position)?; + + let index_position = index.position(); + let index_value = self.run_expression(index)?.expect_value(index_position)?; + + let index = if let Some(index) = index_value.as_integer() { + index as usize + } else { + return Err(VmError::ExpectedInteger { + position: index_position, + }); + }; + + let value_option = list_value.get_index(index); + + Ok(Evaluation::Return(value_option)) + } + + fn run_call(&self, call_expression: CallExpression) -> Result { + let CallExpression { invoker, arguments } = call_expression; + + let invoker_position = invoker.position(); + let invoker_value = if let Some(value) = self.run_expression(invoker)?.value() { + value + } else { + return Err(VmError::ExpectedValue { + position: invoker_position, + }); + }; + + let function = if let Some(function) = invoker_value.as_function() { + function + } else { + return Err(VmError::ExpectedFunction { + actual: invoker_value, + position: invoker_position, + }); + }; + + let mut value_arguments = Vec::new(); + + for argument in arguments { + let position = argument.position(); + + if let Some(value) = self.run_expression(argument)?.value() { + value_arguments.push(value); + } else { + return Err(VmError::ExpectedValue { position }); + } + } + + let context = Context::new(); + + function + .call(None, Some(value_arguments), &context) + .map(|value_option| Evaluation::Return(value_option)) + } + + fn run_field_access(&self, field_access: FieldAccessExpression) -> Result { + let FieldAccessExpression { container, field } = field_access; + + let container_position = container.position(); + let container_value = if let Some(value) = self.run_expression(container)?.value() { + value + } else { + return Err(VmError::ExpectedValue { + position: container_position, + }); + }; + + Ok(Evaluation::Return(container_value.get_field(&field.inner))) + } + + fn run_identifier(&self, identifier: Identifier) -> Result { + let value_option = self.context.get_value(&identifier); + + if let Some(value) = value_option { + Ok(Evaluation::Return(Some(value))) + } else { + Err(VmError::UndefinedVariable { identifier }) + } + } + + fn run_list(&self, list_expression: ListExpression) -> Result { 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 length = self + .run_expression(length_operand)? + .expect_value(position)? + .as_integer() + .ok_or(VmError::ExpectedInteger { position })?; let position = repeat_operand.position(); - let value = if let Some(value) = self.run_expression(repeat_operand)? { - value - } else { - return Err(VmError::ExpectedValue { position }); - }; + let value = self + .run_expression(repeat_operand)? + .expect_value(position)?; - Ok(Some(Value::list(vec![value; length as usize]))) + Ok(Evaluation::Return(Some(Value::list(vec![ + value; + length as usize + ])))) } ListExpression::Ordered(expressions) => { let mut values = Vec::new(); for expression in expressions { let position = expression.position(); + let value = self.run_expression(expression)?.expect_value(position)?; - if let Some(value) = self.run_expression(expression)? { - values.push(value); - } else { - return Err(VmError::ExpectedValue { position }); - } + values.push(value); } - Ok(Some(Value::list(values))) + Ok(Evaluation::Return(Some(Value::list(values)))) } } } - fn run_block(&self, block: Block) -> Result, VmError> { + fn run_block(&self, block: BlockExpression) -> Result { match block { - Block::Async(statements) => { + BlockExpression::Async(statements) => { + let expected_return = statements.last().unwrap().expected_type(); + + let final_result = Arc::new(Mutex::new(None)); + let error_option = statements .into_par_iter() + .enumerate() .find_map_any(|statement| self.run_statement(statement).err()); if let Some(error) = error_option { Err(error) } else { - Ok(None) + Ok(Evaluation::Return(None)) } } - Block::Sync(statements) => { + BlockExpression::Sync(statements) => { let mut previous_value = None; for statement in statements { @@ -275,60 +362,44 @@ impl Vm { self.context.collect_garbage(position.1); } - Ok(previous_value) + Ok(Evaluation::Return(previous_value)) } } } - fn run_if(&self, if_expression: IfExpression) -> Result, VmError> { + fn run_if(&self, if_expression: IfExpression) -> Result { 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, - }); - }; + let position = condition.position(); + let boolean = self + .run_expression(condition)? + .expect_value(position)? + .as_boolean() + .ok_or(VmError::ExpectedBoolean { 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, - }); + if boolean { + self.run_expression(Expression::block(if_block.inner, if_block.position))?; } - Ok(None) + Ok(Evaluation::Return(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, - }); - }; + let position = condition.position(); + let boolean = self + .run_expression(condition)? + .expect_value(position)? + .as_boolean() + .ok_or(VmError::ExpectedBoolean { 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, - }); + if boolean { + self.run_expression(Expression::block(if_block.inner, if_block.position))?; } match r#else { @@ -344,6 +415,28 @@ impl Vm { } } +enum Evaluation { + Break, + Return(Option), +} + +impl Evaluation { + pub fn value(self) -> Option { + match self { + Evaluation::Break => None, + Evaluation::Return(value_option) => value_option, + } + } + + pub fn expect_value(self, position: Span) -> Result { + if let Evaluation::Return(Some(value)) = self { + Ok(value) + } else { + Err(VmError::ExpectedValue { position }) + } + } +} + #[derive(Clone, Debug, PartialEq)] pub enum VmError { ParseError(ParseError), @@ -398,7 +491,7 @@ pub enum VmError { position: Span, }, UndefinedVariable { - identifier: Node, + identifier: Identifier, }, UndefinedProperty { value: Value, @@ -408,32 +501,6 @@ pub enum VmError { }, } -impl VmError { - pub fn position(&self) -> Span { - match self { - Self::ParseError(parse_error) => parse_error.position(), - Self::Trace { position, .. } => *position, - Self::ValueError { position, .. } => *position, - Self::CannotMutate { position, .. } => *position, - Self::BuiltInFunctionError { position, .. } => *position, - Self::ExpectedBoolean { position } => *position, - Self::ExpectedIdentifier { position } => *position, - Self::ExpectedIdentifierOrString { position } => *position, - Self::ExpectedIntegerOrRange { position } => *position, - Self::ExpectedInteger { position } => *position, - Self::ExpectedFunction { position, .. } => *position, - Self::ExpectedList { position } => *position, - Self::ExpectedMap { position } => *position, - Self::ExpectedNumber { position } => *position, - Self::ExpectedValue { position } => *position, - Self::UndefinedVariable { identifier } => identifier.position, - Self::UndefinedProperty { - property_position, .. - } => *property_position, - } - } -} - impl From for VmError { fn from(error: ParseError) -> Self { Self::ParseError(error)