From a28ac297c1a128ff5775b2ed46fa6ed1c4e2b0a4 Mon Sep 17 00:00:00 2001 From: Jeff Date: Fri, 21 Jun 2024 18:28:12 -0400 Subject: [PATCH] Refactor abstract tree traits --- dust-lang/src/abstract_tree/as.rs | 6 +- dust-lang/src/abstract_tree/assignment.rs | 19 +++-- dust-lang/src/abstract_tree/async_block.rs | 28 +++---- dust-lang/src/abstract_tree/block.rs | 18 +++-- .../abstract_tree/built_in_function_call.rs | 10 ++- .../src/abstract_tree/enum_declaration.rs | 24 ++---- dust-lang/src/abstract_tree/expression.rs | 6 +- dust-lang/src/abstract_tree/function_call.rs | 6 +- dust-lang/src/abstract_tree/if_else.rs | 24 +++--- dust-lang/src/abstract_tree/list_index.rs | 10 ++- dust-lang/src/abstract_tree/logic.rs | 6 +- dust-lang/src/abstract_tree/loop.rs | 18 ++--- dust-lang/src/abstract_tree/map_index.rs | 10 ++- dust-lang/src/abstract_tree/math.rs | 6 +- dust-lang/src/abstract_tree/mod.rs | 28 +++++-- dust-lang/src/abstract_tree/statement.rs | 77 +++++++++---------- .../src/abstract_tree/structure_definition.rs | 24 ++---- dust-lang/src/abstract_tree/type.rs | 26 +------ dust-lang/src/abstract_tree/type_alias.rs | 24 ++---- dust-lang/src/abstract_tree/value_node.rs | 7 +- dust-lang/src/abstract_tree/while.rs | 20 ++--- dust-lang/src/context.rs | 27 +++---- dust-lang/src/error.rs | 34 ++++---- dust-lang/src/value.rs | 10 ++- 24 files changed, 227 insertions(+), 241 deletions(-) diff --git a/dust-lang/src/abstract_tree/as.rs b/dust-lang/src/abstract_tree/as.rs index 616910e..b41a115 100644 --- a/dust-lang/src/abstract_tree/as.rs +++ b/dust-lang/src/abstract_tree/as.rs @@ -9,7 +9,7 @@ use crate::{ Value, }; -use super::{Evaluate, Evaluation, ExpectedType, Expression, Type, TypeConstructor}; +use super::{Evaluate, Evaluation, ExpectedType, Expression, Type, TypeConstructor, Validate}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub struct As { @@ -26,7 +26,7 @@ impl As { } } -impl Evaluate for As { +impl Validate for As { fn validate( &self, _context: &mut Context, @@ -44,7 +44,9 @@ impl Evaluate for As { Ok(()) } +} +impl Evaluate for As { fn evaluate( self, context: &mut Context, diff --git a/dust-lang/src/abstract_tree/assignment.rs b/dust-lang/src/abstract_tree/assignment.rs index 473bcad..c6139f1 100644 --- a/dust-lang/src/abstract_tree/assignment.rs +++ b/dust-lang/src/abstract_tree/assignment.rs @@ -9,7 +9,8 @@ use crate::{ use super::{ type_constructor::{RawTypeConstructor, TypeInvokationConstructor}, - Evaluate, Evaluation, ExpectedType, Expression, Statement, Type, TypeConstructor, WithPosition, + Evaluation, ExpectedType, Expression, Run, Statement, Type, TypeConstructor, Validate, + WithPosition, }; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] @@ -43,7 +44,7 @@ impl Assignment { } } -impl Evaluate for Assignment { +impl Validate for Assignment { fn validate(&self, context: &mut Context, manage_memory: bool) -> Result<(), ValidationError> { if let Some(TypeConstructor::Raw(WithPosition { node: RawTypeConstructor::None, @@ -136,16 +137,18 @@ impl Evaluate for Assignment { Ok(()) } +} - fn evaluate( +impl Run for Assignment { + fn run( self, context: &mut Context, manage_memory: bool, - ) -> Result { - let evaluation = self.statement.evaluate(context, manage_memory)?; + ) -> Result, RuntimeError> { + let evaluation = self.statement.run(context, manage_memory)?; let right = match evaluation { - Evaluation::Return(value) => value, - r#break => return Ok(r#break), + Some(Evaluation::Return(value)) => value, + evaluation => return Ok(evaluation), }; match self.operator { @@ -244,6 +247,6 @@ impl Evaluate for Assignment { } } - Ok(Evaluation::None) + Ok(Some(Evaluation::Void)) } } diff --git a/dust-lang/src/abstract_tree/async_block.rs b/dust-lang/src/abstract_tree/async_block.rs index 9638eb7..a0a9672 100644 --- a/dust-lang/src/abstract_tree/async_block.rs +++ b/dust-lang/src/abstract_tree/async_block.rs @@ -1,14 +1,14 @@ -use std::sync::RwLock; +use std::sync::Mutex; use rayon::prelude::*; use serde::{Deserialize, Serialize}; use crate::{ context::Context, - error::{RuntimeError, RwLockPoisonError, ValidationError}, + error::{PoisonError, RuntimeError, ValidationError}, }; -use super::{Evaluate, Evaluation, ExpectedType, Statement, Type}; +use super::{Evaluation, ExpectedType, Run, Statement, Type, Validate}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub struct AsyncBlock { @@ -21,7 +21,7 @@ impl AsyncBlock { } } -impl Evaluate for AsyncBlock { +impl Validate for AsyncBlock { fn validate(&self, _context: &mut Context, manage_memory: bool) -> Result<(), ValidationError> { for statement in &self.statements { statement.validate(_context, manage_memory)?; @@ -29,30 +29,32 @@ impl Evaluate for AsyncBlock { Ok(()) } +} - fn evaluate( +impl Run for AsyncBlock { + fn run( self, _context: &mut Context, _manage_memory: bool, - ) -> Result { + ) -> Result, RuntimeError> { let statement_count = self.statements.len(); - let final_result = RwLock::new(Ok(Evaluation::None)); + let final_result = Mutex::new(Ok(None)); self.statements .into_par_iter() .enumerate() - .find_map_first(|(index, statement)| { - let result = statement.evaluate(&mut _context.clone(), false); + .find_map_any(|(index, statement)| { + let result = statement.run(&mut _context.clone(), false); if index == statement_count - 1 { - let get_write_lock = final_result.write(); + let get_write_lock = final_result.lock(); match get_write_lock { Ok(mut final_result) => { *final_result = result; None } - Err(_error) => Some(Err(RuntimeError::RwLockPoison(RwLockPoisonError))), + Err(_error) => Some(Err(RuntimeError::RwLockPoison(PoisonError))), } } else { None @@ -61,8 +63,8 @@ impl Evaluate for AsyncBlock { .unwrap_or( final_result .into_inner() - .map_err(|_| RuntimeError::RwLockPoison(RwLockPoisonError))?, - ) + .map_err(|_| RuntimeError::RwLockPoison(PoisonError)), + )? } } diff --git a/dust-lang/src/abstract_tree/block.rs b/dust-lang/src/abstract_tree/block.rs index 3371211..33d97a6 100644 --- a/dust-lang/src/abstract_tree/block.rs +++ b/dust-lang/src/abstract_tree/block.rs @@ -5,7 +5,7 @@ use crate::{ error::{RuntimeError, ValidationError}, }; -use super::{Evaluate, Evaluation, ExpectedType, Statement, Type}; +use super::{Evaluation, ExpectedType, Run, Statement, Type, Validate}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub struct Block { @@ -26,7 +26,7 @@ impl Block { } } -impl Evaluate for Block { +impl Validate for Block { fn validate( &self, _context: &mut Context, @@ -38,16 +38,18 @@ impl Evaluate for Block { Ok(()) } +} - fn evaluate( +impl Run for Block { + fn run( self, _context: &mut Context, _manage_memory: bool, - ) -> Result { - let mut previous = Evaluation::None; + ) -> Result, RuntimeError> { + let mut previous = None; for statement in self.statements { - previous = statement.evaluate(_context, _manage_memory)?; + previous = statement.run(_context, _manage_memory)?; } Ok(previous) @@ -84,8 +86,8 @@ mod tests { ]); assert_eq!( - block.evaluate(&mut Context::new(None), true).unwrap(), - Evaluation::Return(Value::integer(42)) + block.run(&mut Context::new(None), true).unwrap(), + Some(Evaluation::Return(Value::integer(42))) ) } diff --git a/dust-lang/src/abstract_tree/built_in_function_call.rs b/dust-lang/src/abstract_tree/built_in_function_call.rs index 66fc59d..34ef1af 100644 --- a/dust-lang/src/abstract_tree/built_in_function_call.rs +++ b/dust-lang/src/abstract_tree/built_in_function_call.rs @@ -14,7 +14,7 @@ use crate::{ Value, }; -use super::{Evaluate, Evaluation, ExpectedType, Expression, Type, TypeConstructor}; +use super::{Evaluate, Evaluation, ExpectedType, Expression, Type, TypeConstructor, Validate}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub enum BuiltInFunctionCall { @@ -26,7 +26,7 @@ pub enum BuiltInFunctionCall { WriteLine(Expression), } -impl Evaluate for BuiltInFunctionCall { +impl Validate for BuiltInFunctionCall { fn validate( &self, _context: &mut Context, @@ -49,7 +49,9 @@ impl Evaluate for BuiltInFunctionCall { } } } +} +impl Evaluate for BuiltInFunctionCall { fn evaluate( self, context: &mut Context, @@ -136,7 +138,7 @@ impl Evaluate for BuiltInFunctionCall { thread::sleep(Duration::from_millis(*milliseconds as u64)); } - Ok(Evaluation::None) + Ok(Evaluation::Void) } BuiltInFunctionCall::WriteLine(expression) => { let action = expression.clone().evaluate(context, _manage_memory)?; @@ -156,7 +158,7 @@ impl Evaluate for BuiltInFunctionCall { stdout.flush()?; } - Ok(Evaluation::None) + Ok(Evaluation::Void) } } } diff --git a/dust-lang/src/abstract_tree/enum_declaration.rs b/dust-lang/src/abstract_tree/enum_declaration.rs index 41fe7d9..a05cc62 100644 --- a/dust-lang/src/abstract_tree/enum_declaration.rs +++ b/dust-lang/src/abstract_tree/enum_declaration.rs @@ -1,12 +1,8 @@ use serde::{Deserialize, Serialize}; -use crate::{ - context::Context, - error::{RuntimeError, ValidationError}, - identifier::Identifier, -}; +use crate::{context::Context, error::RuntimeError, identifier::Identifier}; -use super::{Evaluate, Evaluation, Type, TypeConstructor, WithPosition}; +use super::{Evaluation, Run, Type, TypeConstructor, WithPosition}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub struct EnumDeclaration { @@ -29,20 +25,12 @@ impl EnumDeclaration { } } -impl Evaluate for EnumDeclaration { - fn validate( - &self, - _context: &mut Context, - _manage_memory: bool, - ) -> Result<(), ValidationError> { - Ok(()) - } - - fn evaluate( +impl Run for EnumDeclaration { + fn run( self, context: &mut Context, _manage_memory: bool, - ) -> Result { + ) -> Result, RuntimeError> { let EnumDeclaration { name, type_parameters, @@ -86,7 +74,7 @@ impl Evaluate for EnumDeclaration { context.set_type(name.node, r#type)?; - Ok(Evaluation::None) + Ok(None) } } diff --git a/dust-lang/src/abstract_tree/expression.rs b/dust-lang/src/abstract_tree/expression.rs index 6d77c73..53acc20 100644 --- a/dust-lang/src/abstract_tree/expression.rs +++ b/dust-lang/src/abstract_tree/expression.rs @@ -8,7 +8,7 @@ use crate::{ use super::{ As, BuiltInFunctionCall, Evaluate, Evaluation, ExpectedType, FunctionCall, ListIndex, Logic, - MapIndex, Math, SourcePosition, Type, ValueNode, WithPosition, + MapIndex, Math, SourcePosition, Type, Validate, ValueNode, WithPosition, }; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] @@ -40,7 +40,7 @@ impl Expression { } } -impl Evaluate for Expression { +impl Validate for Expression { fn validate(&self, context: &mut Context, manage_memory: bool) -> Result<(), ValidationError> { match self { Expression::As(r#as) => r#as.node.validate(context, manage_memory), @@ -73,7 +73,9 @@ impl Evaluate for Expression { Expression::Value(value_node) => value_node.node.validate(context, manage_memory), } } +} +impl Evaluate for Expression { fn evaluate( self, context: &mut Context, diff --git a/dust-lang/src/abstract_tree/function_call.rs b/dust-lang/src/abstract_tree/function_call.rs index 9fa6fa4..a76b885 100644 --- a/dust-lang/src/abstract_tree/function_call.rs +++ b/dust-lang/src/abstract_tree/function_call.rs @@ -6,7 +6,7 @@ use crate::{ value::ValueInner, }; -use super::{Evaluate, Evaluation, ExpectedType, Expression, Type, TypeConstructor}; +use super::{Evaluate, Evaluation, ExpectedType, Expression, Type, TypeConstructor, Validate}; #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub struct FunctionCall { @@ -33,7 +33,7 @@ impl FunctionCall { } } -impl Evaluate for FunctionCall { +impl Validate for FunctionCall { fn validate(&self, context: &mut Context, manage_memory: bool) -> Result<(), ValidationError> { self.function.validate(context, manage_memory)?; @@ -69,7 +69,9 @@ impl Evaluate for FunctionCall { }) } } +} +impl Evaluate for FunctionCall { fn evaluate( self, context: &mut Context, diff --git a/dust-lang/src/abstract_tree/if_else.rs b/dust-lang/src/abstract_tree/if_else.rs index d20baf8..d072093 100644 --- a/dust-lang/src/abstract_tree/if_else.rs +++ b/dust-lang/src/abstract_tree/if_else.rs @@ -6,7 +6,9 @@ use crate::{ value::ValueInner, }; -use super::{Block, Evaluate, Evaluation, ExpectedType, Expression, Type, WithPosition}; +use super::{ + Block, Evaluate, Evaluation, ExpectedType, Expression, Run, Type, Validate, WithPosition, +}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub struct IfElse { @@ -32,7 +34,7 @@ impl IfElse { } } -impl Evaluate for IfElse { +impl Validate for IfElse { fn validate(&self, context: &mut Context, manage_memory: bool) -> Result<(), ValidationError> { self.if_expression.validate(context, manage_memory)?; self.if_block.node.validate(context, manage_memory)?; @@ -88,12 +90,14 @@ impl Evaluate for IfElse { Ok(()) } +} - fn evaluate( +impl Run for IfElse { + fn run( self, context: &mut Context, _manage_memory: bool, - ) -> Result { + ) -> Result, RuntimeError> { let if_position = self.if_expression.position(); let action = self.if_expression.evaluate(context, _manage_memory)?; let value = if let Evaluation::Return(value) = action { @@ -106,7 +110,7 @@ impl Evaluate for IfElse { if let ValueInner::Boolean(if_boolean) = value.inner().as_ref() { if *if_boolean { - return self.if_block.node.evaluate(context, _manage_memory); + return self.if_block.node.run(context, _manage_memory); } if let Some(else_ifs) = self.else_ifs { @@ -123,7 +127,7 @@ impl Evaluate for IfElse { if let ValueInner::Boolean(else_if_boolean) = value.inner().as_ref() { if *else_if_boolean { - return block.node.evaluate(context, _manage_memory); + return block.node.run(context, _manage_memory); } } else { return Err(RuntimeError::ValidationFailure( @@ -137,9 +141,9 @@ impl Evaluate for IfElse { } if let Some(else_statement) = self.else_block { - else_statement.node.evaluate(context, _manage_memory) + else_statement.node.run(context, _manage_memory) } else { - Ok(Evaluation::None) + Ok(None) } } else { Err(RuntimeError::ValidationFailure( @@ -179,9 +183,9 @@ mod tests { Some(Vec::with_capacity(0)), None ) - .evaluate(&mut Context::new(None), true) + .run(&mut Context::new(None), true) .unwrap(), - Evaluation::Return(Value::string("foo".to_string())) + Some(Evaluation::Return(Value::string("foo".to_string()))) ) } } diff --git a/dust-lang/src/abstract_tree/list_index.rs b/dust-lang/src/abstract_tree/list_index.rs index 0bbe1e7..b6fd29a 100644 --- a/dust-lang/src/abstract_tree/list_index.rs +++ b/dust-lang/src/abstract_tree/list_index.rs @@ -5,7 +5,9 @@ use crate::{ error::{RuntimeError, ValidationError}, }; -use super::{Evaluate, Evaluation, ExpectedType, Expression, Type, ValueNode, WithPosition}; +use super::{ + Evaluate, Evaluation, ExpectedType, Expression, Type, Validate, ValueNode, WithPosition, +}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub struct ListIndex { @@ -22,7 +24,7 @@ impl ListIndex { } } -impl Evaluate for ListIndex { +impl Validate for ListIndex { fn validate(&self, context: &mut Context, _manage_memory: bool) -> Result<(), ValidationError> { self.collection.validate(context, _manage_memory)?; self.index.validate(context, _manage_memory)?; @@ -53,7 +55,9 @@ impl Evaluate for ListIndex { }), } } +} +impl Evaluate for ListIndex { fn evaluate( self, context: &mut Context, @@ -84,7 +88,7 @@ impl Evaluate for ListIndex { if let Some(item) = found_item { Ok(Evaluation::Return(item.clone())) } else { - Ok(Evaluation::None) + Ok(Evaluation::Void) } } else { Err(RuntimeError::ValidationFailure( diff --git a/dust-lang/src/abstract_tree/logic.rs b/dust-lang/src/abstract_tree/logic.rs index 3397d9b..655f954 100644 --- a/dust-lang/src/abstract_tree/logic.rs +++ b/dust-lang/src/abstract_tree/logic.rs @@ -7,7 +7,7 @@ use crate::{ Value, }; -use super::{Evaluate, Evaluation, ExpectedType, Expression, Type}; +use super::{Evaluate, Evaluation, ExpectedType, Expression, Type, Validate}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub enum Logic { @@ -22,7 +22,7 @@ pub enum Logic { Not(Expression), } -impl Evaluate for Logic { +impl Validate for Logic { fn validate(&self, context: &mut Context, _manage_memory: bool) -> Result<(), ValidationError> { match self { Logic::Equal(left, right) @@ -88,7 +88,9 @@ impl Evaluate for Logic { } } } +} +impl Evaluate for Logic { fn evaluate( self, context: &mut Context, diff --git a/dust-lang/src/abstract_tree/loop.rs b/dust-lang/src/abstract_tree/loop.rs index 72d04dc..e591952 100644 --- a/dust-lang/src/abstract_tree/loop.rs +++ b/dust-lang/src/abstract_tree/loop.rs @@ -5,7 +5,7 @@ use crate::{ error::{RuntimeError, ValidationError}, }; -use super::{Evaluate, Evaluation, Statement}; +use super::{Evaluation, Run, Statement, Validate}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub struct Loop { @@ -22,7 +22,7 @@ impl Loop { } } -impl Evaluate for Loop { +impl Validate for Loop { fn validate( &self, _context: &mut Context, @@ -34,20 +34,20 @@ impl Evaluate for Loop { Ok(()) } +} - fn evaluate( +impl Run for Loop { + fn run( self, _context: &mut Context, _manage_memory: bool, - ) -> Result { + ) -> Result, RuntimeError> { loop { for statement in &self.statements { - let action = statement.clone().evaluate(_context, false)?; + let run = statement.clone().run(_context, false)?; - match action { - Evaluation::Return(_) => {} - Evaluation::None => {} - Evaluation::Break => return Ok(Evaluation::Break), + if let Some(Evaluation::Break) = run { + return Ok(run); } } } diff --git a/dust-lang/src/abstract_tree/map_index.rs b/dust-lang/src/abstract_tree/map_index.rs index 3453bdb..3f6f861 100644 --- a/dust-lang/src/abstract_tree/map_index.rs +++ b/dust-lang/src/abstract_tree/map_index.rs @@ -6,7 +6,9 @@ use crate::{ value::ValueInner, }; -use super::{Evaluate, Evaluation, ExpectedType, Expression, Type, ValueNode, WithPosition}; +use super::{ + Evaluate, Evaluation, ExpectedType, Expression, Type, Validate, ValueNode, WithPosition, +}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub struct MapIndex { @@ -23,7 +25,7 @@ impl MapIndex { } } -impl Evaluate for MapIndex { +impl Validate for MapIndex { fn validate( &self, _context: &mut Context, @@ -31,7 +33,9 @@ impl Evaluate for MapIndex { ) -> Result<(), ValidationError> { self.collection.validate(_context, _manage_memory) } +} +impl Evaluate for MapIndex { fn evaluate( self, context: &mut Context, @@ -53,7 +57,7 @@ impl Evaluate for MapIndex { let action = map .get(&index.node) .map(|value| Evaluation::Return(value.clone())) - .unwrap_or(Evaluation::None); + .unwrap_or(Evaluation::Void); Ok(action) } else { diff --git a/dust-lang/src/abstract_tree/math.rs b/dust-lang/src/abstract_tree/math.rs index ee2b9bd..68c8ca2 100644 --- a/dust-lang/src/abstract_tree/math.rs +++ b/dust-lang/src/abstract_tree/math.rs @@ -7,7 +7,7 @@ use crate::{ Value, }; -use super::{Evaluate, Evaluation, ExpectedType, Expression, SourcePosition, Type}; +use super::{Evaluate, Evaluation, ExpectedType, Expression, SourcePosition, Type, Validate}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub enum Math { @@ -18,7 +18,7 @@ pub enum Math { Modulo(Expression, Expression), } -impl Evaluate for Math { +impl Validate for Math { fn validate(&self, context: &mut Context, _manage_memory: bool) -> Result<(), ValidationError> { match self { Math::Add(left, right) => { @@ -66,7 +66,9 @@ impl Evaluate for Math { } } } +} +impl Evaluate for Math { fn evaluate( self, _context: &mut Context, diff --git a/dust-lang/src/abstract_tree/mod.rs b/dust-lang/src/abstract_tree/mod.rs index 04543a2..e7564e7 100644 --- a/dust-lang/src/abstract_tree/mod.rs +++ b/dust-lang/src/abstract_tree/mod.rs @@ -91,9 +91,10 @@ impl From<(usize, usize)> for SourcePosition { #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord)] pub enum Evaluation { - Return(Value), Break, - None, + Continue, + Return(Value), + Void, } #[derive(Debug, Clone)] @@ -120,12 +121,12 @@ impl AbstractTree { for statement in valid_statements { let position = statement.position(); - let run = statement.evaluate(context, manage_memory); + let run = statement.run(context, manage_memory); match run { - Ok(action) => match action { - Evaluation::Return(value) => previous_value = Some(value), - Evaluation::None => previous_value = None, + Ok(evaluation) => match evaluation { + Some(Evaluation::Return(value)) => previous_value = Some(value), + Some(Evaluation::Void) | None => previous_value = None, _ => {} }, Err(runtime_error) => { @@ -159,7 +160,7 @@ impl AbstractTree { } else if errors.is_empty() { if let Statement::StructureDefinition(_) = statement { let position = statement.position(); - let run = statement.evaluate(context, true); + let run = statement.run(context, true); if let Err(runtime_error) = run { errors.push(DustError::Runtime { @@ -193,8 +194,11 @@ impl Index for AbstractTree { } } -pub trait Evaluate: Sized { +pub trait Validate { fn validate(&self, context: &mut Context, manage_memory: bool) -> Result<(), ValidationError>; +} + +pub trait Evaluate: ExpectedType { fn evaluate( self, context: &mut Context, @@ -202,6 +206,14 @@ pub trait Evaluate: Sized { ) -> Result; } +pub trait Run { + fn run( + self, + context: &mut Context, + manage_memory: bool, + ) -> Result, RuntimeError>; +} + pub trait ExpectedType { fn expected_type(&self, context: &mut Context) -> Result; } diff --git a/dust-lang/src/abstract_tree/statement.rs b/dust-lang/src/abstract_tree/statement.rs index 04b8b8b..1d40a3e 100644 --- a/dust-lang/src/abstract_tree/statement.rs +++ b/dust-lang/src/abstract_tree/statement.rs @@ -7,7 +7,8 @@ use crate::{ use super::{ Assignment, AsyncBlock, Block, EnumDeclaration, Evaluate, Evaluation, ExpectedType, Expression, - IfElse, Loop, SourcePosition, StructureDefinition, Type, TypeAlias, While, WithPosition, + IfElse, Loop, Run, SourcePosition, StructureDefinition, Type, TypeAlias, Validate, While, + WithPosition, }; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] @@ -51,7 +52,41 @@ impl Statement { } } -impl Evaluate for Statement { +impl Run for Statement { + fn run( + self, + context: &mut Context, + manage_memory: bool, + ) -> Result, RuntimeError> { + let result = match self { + Statement::Assignment(assignment) => assignment.node.run(context, manage_memory), + Statement::AsyncBlock(async_block) => async_block.node.run(context, manage_memory), + Statement::Block(block) => block.node.run(context, manage_memory), + Statement::Break(_) => Ok(Some(Evaluation::Break)), + Statement::Expression(expression) => { + let evaluation = expression.evaluate(context, manage_memory)?; + + Ok(Some(evaluation)) + } + Statement::IfElse(if_else) => if_else.node.run(context, manage_memory), + Statement::Loop(r#loop) => r#loop.node.run(context, manage_memory), + Statement::StructureDefinition(structure_definition) => { + structure_definition.node.run(context, manage_memory) + } + Statement::TypeAlias(type_alias) => type_alias.node.run(context, manage_memory), + Statement::EnumDeclaration(type_alias) => type_alias.node.run(context, manage_memory), + Statement::While(r#while) => r#while.node.run(context, manage_memory), + }; + + if manage_memory { + context.clean()?; + } + + result + } +} + +impl Validate for Statement { fn validate( &self, _context: &mut Context, @@ -67,46 +102,10 @@ impl Evaluate for Statement { Statement::Expression(expression) => expression.validate(_context, _manage_memory), Statement::IfElse(if_else) => if_else.node.validate(_context, _manage_memory), Statement::Loop(r#loop) => r#loop.node.validate(_context, _manage_memory), - Statement::StructureDefinition(structure_definition) => { - structure_definition.node.validate(_context, _manage_memory) - } - Statement::TypeAlias(type_alias) => type_alias.node.validate(_context, _manage_memory), - Statement::EnumDeclaration(type_declaration) => { - type_declaration.node.validate(_context, _manage_memory) - } Statement::While(r#while) => r#while.node.validate(_context, _manage_memory), + _ => Ok(()), } } - - fn evaluate( - self, - context: &mut Context, - manage_memory: bool, - ) -> Result { - let result = match self { - Statement::Assignment(assignment) => assignment.node.evaluate(context, manage_memory), - Statement::AsyncBlock(async_block) => async_block.node.evaluate(context, manage_memory), - Statement::Block(block) => block.node.evaluate(context, manage_memory), - Statement::Break(_) => Ok(Evaluation::Break), - Statement::Expression(expression) => expression.evaluate(context, manage_memory), - Statement::IfElse(if_else) => if_else.node.evaluate(context, manage_memory), - Statement::Loop(r#loop) => r#loop.node.evaluate(context, manage_memory), - Statement::StructureDefinition(structure_definition) => { - structure_definition.node.evaluate(context, manage_memory) - } - Statement::TypeAlias(type_alias) => type_alias.node.evaluate(context, manage_memory), - Statement::EnumDeclaration(type_alias) => { - type_alias.node.evaluate(context, manage_memory) - } - Statement::While(r#while) => r#while.node.evaluate(context, manage_memory), - }; - - if manage_memory { - context.clean()?; - } - - result - } } impl ExpectedType for Statement { diff --git a/dust-lang/src/abstract_tree/structure_definition.rs b/dust-lang/src/abstract_tree/structure_definition.rs index 24408af..dc0dd16 100644 --- a/dust-lang/src/abstract_tree/structure_definition.rs +++ b/dust-lang/src/abstract_tree/structure_definition.rs @@ -1,12 +1,8 @@ use serde::{Deserialize, Serialize}; -use crate::{ - context::Context, - error::{RuntimeError, ValidationError}, - identifier::Identifier, -}; +use crate::{context::Context, error::RuntimeError, identifier::Identifier}; -use super::{Evaluate, Evaluation, Type, TypeConstructor}; +use super::{Evaluation, Run, Type, TypeConstructor}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub struct StructureDefinition { @@ -20,20 +16,12 @@ impl StructureDefinition { } } -impl Evaluate for StructureDefinition { - fn validate( - &self, - _context: &mut Context, - _manage_memory: bool, - ) -> Result<(), ValidationError> { - Ok(()) - } - - fn evaluate( +impl Run for StructureDefinition { + fn run( self, context: &mut Context, _manage_memory: bool, - ) -> Result { + ) -> Result, RuntimeError> { let mut fields = Vec::with_capacity(self.fields.len()); for (identifier, constructor) in self.fields { @@ -49,6 +37,6 @@ impl Evaluate for StructureDefinition { context.set_type(self.name, struct_type)?; - Ok(Evaluation::None) + Ok(None) } } diff --git a/dust-lang/src/abstract_tree/type.rs b/dust-lang/src/abstract_tree/type.rs index 273d7ea..052809b 100644 --- a/dust-lang/src/abstract_tree/type.rs +++ b/dust-lang/src/abstract_tree/type.rs @@ -3,13 +3,7 @@ use std::fmt::{self, Display, Formatter}; use clap::error::Result; use serde::{Deserialize, Serialize}; -use crate::{ - context::Context, - error::{RuntimeError, TypeConflict, ValidationError}, - identifier::Identifier, -}; - -use super::{Evaluate, Evaluation}; +use crate::{error::TypeConflict, identifier::Identifier}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub enum Type { @@ -208,24 +202,6 @@ impl Type { } } -impl Evaluate for Type { - fn validate( - &self, - _context: &mut Context, - _manage_memory: bool, - ) -> Result<(), ValidationError> { - Ok(()) - } - - fn evaluate( - self, - _context: &mut Context, - _manage_memory: bool, - ) -> Result { - Ok(Evaluation::None) - } -} - impl Display for Type { fn fmt(&self, f: &mut Formatter) -> fmt::Result { match self { diff --git a/dust-lang/src/abstract_tree/type_alias.rs b/dust-lang/src/abstract_tree/type_alias.rs index 691c1aa..3bd3a99 100644 --- a/dust-lang/src/abstract_tree/type_alias.rs +++ b/dust-lang/src/abstract_tree/type_alias.rs @@ -1,12 +1,8 @@ use serde::{Deserialize, Serialize}; -use crate::{ - context::Context, - error::{RuntimeError, ValidationError}, - identifier::Identifier, -}; +use crate::{context::Context, error::RuntimeError, identifier::Identifier}; -use super::{Evaluate, Evaluation, TypeConstructor, WithPosition}; +use super::{Evaluation, Run, TypeConstructor, WithPosition}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub struct TypeAlias { @@ -23,24 +19,16 @@ impl TypeAlias { } } -impl Evaluate for TypeAlias { - fn validate(&self, context: &mut Context, _manage_memory: bool) -> Result<(), ValidationError> { - let r#type = self.constructor.clone().construct(&context)?; - - context.set_type(self.identifier.node.clone(), r#type)?; - - Ok(()) - } - - fn evaluate( +impl Run for TypeAlias { + fn run( self, context: &mut Context, _manage_memory: bool, - ) -> Result { + ) -> Result, RuntimeError> { let r#type = self.constructor.construct(&context)?; context.set_type(self.identifier.node, r#type)?; - Ok(Evaluation::None) + Ok(None) } } diff --git a/dust-lang/src/abstract_tree/value_node.rs b/dust-lang/src/abstract_tree/value_node.rs index 4dcadf2..1730b80 100644 --- a/dust-lang/src/abstract_tree/value_node.rs +++ b/dust-lang/src/abstract_tree/value_node.rs @@ -10,7 +10,8 @@ use crate::{ }; use super::{ - Block, Evaluate, Evaluation, ExpectedType, Expression, Type, TypeConstructor, WithPosition, + Block, Evaluate, Evaluation, ExpectedType, Expression, Type, TypeConstructor, Validate, + WithPosition, }; #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] @@ -39,7 +40,7 @@ pub enum ValueNode { }, } -impl Evaluate for ValueNode { +impl Validate for ValueNode { fn validate(&self, context: &mut Context, _manage_memory: bool) -> Result<(), ValidationError> { if let ValueNode::EnumInstance { type_name, variant, .. @@ -162,7 +163,9 @@ impl Evaluate for ValueNode { Ok(()) } +} +impl Evaluate for ValueNode { fn evaluate( self, context: &mut Context, diff --git a/dust-lang/src/abstract_tree/while.rs b/dust-lang/src/abstract_tree/while.rs index cf662d6..769176e 100644 --- a/dust-lang/src/abstract_tree/while.rs +++ b/dust-lang/src/abstract_tree/while.rs @@ -7,7 +7,7 @@ use crate::{ Value, }; -use super::{Evaluate, Evaluation, Expression, Statement}; +use super::{Evaluate, Evaluation, Expression, Run, Statement, Validate}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub struct While { @@ -24,7 +24,7 @@ impl While { } } -impl Evaluate for While { +impl Validate for While { fn validate( &self, _context: &mut Context, @@ -38,12 +38,14 @@ impl Evaluate for While { Ok(()) } +} - fn evaluate( +impl Run for While { + fn run( self, _context: &mut Context, _manage_memory: bool, - ) -> Result { + ) -> Result, RuntimeError> { let get_boolean = || -> Result { let expression_position = self.expression.position(); let action = self @@ -62,16 +64,14 @@ impl Evaluate for While { while let ValueInner::Boolean(true) = get_boolean()?.inner().as_ref() { for statement in &self.statements { - let action = statement.clone().evaluate(&mut _context.clone(), false)?; + let evaluation = statement.clone().run(&mut _context.clone(), false)?; - match action { - Evaluation::Return(_) => {} - Evaluation::None => {} - Evaluation::Break => return Ok(Evaluation::Break), + if let Some(Evaluation::Break) = evaluation { + return Ok(evaluation); } } } - Ok(Evaluation::None) + Ok(None) } } diff --git a/dust-lang/src/context.rs b/dust-lang/src/context.rs index d967e77..8433b2b 100644 --- a/dust-lang/src/context.rs +++ b/dust-lang/src/context.rs @@ -5,7 +5,7 @@ use std::{ use crate::{ abstract_tree::Type, - error::{RwLockPoisonError, ValidationError}, + error::{PoisonError, ValidationError}, identifier::Identifier, Value, }; @@ -32,12 +32,11 @@ impl<'a> Context<'a> { pub fn inner( &self, - ) -> Result>, RwLockPoisonError> - { + ) -> Result>, PoisonError> { Ok(self.variables.read()?) } - pub fn contains(&self, identifier: &Identifier) -> Result { + pub fn contains(&self, identifier: &Identifier) -> Result { log::trace!("Checking that {identifier} exists."); if self.variables.read()?.contains_key(identifier) { @@ -66,7 +65,7 @@ impl<'a> Context<'a> { } } - pub fn use_value(&self, identifier: &Identifier) -> Result, RwLockPoisonError> { + pub fn use_value(&self, identifier: &Identifier) -> Result, PoisonError> { if let Some((VariableData::Value(value), usage_data)) = self.variables.read()?.get(identifier) { @@ -83,7 +82,7 @@ impl<'a> Context<'a> { } } - pub fn get_value(&self, identifier: &Identifier) -> Result, RwLockPoisonError> { + pub fn get_value(&self, identifier: &Identifier) -> Result, PoisonError> { if let Some((VariableData::Value(value), _)) = self.variables.read()?.get(identifier) { log::trace!("Getting {identifier}'s value."); @@ -98,7 +97,7 @@ impl<'a> Context<'a> { pub fn get_data( &self, identifier: &Identifier, - ) -> Result, RwLockPoisonError> { + ) -> Result, PoisonError> { if let Some(full_data) = self.variables.read()?.get(identifier) { log::trace!("Getting {identifier}'s value."); @@ -110,7 +109,7 @@ impl<'a> Context<'a> { } } - pub fn set_type(&self, identifier: Identifier, r#type: Type) -> Result<(), RwLockPoisonError> { + pub fn set_type(&self, identifier: Identifier, r#type: Type) -> Result<(), PoisonError> { log::debug!("Setting {identifier} to type {}.", r#type); self.variables @@ -120,11 +119,7 @@ impl<'a> Context<'a> { Ok(()) } - pub fn set_value( - &mut self, - identifier: Identifier, - value: Value, - ) -> Result<(), RwLockPoisonError> { + pub fn set_value(&mut self, identifier: Identifier, value: Value) -> Result<(), PoisonError> { log::debug!("Setting {identifier} to value {value}."); let mut variables = self.variables.write()?; @@ -141,7 +136,7 @@ impl<'a> Context<'a> { Ok(()) } - pub fn clean(&mut self) -> Result<(), RwLockPoisonError> { + pub fn clean(&mut self) -> Result<(), PoisonError> { if *self.is_clean.read()? { return Ok(()); } @@ -169,7 +164,7 @@ impl<'a> Context<'a> { Ok(()) } - pub fn is_clean(&mut self) -> Result { + pub fn is_clean(&mut self) -> Result { if *self.is_clean.read()? { Ok(true) } else { @@ -185,7 +180,7 @@ impl<'a> Context<'a> { } } - pub fn add_expected_use(&self, identifier: &Identifier) -> Result { + pub fn add_expected_use(&self, identifier: &Identifier) -> Result { if let Some((_, usage_data)) = self.variables.read()?.get(identifier) { log::trace!("Adding expected use for variable {identifier}."); diff --git a/dust-lang/src/error.rs b/dust-lang/src/error.rs index b8a03c1..0465ccf 100644 --- a/dust-lang/src/error.rs +++ b/dust-lang/src/error.rs @@ -1,4 +1,4 @@ -use std::{io, sync::PoisonError}; +use std::{io, sync::PoisonError as StdPoisonError}; use chumsky::{prelude::Rich, span::Span}; @@ -53,20 +53,20 @@ impl<'src> From>> for DustError { #[derive(Debug)] pub enum RuntimeError { Io(io::Error), - RwLockPoison(RwLockPoisonError), + RwLockPoison(PoisonError), ValidationFailure(ValidationError), SerdeJson(serde_json::Error), } -impl From for RuntimeError { - fn from(error: RwLockPoisonError) -> Self { +impl From for RuntimeError { + fn from(error: PoisonError) -> Self { RuntimeError::RwLockPoison(error) } } -impl From> for RuntimeError { - fn from(_: PoisonError) -> Self { - RuntimeError::RwLockPoison(RwLockPoisonError) +impl From> for RuntimeError { + fn from(_: StdPoisonError) -> Self { + RuntimeError::RwLockPoison(PoisonError) } } @@ -137,7 +137,7 @@ pub enum ValidationError { position: SourcePosition, }, InterpreterExpectedReturn(SourcePosition), - RwLockPoison(RwLockPoisonError), + RwLockPoison(PoisonError), TypeCheck { /// The mismatch that caused the error. conflict: TypeConflict, @@ -174,24 +174,24 @@ pub enum ValidationError { }, } -impl From for ValidationError { - fn from(error: RwLockPoisonError) -> Self { +impl From for ValidationError { + fn from(error: PoisonError) -> Self { ValidationError::RwLockPoison(error) } } -impl From> for ValidationError { - fn from(_: PoisonError) -> Self { - ValidationError::RwLockPoison(RwLockPoisonError) +impl From> for ValidationError { + fn from(_: StdPoisonError) -> Self { + ValidationError::RwLockPoison(PoisonError) } } #[derive(Debug, PartialEq)] -pub struct RwLockPoisonError; +pub struct PoisonError; -impl From> for RwLockPoisonError { - fn from(_: PoisonError) -> Self { - RwLockPoisonError +impl From> for PoisonError { + fn from(_: StdPoisonError) -> Self { + PoisonError } } diff --git a/dust-lang/src/value.rs b/dust-lang/src/value.rs index d7d11fd..6e5a4cf 100644 --- a/dust-lang/src/value.rs +++ b/dust-lang/src/value.rs @@ -14,7 +14,7 @@ use serde::{ }; use crate::{ - abstract_tree::{Block, Evaluate, Evaluation, Type, WithPosition}, + abstract_tree::{Block, Evaluation, Run, Type, WithPosition}, context::Context, error::{RuntimeError, ValidationError}, identifier::Identifier, @@ -735,6 +735,12 @@ impl Function { context.set_value(identifier.clone(), value)?; } - self.body.evaluate(context, clear_variables) + self.body.run(context, clear_variables).map(|eval_option| { + if let Some(evaluation) = eval_option { + evaluation + } else { + Evaluation::Void + } + }) } }