diff --git a/dust-lang/src/abstract_tree/expression.rs b/dust-lang/src/abstract_tree/expression.rs index 52882e0..e2be0fb 100644 --- a/dust-lang/src/abstract_tree/expression.rs +++ b/dust-lang/src/abstract_tree/expression.rs @@ -11,60 +11,52 @@ use super::{Node, Statement}; #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub enum Expression { - WithBlock(Node>), - WithoutBlock(Node>), + Block(Node>), + Call(Node>), + FieldAccess(Node>), + Grouped(Node>), + Identifier(Node), + If(Node>), + List(Node>), + ListIndex(Node>), + Literal(Node>), + Loop(Node>), + Operator(Node>), + Range(Node>), + Struct(Node>), + TupleAccess(Node>), } impl Expression { pub fn operator(operator_expression: OperatorExpression, position: Span) -> Self { - Expression::WithoutBlock(Node::new( - Box::new(ExpressionWithoutBlock::Operator(operator_expression)), - position, - )) + Self::Operator(Node::new(Box::new(operator_expression), position)) } pub fn range(start: Expression, end: Expression, position: Span) -> Self { - Expression::WithoutBlock(Node::new( - Box::new(ExpressionWithoutBlock::Range(Range { start, end })), - position, - )) + Self::Range(Node::new(Box::new(Range { start, end }), position)) } pub fn call(invoker: Expression, arguments: Vec, position: Span) -> Self { - Expression::WithoutBlock(Node::new( - Box::new(ExpressionWithoutBlock::Call(CallExpression { - invoker, - arguments, - })), + Self::Call(Node::new( + Box::new(CallExpression { invoker, arguments }), position, )) } pub fn field_access(container: Expression, field: Node, position: Span) -> Self { - Expression::WithoutBlock(Node::new( - Box::new(ExpressionWithoutBlock::FieldAccess(FieldAccess { - container, - field, - })), + Self::FieldAccess(Node::new( + Box::new(FieldAccess { container, field }), position, )) } pub fn tuple_access(tuple: Expression, index: Node, position: Span) -> Self { - Expression::WithoutBlock(Node::new( - Box::new(ExpressionWithoutBlock::TupleAccess(TupleAccess { - tuple, - index, - })), - position, - )) + Self::TupleAccess(Node::new(Box::new(TupleAccess { tuple, index }), position)) } pub fn assignment(assignee: Expression, value: Expression, position: Span) -> Self { - Expression::WithoutBlock(Node::new( - Box::new(ExpressionWithoutBlock::Operator( - OperatorExpression::Assignment { assignee, value }, - )), + Self::Operator(Node::new( + Box::new(OperatorExpression::Assignment { assignee, value }), position, )) } @@ -75,14 +67,12 @@ impl Expression { right: Expression, position: Span, ) -> Self { - Expression::WithoutBlock(Node::new( - Box::new(ExpressionWithoutBlock::Operator( - OperatorExpression::Comparison { - left, - operator, - right, - }, - )), + Self::Operator(Node::new( + Box::new(OperatorExpression::Comparison { + left, + operator, + right, + }), position, )) } @@ -93,14 +83,12 @@ impl Expression { modifier: Expression, position: Span, ) -> Self { - Expression::WithoutBlock(Node::new( - Box::new(ExpressionWithoutBlock::Operator( - OperatorExpression::CompoundAssignment { - assignee, - operator, - modifier, - }, - )), + Self::Operator(Node::new( + Box::new(OperatorExpression::CompoundAssignment { + assignee, + operator, + modifier, + }), position, )) } @@ -111,30 +99,26 @@ impl Expression { right: Expression, position: Span, ) -> Self { - Expression::WithoutBlock(Node::new( - Box::new(ExpressionWithoutBlock::Operator(OperatorExpression::Math { + Self::Operator(Node::new( + Box::new(OperatorExpression::Math { left, operator, right, - })), + }), position, )) } pub fn negation(expression: Expression, position: Span) -> Self { - Expression::WithoutBlock(Node::new( - Box::new(ExpressionWithoutBlock::Operator( - OperatorExpression::Negation(expression), - )), + Self::Operator(Node::new( + Box::new(OperatorExpression::Negation(expression)), position, )) } pub fn not(expression: Expression, position: Span) -> Self { - Expression::WithoutBlock(Node::new( - Box::new(ExpressionWithoutBlock::Operator(OperatorExpression::Not( - expression, - ))), + Self::Operator(Node::new( + Box::new(OperatorExpression::Not(expression)), position, )) } @@ -145,37 +129,30 @@ impl Expression { right: Expression, position: Span, ) -> Self { - Expression::WithoutBlock(Node::new( - Box::new(ExpressionWithoutBlock::Operator( - OperatorExpression::Logic { - left, - operator, - right, - }, - )), + Self::Operator(Node::new( + Box::new(OperatorExpression::Logic { + left, + operator, + right, + }), position, )) } pub fn error_propagation(expression: Expression, position: Span) -> Self { - Expression::WithoutBlock(Node::new( - Box::new(ExpressionWithoutBlock::Operator( - OperatorExpression::ErrorPropagation(expression), - )), + Self::Operator(Node::new( + Box::new(OperatorExpression::ErrorPropagation(expression)), position, )) } pub fn infinite_loop(block: Node, position: Span) -> Self { - Expression::WithBlock(Node::new( - Box::new(ExpressionWithBlock::Loop(Loop::Infinite { block })), - position, - )) + Self::Loop(Node::new(Box::new(Loop::Infinite { block }), position)) } pub fn while_loop(condition: Expression, block: Node, position: Span) -> Self { - Expression::WithBlock(Node::new( - Box::new(ExpressionWithBlock::Loop(Loop::While { condition, block })), + Self::Loop(Node::new( + Box::new(Loop::While { condition, block }), position, )) } @@ -186,82 +163,51 @@ impl Expression { block: Node, position: Span, ) -> Self { - Expression::WithBlock(Node::new( - Box::new(ExpressionWithBlock::Loop(Loop::For { + Self::Loop(Node::new( + Box::new(Loop::For { identifier, iterator, block, - })), + }), position, )) } pub fn block(block: Block, position: Span) -> Self { - Expression::WithBlock(Node::new( - Box::new(ExpressionWithBlock::Block(block)), - position, - )) + Self::Block(Node::new(Box::new(block), position)) } pub fn grouped(expression: Expression, position: Span) -> Self { - Expression::WithoutBlock(Node::new( - Box::new(ExpressionWithoutBlock::Grouped(expression)), - position, - )) + Self::Grouped(Node::new(Box::new(expression), position)) } pub fn r#struct(struct_expression: StructExpression, position: Span) -> Self { - Expression::WithoutBlock(Node::new( - Box::new(ExpressionWithoutBlock::Struct(struct_expression)), - position, - )) + Self::Struct(Node::new(Box::new(struct_expression), position)) } pub fn identifier(identifier: Identifier, position: Span) -> Self { - Expression::WithoutBlock(Node::new( - Box::new(ExpressionWithoutBlock::Identifier(identifier)), - position, - )) + Self::Identifier(Node::new(identifier, position)) } pub fn list(list_expression: ListExpression, position: Span) -> Self { - Expression::WithoutBlock(Node::new( - Box::new(ExpressionWithoutBlock::List(list_expression)), - position, - )) + Self::List(Node::new(Box::new(list_expression), position)) } pub fn list_index(list_index: ListIndex, position: Span) -> Self { - Expression::WithoutBlock(Node::new( - Box::new(ExpressionWithoutBlock::ListIndex(list_index)), - position, - )) + Self::ListIndex(Node::new(Box::new(list_index), position)) } pub fn r#if(r#if: If, position: Span) -> Self { - Expression::WithBlock(Node::new(Box::new(ExpressionWithBlock::If(r#if)), position)) + Self::If(Node::new(Box::new(r#if), position)) } pub fn literal(literal: LiteralExpression, position: Span) -> Self { - Expression::WithoutBlock(Node::new( - Box::new(ExpressionWithoutBlock::Literal(literal)), - position, - )) + Self::Literal(Node::new(Box::new(literal), position)) } pub fn as_identifier(&self) -> Option<&Identifier> { - if let Expression::WithoutBlock(Node { - inner: expression_without_block, - .. - }) = self - { - if let ExpressionWithoutBlock::Identifier(identifier) = - expression_without_block.as_ref() - { - Some(identifier) - } else { - None - } + if let Expression::Identifier(identifier) = self { + Some(&identifier.inner) } else { None } @@ -269,8 +215,20 @@ impl Expression { pub fn position(&self) -> Span { match self { - Expression::WithBlock(expression_node) => expression_node.position, - Expression::WithoutBlock(expression_node) => expression_node.position, + Expression::Block(block) => block.position, + Expression::Call(call) => call.position, + Expression::FieldAccess(field_access) => field_access.position, + Expression::Grouped(grouped) => grouped.position, + Expression::Identifier(identifier) => identifier.position, + Expression::If(r#if) => r#if.position, + Expression::List(list) => list.position, + Expression::ListIndex(list_index) => list_index.position, + Expression::Literal(literal) => literal.position, + Expression::Loop(r#loop) => r#loop.position, + Expression::Operator(operator) => operator.position, + Expression::Range(range) => range.position, + Expression::Struct(r#struct) => r#struct.position, + Expression::TupleAccess(tuple_access) => tuple_access.position, } } } @@ -278,58 +236,20 @@ impl Expression { impl Display for Expression { fn fmt(&self, f: &mut Formatter) -> fmt::Result { match self { - Expression::WithBlock(expression) => write!(f, "{}", expression), - Expression::WithoutBlock(expression) => write!(f, "{}", expression), - } - } -} - -#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] -pub enum ExpressionWithBlock { - Block(Block), - Loop(Loop), - If(If), -} - -impl Display for ExpressionWithBlock { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - match self { - ExpressionWithBlock::Block(block) => write!(f, "{}", block), - ExpressionWithBlock::Loop(r#loop) => write!(f, "{}", r#loop), - ExpressionWithBlock::If(r#if) => write!(f, "{}", r#if), - } - } -} - -#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] -pub enum ExpressionWithoutBlock { - Call(CallExpression), - List(ListExpression), - Literal(LiteralExpression), - Identifier(Identifier), - Operator(OperatorExpression), - Struct(StructExpression), - Grouped(Expression), - FieldAccess(FieldAccess), - ListIndex(ListIndex), - Range(Range), - TupleAccess(TupleAccess), -} - -impl Display for ExpressionWithoutBlock { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - match self { - ExpressionWithoutBlock::Call(call_expression) => write!(f, "{}", call_expression), - ExpressionWithoutBlock::List(list) => write!(f, "{}", list), - ExpressionWithoutBlock::Literal(literal) => write!(f, "{}", literal), - ExpressionWithoutBlock::Identifier(identifier) => write!(f, "{}", identifier), - ExpressionWithoutBlock::Operator(expression) => write!(f, "{}", expression), - ExpressionWithoutBlock::Struct(struct_expression) => write!(f, "{}", struct_expression), - ExpressionWithoutBlock::Grouped(expression) => write!(f, "({})", expression), - ExpressionWithoutBlock::FieldAccess(field_access) => write!(f, "{}", field_access), - ExpressionWithoutBlock::ListIndex(list_index) => write!(f, "{}", list_index), - ExpressionWithoutBlock::Range(range) => write!(f, "{}", range), - ExpressionWithoutBlock::TupleAccess(tuple_access) => write!(f, "{}", tuple_access), + Expression::Block(block) => write!(f, "{}", block.inner), + Expression::Call(call) => write!(f, "{}", call.inner), + Expression::FieldAccess(field_access) => write!(f, "{}", field_access.inner), + Expression::Grouped(grouped) => write!(f, "({})", grouped.inner), + Expression::Identifier(identifier) => write!(f, "{}", identifier.inner), + Expression::If(r#if) => write!(f, "{}", r#if.inner), + Expression::List(list) => write!(f, "{}", list.inner), + Expression::ListIndex(list_index) => write!(f, "{}", list_index.inner), + Expression::Literal(literal) => write!(f, "{}", literal.inner), + Expression::Loop(r#loop) => write!(f, "{}", r#loop.inner), + Expression::Operator(operator) => write!(f, "{}", operator.inner), + Expression::Range(range) => write!(f, "{}", range), + Expression::Struct(r#struct) => write!(f, "{}", r#struct.inner), + Expression::TupleAccess(tuple_access) => write!(f, "{}", tuple_access), } } } diff --git a/dust-lang/src/value.rs b/dust-lang/src/value.rs index 5a0ff2a..01ccd9e 100644 --- a/dust-lang/src/value.rs +++ b/dust-lang/src/value.rs @@ -5,7 +5,7 @@ use std::{ error::Error, fmt::{self, Display, Formatter}, ops::Range, - sync::{Arc, RwLock}, + sync::{Arc, RwLock, RwLockWriteGuard}, }; use serde::{ @@ -135,13 +135,6 @@ impl Value { } } - pub fn get_property(&self, property: &Identifier) -> Option { - match self { - Value::Immutable(inner) => inner.get_property(property), - Value::Mutable(inner_locked) => inner_locked.read().unwrap().get_property(property), - } - } - pub fn as_boolean(&self) -> Option { match self { Value::Immutable(arc) => match arc.as_ref() { @@ -211,16 +204,6 @@ impl Value { } } - pub fn as_range(&self) -> Option<&Range> { - if let Value::Immutable(arc) = self { - if let ValueData::Range(range) = arc.as_ref() { - return Some(range); - } - } - - None - } - pub fn as_string(&self) -> Option<&String> { if let Value::Immutable(arc) = self { if let ValueData::String(string) = arc.as_ref() { @@ -231,6 +214,46 @@ impl Value { None } + pub fn as_struct(&self) -> Option<&Struct> { + if let Value::Immutable(arc) = self { + if let ValueData::Struct(r#struct) = arc.as_ref() { + return Some(r#struct); + } + } + + None + } + + pub fn value_data_immutable(&self) -> Option<&ValueData> { + if let Value::Immutable(inner) = self { + Some(inner.as_ref()) + } else { + None + } + } + + pub fn value_data_mutable(&self) -> Option> { + if let Value::Mutable(inner) = self { + Some(inner.write().unwrap()) + } else { + None + } + } + + pub fn get_field(&self, field: &Identifier) -> Option { + return 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 { + Value::Immutable(inner) => inner.get_index(index), + Value::Mutable(inner) => inner.read().unwrap().get_index(index), + }; + } + pub fn add(&self, other: &Value) -> Result { match (self, other) { (Value::Immutable(left), Value::Immutable(right)) => { @@ -998,19 +1021,44 @@ impl ValueData { } } - fn get_property(&self, property: &Identifier) -> Option { - match self { - ValueData::List(list) => { - if property.as_str() == "length" { - Some(Value::integer(list.len() as i64)) + fn get_field(&self, property: &Identifier) -> Option { + if let ValueData::Struct(Struct::Fields { fields, .. }) = self { + fields.iter().find_map(|(identifier, value)| { + if identifier == property { + Some(value.clone()) } else { None } - } - ValueData::Map(value_map) => value_map.get(property).cloned(), - _ => None, + }) + } else { + None } } + + fn get_index(&self, index: usize) -> Option { + if let ValueData::List(list) = self { + return list.get(index).cloned(); + } + + if let ValueData::Range(range) = self { + if range.contains(&(index as i64)) { + return Some(Value::integer(index as i64)); + } + } + + if let ValueData::String(string) = self { + return string + .chars() + .nth(index) + .map(|character| Value::string(character.to_string())); + } + + if let ValueData::Struct(Struct::Tuple { fields, .. }) = self { + return fields.get(index).cloned(); + } + + None + } } impl Display for ValueData { @@ -1407,7 +1455,7 @@ pub struct Function { impl Function { pub fn call( - self, + &self, _type_arguments: Option>, value_arguments: Option>, context: &Context, @@ -1415,14 +1463,14 @@ impl Function { let new_context = Context::with_variables_from(context); 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) { - new_context.set_value(identifier, value); + new_context.set_value(identifier.clone(), value); } } - let mut vm = Vm::new(self.body, new_context); + let mut vm = Vm::new(self.body.clone(), new_context); vm.run() } diff --git a/dust-lang/src/vm.rs b/dust-lang/src/vm.rs index 4750edf..921a474 100644 --- a/dust-lang/src/vm.rs +++ b/dust-lang/src/vm.rs @@ -9,10 +9,12 @@ use std::{ fmt::{self, Display, Formatter}, }; +use rayon::iter::{IntoParallelIterator, ParallelIterator}; + use crate::{ - abstract_tree::{AbstractSyntaxTree, Node, Statement}, - parse, Analyzer, BuiltInFunctionError, Context, DustError, Identifier, ParseError, Span, - Struct, StructType, Type, Value, ValueError, + abstract_tree::{AbstractSyntaxTree, Block, CallExpression, FieldAccess, Node, Statement}, + parse, Analyzer, BuiltInFunctionError, Context, DustError, Expression, Identifier, ParseError, + Span, Struct, StructType, Type, Value, ValueError, }; /// Run the source code and return the result. @@ -101,8 +103,110 @@ impl Vm { Ok(previous_value) } - fn run_statement(&self, node: Statement) -> Result, VmError> { - todo!() + fn run_statement(&self, statement: Statement) -> Result, VmError> { + match statement { + Statement::Expression(expression) => self.run_expression(expression), + Statement::ExpressionNullified(expression) => { + self.run_expression(expression.inner)?; + + Ok(None) + } + Statement::Let(_) => todo!(), + Statement::StructDefinition(_) => todo!(), + } + } + + fn run_expression(&self, expression: Expression) -> Result, VmError> { + match expression { + Expression::Block(Node { inner, position }) => match *inner { + 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) + } + }, + 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::Grouped(_) => todo!(), + Expression::Identifier(_) => todo!(), + Expression::If(_) => todo!(), + Expression::List(_) => todo!(), + Expression::ListIndex(_) => todo!(), + Expression::Literal(_) => todo!(), + Expression::Loop(_) => todo!(), + Expression::Operator(_) => todo!(), + Expression::Range(_) => todo!(), + Expression::Struct(_) => todo!(), + Expression::TupleAccess(_) => todo!(), + } } }