From 8b14d74eba445c6b9097e2cd74701e597e2f9116 Mon Sep 17 00:00:00 2001 From: Jeff Date: Fri, 23 Aug 2024 13:47:22 -0400 Subject: [PATCH] Replace "return_type" methods in AST with new type_evaluation --- dust-lang/src/analyzer.rs | 188 ++++++++++++--------- dust-lang/src/ast/expression.rs | 288 +++++++++++++++++++------------- dust-lang/src/ast/mod.rs | 59 ++++++- dust-lang/src/ast/statement.rs | 20 ++- dust-lang/src/evaluation.rs | 39 +++++ dust-lang/src/lib.rs | 2 + dust-lang/src/vm.rs | 27 +-- 7 files changed, 395 insertions(+), 228 deletions(-) create mode 100644 dust-lang/src/evaluation.rs diff --git a/dust-lang/src/analyzer.rs b/dust-lang/src/analyzer.rs index 6729a87..e791fb9 100644 --- a/dust-lang/src/analyzer.rs +++ b/dust-lang/src/analyzer.rs @@ -91,13 +91,13 @@ impl<'a> Analyzer<'a> { Statement::Let(let_statement) => match &let_statement.inner { LetStatement::Let { identifier, value } | LetStatement::LetMut { identifier, value } => { - let r#type = match value.return_type(&self.context) { - Ok(type_option) => type_option, + let r#type = match value.type_evaluation(&self.context) { Err(ast_error) => { self.errors.push(AnalysisError::AstError(ast_error)); - None + return; } + Ok(evaluation) => evaluation.r#type(), }; if let Some(r#type) = r#type { @@ -196,19 +196,22 @@ impl<'a> Analyzer<'a> { let FieldAccessExpression { container, field } = field_access_expression.inner.as_ref(); - let container_type = match container.return_type(&self.context) { - Ok(Some(r#type)) => r#type, - Ok(None) => { + let evaluation = match container.type_evaluation(&self.context) { + Ok(evaluation) => evaluation, + Err(ast_error) => { + self.errors.push(AnalysisError::AstError(ast_error)); + + return; + } + }; + let container_type = match evaluation.r#type() { + Some(r#type) => r#type, + None => { self.errors .push(AnalysisError::ExpectedValueFromExpression { expression: container.clone(), }); - return; - } - Err(ast_error) => { - self.errors.push(AnalysisError::AstError(ast_error)); - return; } }; @@ -266,25 +269,17 @@ impl<'a> Analyzer<'a> { self.analyze_expression(list, statement_position); self.analyze_expression(index, statement_position); - let list_type = match list.return_type(&self.context) { - Ok(Some(r#type)) => r#type, - Ok(None) => { - self.errors - .push(AnalysisError::ExpectedValueFromExpression { - expression: list.clone(), - }); - - return; - } + let list_type_evaluation = match list.type_evaluation(&self.context) { + Ok(evaluation) => evaluation, Err(ast_error) => { self.errors.push(AnalysisError::AstError(ast_error)); return; } }; - let index_type = match index.return_type(&self.context) { - Ok(Some(r#type)) => r#type, - Ok(None) => { + let list_type = match list_type_evaluation.r#type() { + Some(r#type) => r#type, + None => { self.errors .push(AnalysisError::ExpectedValueFromExpression { expression: list.clone(), @@ -292,12 +287,26 @@ impl<'a> Analyzer<'a> { return; } + }; + let index_type_evaluation = match index.type_evaluation(&self.context) { + Ok(evaluation) => evaluation, Err(ast_error) => { self.errors.push(AnalysisError::AstError(ast_error)); return; } }; + let index_type = match index_type_evaluation.r#type() { + Some(r#type) => r#type, + None => { + self.errors + .push(AnalysisError::ExpectedValueFromExpression { + expression: list.clone(), + }); + + return; + } + }; let literal_type = if let Expression::Literal(Node { inner, .. }) = index { Some(inner.as_ref().clone()) } else { @@ -406,14 +415,29 @@ impl<'a> Analyzer<'a> { self.analyze_expression(assignee, statement_position); self.analyze_expression(modifier, statement_position); + let assignee_type_evaluation = match assignee.type_evaluation(&self.context) { + Ok(evaluation) => evaluation, + Err(ast_error) => { + self.errors.push(AnalysisError::AstError(ast_error)); + + return; + } + }; + let modifier_type_evaluation = match modifier.type_evaluation(&self.context) { + Ok(evaluation) => evaluation, + Err(ast_error) => { + self.errors.push(AnalysisError::AstError(ast_error)); + + return; + } + }; + let (expected_type, actual_type) = match ( - assignee.return_type(&self.context), - modifier.return_type(&self.context), + assignee_type_evaluation.r#type(), + modifier_type_evaluation.r#type(), ) { - (Ok(Some(expected_type)), Ok(Some(actual_type))) => { - (expected_type, actual_type) - } - (Ok(None), Ok(None)) => { + (Some(expected_type), Some(actual_type)) => (expected_type, actual_type), + (None, None) => { self.errors .push(AnalysisError::ExpectedValueFromExpression { expression: assignee.clone(), @@ -424,28 +448,20 @@ impl<'a> Analyzer<'a> { }); return; } - (Ok(None), _) => { + (None, _) => { self.errors .push(AnalysisError::ExpectedValueFromExpression { expression: assignee.clone(), }); return; } - (_, Ok(None)) => { + (_, None) => { self.errors .push(AnalysisError::ExpectedValueFromExpression { expression: modifier.clone(), }); return; } - (Err(ast_error), _) => { - self.errors.push(AnalysisError::AstError(ast_error)); - return; - } - (_, Err(ast_error)) => { - self.errors.push(AnalysisError::AstError(ast_error)); - return; - } }; if actual_type != expected_type { @@ -467,12 +483,29 @@ impl<'a> Analyzer<'a> { self.analyze_expression(left, statement_position); self.analyze_expression(right, statement_position); + let left_type_evaluation = match left.type_evaluation(&self.context) { + Ok(evaluation) => evaluation, + Err(ast_error) => { + self.errors.push(AnalysisError::AstError(ast_error)); + + return; + } + }; + let right_type_evaluation = match right.type_evaluation(&self.context) { + Ok(evaluation) => evaluation, + Err(ast_error) => { + self.errors.push(AnalysisError::AstError(ast_error)); + + return; + } + }; + let (left_type, right_type) = match ( - left.return_type(&self.context), - right.return_type(&self.context), + left_type_evaluation.r#type(), + right_type_evaluation.r#type(), ) { - (Ok(Some(left_type)), Ok(Some(right_type))) => (left_type, right_type), - (Ok(None), Ok(None)) => { + (Some(left_type), Some(right_type)) => (left_type, right_type), + (None, None) => { self.errors .push(AnalysisError::ExpectedValueFromExpression { expression: left.clone(), @@ -483,28 +516,20 @@ impl<'a> Analyzer<'a> { }); return; } - (Ok(None), _) => { + (None, _) => { self.errors .push(AnalysisError::ExpectedValueFromExpression { expression: left.clone(), }); return; } - (_, Ok(None)) => { + (_, None) => { self.errors .push(AnalysisError::ExpectedValueFromExpression { expression: right.clone(), }); return; } - (Err(ast_error), _) => { - self.errors.push(AnalysisError::AstError(ast_error)); - return; - } - (_, Err(ast_error)) => { - self.errors.push(AnalysisError::AstError(ast_error)); - return; - } }; match left_type { @@ -554,12 +579,29 @@ impl<'a> Analyzer<'a> { self.analyze_expression(left, statement_position); self.analyze_expression(right, statement_position); + let left_type_evaluation = match left.type_evaluation(&self.context) { + Ok(evaluation) => evaluation, + Err(ast_error) => { + self.errors.push(AnalysisError::AstError(ast_error)); + + return; + } + }; + let right_type_evaluation = match right.type_evaluation(&self.context) { + Ok(evaluation) => evaluation, + Err(ast_error) => { + self.errors.push(AnalysisError::AstError(ast_error)); + + return; + } + }; + let (left_type, right_type) = match ( - left.return_type(&self.context), - right.return_type(&self.context), + left_type_evaluation.r#type(), + right_type_evaluation.r#type(), ) { - (Ok(Some(left_type)), Ok(Some(right_type))) => (left_type, right_type), - (Ok(None), Ok(None)) => { + (Some(left_type), Some(right_type)) => (left_type, right_type), + (None, None) => { self.errors .push(AnalysisError::ExpectedValueFromExpression { expression: left.clone(), @@ -570,28 +612,20 @@ impl<'a> Analyzer<'a> { }); return; } - (Ok(None), _) => { + (None, _) => { self.errors .push(AnalysisError::ExpectedValueFromExpression { expression: left.clone(), }); return; } - (_, Ok(None)) => { + (_, None) => { self.errors .push(AnalysisError::ExpectedValueFromExpression { expression: right.clone(), }); return; } - (Err(ast_error), _) => { - self.errors.push(AnalysisError::AstError(ast_error)); - return; - } - (_, Err(ast_error)) => { - self.errors.push(AnalysisError::AstError(ast_error)); - return; - } }; if left_type != right_type { @@ -636,19 +670,23 @@ impl<'a> Analyzer<'a> { Expression::TupleAccess(tuple_access) => { let TupleAccessExpression { tuple, index } = tuple_access.inner.as_ref(); - let tuple_type = match tuple.return_type(&self.context) { - Ok(Some(tuple_type)) => tuple_type, - Ok(None) => { + let type_evaluation = match tuple.type_evaluation(&self.context) { + Ok(evaluation) => evaluation, + Err(ast_error) => { + self.errors.push(AnalysisError::AstError(ast_error)); + return; + } + }; + + let tuple_type = match type_evaluation.r#type() { + Some(tuple_type) => tuple_type, + None => { self.errors .push(AnalysisError::ExpectedValueFromExpression { expression: tuple.clone(), }); return; } - Err(ast_error) => { - self.errors.push(AnalysisError::AstError(ast_error)); - return; - } }; if let Type::Tuple { diff --git a/dust-lang/src/ast/expression.rs b/dust-lang/src/ast/expression.rs index f398a6c..d76467e 100644 --- a/dust-lang/src/ast/expression.rs +++ b/dust-lang/src/ast/expression.rs @@ -6,7 +6,10 @@ use std::{ use serde::{Deserialize, Serialize}; -use crate::{BuiltInFunction, Context, FunctionType, Identifier, RangeableType, StructType, Type}; +use crate::{ + BuiltInFunction, Context, FunctionType, Identifier, RangeableType, StructType, Type, + TypeEvaluation, +}; use super::{AstError, Node, Span, Statement}; @@ -268,127 +271,172 @@ impl Expression { } } - pub fn return_type(&self, context: &Context) -> Result, AstError> { + pub fn type_evaluation(&self, context: &Context) -> Result { let return_type = match self { - Expression::Block(block_expression) => block_expression.inner.return_type(context)?, + Expression::Block(block_expression) => { + block_expression.inner.type_evaluation(context)? + } Expression::Break(expression_node) => { if let Some(expression) = expression_node.inner.as_ref() { - expression.return_type(context)? + let type_evaluation = expression.type_evaluation(context)?; + + TypeEvaluation::Break(type_evaluation.r#type()) } else { - None + TypeEvaluation::Break(None) } } Expression::Call(call_expression) => { let CallExpression { invoker, .. } = call_expression.inner.as_ref(); - let invoker_type = invoker.return_type(context)?; + let invoker_type = invoker.type_evaluation(context)?.r#type(); - if let Some(Type::Function(FunctionType { return_type, .. })) = invoker_type { - return_type.map(|r#type| *r#type) - } else if let Some(Type::Struct(_)) = invoker_type { - invoker_type - } else { - None - } + let return_type = + if let Some(Type::Function(FunctionType { return_type, .. })) = invoker_type { + return_type.map(|r#type| *r#type) + } else if let Some(Type::Struct(_)) = invoker_type { + invoker_type + } else { + None + }; + + TypeEvaluation::Return(return_type) } Expression::FieldAccess(field_access_expression) => { let FieldAccessExpression { container, field } = field_access_expression.inner.as_ref(); - let container_type = container.return_type(context)?; + let container_type = container.type_evaluation(context)?.r#type(); if let Some(Type::Struct(StructType::Fields { fields, .. })) = container_type { - fields + let found_type = fields .into_iter() .find(|(name, _)| name == &field.inner) - .map(|(_, r#type)| r#type) + .map(|(_, r#type)| r#type); + + TypeEvaluation::Return(found_type) } else { - None + return Err(AstError::ExpectedStructFieldsType { + position: container.position(), + }); } } - Expression::Grouped(expression) => expression.inner.return_type(context)?, + Expression::Grouped(expression) => expression.inner.type_evaluation(context)?, Expression::Identifier(identifier) => { - context - .get_type(&identifier.inner) - .map_err(|error| AstError::ContextError { + let type_option = context.get_type(&identifier.inner).map_err(|error| { + AstError::ContextError { error, position: identifier.position, - })? + } + })?; + + TypeEvaluation::Return(type_option) } Expression::If(if_expression) => match if_expression.inner.as_ref() { - IfExpression::If { .. } => None, - IfExpression::IfElse { if_block, .. } => if_block.inner.return_type(context)?, + IfExpression::If { .. } => TypeEvaluation::Return(None), + IfExpression::IfElse { if_block, .. } => if_block.inner.type_evaluation(context)?, }, Expression::List(list_expression) => match list_expression.inner.as_ref() { - ListExpression::AutoFill { repeat_operand, .. } => { - let item_type = repeat_operand.return_type(context)?; - - if let Some(r#type) = item_type { - Some(Type::ListOf { - item_type: Box::new(r#type), - }) - } else { - return Err(AstError::ExpectedType { + ListExpression::AutoFill { + repeat_operand, + length_operand, + } => { + let item_type = repeat_operand + .type_evaluation(context)? + .r#type() + .ok_or_else(|| AstError::ExpectedListType { position: repeat_operand.position(), - }); - } + })?; + + let list_type = if let Expression::Literal(literal_expression) = length_operand + { + if let Some(index) = literal_expression.inner.as_integer() { + let length = match usize::try_from(index) { + Ok(usize) => usize, + Err(error) => { + return Err(AstError::FromIntError { + error, + position: length_operand.position(), + }) + } + }; + + Type::List { + item_type: Box::new(item_type), + length, + } + } else { + return Err(AstError::ExpectedInteger { + position: literal_expression.position, + }); + } + } else { + Type::ListOf { + item_type: Box::new(item_type), + } + }; + + TypeEvaluation::Return(Some(list_type)) } ListExpression::Ordered(expressions) => { if expressions.is_empty() { - return Ok(Some(Type::ListEmpty)); + return Ok(TypeEvaluation::Return(Some(Type::ListEmpty))); } let item_type = expressions .first() - .ok_or_else(|| AstError::ExpectedNonEmptyList { - position: self.position(), - })? - .return_type(context)? - .ok_or_else(|| AstError::ExpectedType { + .unwrap() + .type_evaluation(context)? + .r#type() + .ok_or_else(|| AstError::ExpectedNonEmptyEvaluation { position: expressions.first().unwrap().position(), })?; - let length = expressions.len(); - Some(Type::List { + TypeEvaluation::Return(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)? - .ok_or_else(|| AstError::ExpectedType { - position: list.position(), - })?; + let list_type = list.type_evaluation(context)?.r#type().ok_or_else(|| { + AstError::ExpectedListType { + position: list.position(), + } + })?; if let Type::List { item_type, .. } = list_type { - Some(*item_type) + TypeEvaluation::Return(Some(*item_type)) } else { - None + return Err(AstError::ExpectedListType { + position: list.position(), + }); } } - Expression::Literal(literal_expression) => match literal_expression.inner.as_ref() { - LiteralExpression::BuiltInFunction(built_in_function) => { - built_in_function.return_type() - } - LiteralExpression::Primitive(primitive_value) => match primitive_value { - PrimitiveValueExpression::Boolean(_) => Some(Type::Boolean), - PrimitiveValueExpression::Character(_) => Some(Type::Character), - PrimitiveValueExpression::Integer(_) => Some(Type::Integer), - PrimitiveValueExpression::Float(_) => Some(Type::Float), - }, - LiteralExpression::String(string) => Some(Type::String { - length: Some(string.len()), - }), - }, + Expression::Literal(literal_expression) => { + let type_option = match literal_expression.inner.as_ref() { + LiteralExpression::BuiltInFunction(built_in_function) => { + built_in_function.return_type() + } + LiteralExpression::Primitive(primitive_value) => match primitive_value { + PrimitiveValueExpression::Boolean(_) => Some(Type::Boolean), + PrimitiveValueExpression::Character(_) => Some(Type::Character), + PrimitiveValueExpression::Integer(_) => Some(Type::Integer), + PrimitiveValueExpression::Float(_) => Some(Type::Float), + }, + LiteralExpression::String(string) => Some(Type::String { + length: Some(string.len()), + }), + }; + + TypeEvaluation::Return(type_option) + } 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)?, + LoopExpression::For { block, .. } => block.inner.type_evaluation(context)?, + LoopExpression::Infinite { block } => block.inner.type_evaluation(context)?, + LoopExpression::While { block, .. } => block.inner.type_evaluation(context)?, }, Expression::Map(map_expression) => { let MapExpression { pairs } = map_expression.inner.as_ref(); @@ -396,41 +444,47 @@ impl Expression { let mut types = HashMap::with_capacity(pairs.len()); for (key, value) in pairs { - let value_type = - value - .return_type(context)? - .ok_or_else(|| AstError::ExpectedType { - position: value.position(), - })?; + let value_type = value.type_evaluation(context)?.r#type().ok_or_else(|| { + AstError::ExpectedNonEmptyEvaluation { + position: value.position(), + } + })?; types.insert(key.inner.clone(), value_type); } - Some(Type::Map { pairs: types }) + TypeEvaluation::Return(Some(Type::Map { pairs: types })) + } + Expression::Operator(operator_expression) => { + let expected_type = match operator_expression.inner.as_ref() { + OperatorExpression::Assignment { .. } => None, + OperatorExpression::Comparison { .. } => Some(Type::Boolean), + OperatorExpression::CompoundAssignment { .. } => None, + OperatorExpression::ErrorPropagation(expression) => { + expression.type_evaluation(context)?.r#type() + } + OperatorExpression::Negation(expression) => { + expression.type_evaluation(context)?.r#type() + } + OperatorExpression::Not(_) => Some(Type::Boolean), + OperatorExpression::Math { left, .. } => { + left.type_evaluation(context)?.r#type() + } + OperatorExpression::Logic { .. } => Some(Type::Boolean), + }; + + TypeEvaluation::Return(expected_type) } - 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(range_expression) => { let start = match range_expression.inner.as_ref() { RangeExpression::Exclusive { start, .. } => start, RangeExpression::Inclusive { start, .. } => start, }; - let start_type = - start - .return_type(context)? - .ok_or_else(|| AstError::ExpectedType { - position: start.position(), - })?; + let start_type = start.type_evaluation(context)?.r#type().ok_or_else(|| { + AstError::ExpectedListType { + position: start.position(), + } + })?; let rangeable_type = match start_type { Type::Byte => RangeableType::Byte, Type::Character => RangeableType::Character, @@ -443,44 +497,41 @@ impl Expression { } }; - Some(Type::Range { + TypeEvaluation::Return(Some(Type::Range { r#type: rangeable_type, - }) + })) } Expression::Struct(struct_expression) => match struct_expression.inner.as_ref() { StructExpression::Fields { name, fields } => { let mut types = HashMap::with_capacity(fields.len()); for (field, expression) in fields { - let r#type = expression.return_type(context)?.ok_or_else(|| { - AstError::ExpectedType { - position: expression.position(), - } - })?; + let r#type = + expression + .type_evaluation(context)? + .r#type() + .ok_or_else(|| AstError::ExpectedListType { + position: expression.position(), + })?; types.insert(field.inner.clone(), r#type); } - Some(Type::Struct(StructType::Fields { + TypeEvaluation::Return(Some(Type::Struct(StructType::Fields { name: name.inner.clone(), fields: types, - })) + }))) } }, Expression::TupleAccess(tuple_access_expression) => { let TupleAccessExpression { tuple, index } = tuple_access_expression.inner.as_ref(); - let tuple_value = - tuple - .return_type(context)? - .ok_or_else(|| AstError::ExpectedType { - position: tuple.position(), - })?; + let tuple_value = tuple.type_evaluation(context)?.r#type(); - if let Type::Tuple { + if let Some(Type::Tuple { fields: Some(fields), - } = tuple_value + }) = tuple_value { - fields.get(index.inner).cloned() + TypeEvaluation::Return(fields.get(index.inner).cloned()) } else { Err(AstError::ExpectedTupleType { position: tuple.position(), @@ -766,6 +817,15 @@ pub enum LiteralExpression { String(String), } +impl LiteralExpression { + pub fn as_integer(&self) -> Option { + match self { + LiteralExpression::Primitive(PrimitiveValueExpression::Integer(value)) => Some(*value), + _ => None, + } + } +} + impl Display for LiteralExpression { fn fmt(&self, f: &mut Formatter) -> fmt::Result { match self { @@ -1051,13 +1111,13 @@ pub enum BlockExpression { } impl BlockExpression { - fn return_type(&self, context: &Context) -> Result, AstError> { + fn type_evaluation(&self, context: &Context) -> Result { match self { BlockExpression::Async(statements) | BlockExpression::Sync(statements) => { if let Some(statement) = statements.last() { - statement.return_type(context) + statement.type_evaluation(context) } else { - Ok(None) + Ok(TypeEvaluation::Return(None)) } } } diff --git a/dust-lang/src/ast/mod.rs b/dust-lang/src/ast/mod.rs index faa380d..805f4f0 100644 --- a/dust-lang/src/ast/mod.rs +++ b/dust-lang/src/ast/mod.rs @@ -8,6 +8,7 @@ pub use statement::*; use std::{ collections::VecDeque, fmt::{self, Display, Formatter}, + num::TryFromIntError, }; use serde::{Deserialize, Serialize}; @@ -62,21 +63,49 @@ impl Display for Node { #[derive(Debug, Clone, PartialEq)] pub enum AstError { - ContextError { error: ContextError, position: Span }, - ExpectedType { position: Span }, - ExpectedTupleType { position: Span }, - ExpectedNonEmptyList { position: Span }, - ExpectedRangeableType { position: Span }, + ContextError { + error: ContextError, + position: Span, + }, + ExpectedInteger { + position: Span, + }, + ExpectedListType { + position: Span, + }, + ExpectedNonEmptyEvaluation { + position: Span, + }, + ExpectedNonEmptyList { + position: Span, + }, + ExpectedRangeableType { + position: Span, + }, + ExpectedStructFieldsType { + position: Span, + }, + ExpectedTupleType { + position: Span, + }, + FromIntError { + error: TryFromIntError, + position: Span, + }, } impl AstError { pub fn position(&self) -> Span { match self { AstError::ContextError { position, .. } => *position, - AstError::ExpectedType { position } => *position, - AstError::ExpectedTupleType { position } => *position, + AstError::ExpectedInteger { position } => *position, + AstError::ExpectedListType { position } => *position, + AstError::ExpectedNonEmptyEvaluation { position } => *position, AstError::ExpectedNonEmptyList { position } => *position, AstError::ExpectedRangeableType { position } => *position, + AstError::ExpectedStructFieldsType { position } => *position, + AstError::ExpectedTupleType { position } => *position, + AstError::FromIntError { position, .. } => *position, } } } @@ -87,16 +116,30 @@ impl Display for AstError { AstError::ContextError { error, position } => { write!(f, "Context error at {:?}: {}", position, error) } - AstError::ExpectedType { position } => write!(f, "Expected a type at {:?}", position), + AstError::ExpectedInteger { position } => { + write!(f, "Expected an integer at {:?}", position) + } + AstError::ExpectedListType { position } => { + write!(f, "Expected a type at {:?}", position) + } AstError::ExpectedTupleType { position } => { write!(f, "Expected a tuple type at {:?}", position) } + AstError::ExpectedNonEmptyEvaluation { position } => { + write!(f, "Expected a type at {:?}", position) + } AstError::ExpectedNonEmptyList { position } => { write!(f, "Expected a non-empty list at {:?}", position) } AstError::ExpectedRangeableType { position } => { write!(f, "Expected a rangeable type at {:?}", position) } + AstError::ExpectedStructFieldsType { position } => { + write!(f, "Expected a struct type with fields at {:?}", position) + } + AstError::FromIntError { error, position } => { + write!(f, "Integer conversion error at {:?}: {}", position, error) + } } } } diff --git a/dust-lang/src/ast/statement.rs b/dust-lang/src/ast/statement.rs index cf57d25..d4d35e9 100644 --- a/dust-lang/src/ast/statement.rs +++ b/dust-lang/src/ast/statement.rs @@ -2,7 +2,7 @@ use std::fmt::{self, Display, Formatter}; use serde::{Deserialize, Serialize}; -use crate::{Context, Identifier, Type}; +use crate::{Context, Identifier, Type, TypeEvaluation}; use super::{AstError, Expression, Node, Span}; @@ -28,12 +28,20 @@ impl Statement { } } - pub fn return_type(&self, context: &Context) -> Result, AstError> { + pub fn type_evaluation(&self, context: &Context) -> Result { match self { - Statement::Expression(expression) => expression.return_type(context), - Statement::ExpressionNullified(_) => Ok(None), - Statement::Let(_) => Ok(None), - Statement::StructDefinition(_) => Ok(None), + Statement::Expression(expression) => expression.type_evaluation(context), + Statement::ExpressionNullified(expression_node) => { + let type_evaluation = expression_node.inner.type_evaluation(context)?; + + if let TypeEvaluation::Break(_) = type_evaluation { + Ok(type_evaluation) + } else { + Ok(TypeEvaluation::Return(None)) + } + } + Statement::Let(_) => Ok(TypeEvaluation::Return(None)), + Statement::StructDefinition(_) => Ok(TypeEvaluation::Return(None)), } } } diff --git a/dust-lang/src/evaluation.rs b/dust-lang/src/evaluation.rs new file mode 100644 index 0000000..29b605b --- /dev/null +++ b/dust-lang/src/evaluation.rs @@ -0,0 +1,39 @@ +use crate::{Constructor, RuntimeError, Span, Type, Value}; + +pub enum Evaluation { + Break(Option), + Constructor(Constructor), + Return(Option), +} + +impl Evaluation { + pub fn value(self) -> Option { + match self { + Evaluation::Return(value_option) => value_option, + _ => None, + } + } + + pub fn expect_value(self, position: Span) -> Result { + if let Evaluation::Return(Some(value)) = self { + Ok(value) + } else { + Err(RuntimeError::ExpectedValue { position }) + } + } +} + +pub enum TypeEvaluation { + Break(Option), + Constructor(Type), + Return(Option), +} + +impl TypeEvaluation { + pub fn r#type(self) -> Option { + match self { + TypeEvaluation::Return(type_option) => type_option, + _ => None, + } + } +} diff --git a/dust-lang/src/lib.rs b/dust-lang/src/lib.rs index 9724948..8424a13 100644 --- a/dust-lang/src/lib.rs +++ b/dust-lang/src/lib.rs @@ -22,6 +22,7 @@ pub mod constructor; pub mod context; pub mod core_library; pub mod dust_error; +pub mod evaluation; pub mod identifier; pub mod lexer; pub mod parser; @@ -37,6 +38,7 @@ pub use constructor::Constructor; pub use context::{Context, ContextData, ContextError}; pub use core_library::core_library; pub use dust_error::DustError; +pub use evaluation::{Evaluation, TypeEvaluation}; pub use identifier::Identifier; pub use lexer::{lex, LexError, Lexer}; pub use parser::{parse, ParseError, Parser}; diff --git a/dust-lang/src/vm.rs b/dust-lang/src/vm.rs index 4b0a5b3..efa7aed 100644 --- a/dust-lang/src/vm.rs +++ b/dust-lang/src/vm.rs @@ -21,8 +21,8 @@ use crate::{ StructDefinition, StructExpression, }, constructor::ConstructError, - core_library, parse, Analyzer, BuiltInFunctionError, Constructor, Context, ContextData, - ContextError, DustError, Expression, Function, FunctionCallError, Identifier, ParseError, + core_library, parse, Analyzer, BuiltInFunctionError, Context, ContextData, ContextError, + DustError, Evaluation, Expression, Function, FunctionCallError, Identifier, ParseError, StructType, Type, Value, ValueData, ValueError, }; @@ -1066,29 +1066,6 @@ impl Vm { } } -enum Evaluation { - Break(Option), - Constructor(Constructor), - Return(Option), -} - -impl Evaluation { - pub fn value(self) -> Option { - match self { - Evaluation::Return(value_option) => value_option, - _ => None, - } - } - - pub fn expect_value(self, position: Span) -> Result { - if let Evaluation::Return(Some(value)) = self { - Ok(value) - } else { - Err(RuntimeError::ExpectedValue { position }) - } - } -} - #[derive(Clone, Debug, PartialEq)] pub enum RuntimeError { ConstructError {