Replace "return_type" methods in AST with new type_evaluation
This commit is contained in:
parent
f510cce0ee
commit
8b14d74eba
@ -91,13 +91,13 @@ impl<'a> Analyzer<'a> {
|
|||||||
Statement::Let(let_statement) => match &let_statement.inner {
|
Statement::Let(let_statement) => match &let_statement.inner {
|
||||||
LetStatement::Let { identifier, value }
|
LetStatement::Let { identifier, value }
|
||||||
| LetStatement::LetMut { identifier, value } => {
|
| LetStatement::LetMut { identifier, value } => {
|
||||||
let r#type = match value.return_type(&self.context) {
|
let r#type = match value.type_evaluation(&self.context) {
|
||||||
Ok(type_option) => type_option,
|
|
||||||
Err(ast_error) => {
|
Err(ast_error) => {
|
||||||
self.errors.push(AnalysisError::AstError(ast_error));
|
self.errors.push(AnalysisError::AstError(ast_error));
|
||||||
|
|
||||||
None
|
return;
|
||||||
}
|
}
|
||||||
|
Ok(evaluation) => evaluation.r#type(),
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(r#type) = r#type {
|
if let Some(r#type) = r#type {
|
||||||
@ -196,19 +196,22 @@ impl<'a> Analyzer<'a> {
|
|||||||
let FieldAccessExpression { container, field } =
|
let FieldAccessExpression { container, field } =
|
||||||
field_access_expression.inner.as_ref();
|
field_access_expression.inner.as_ref();
|
||||||
|
|
||||||
let container_type = match container.return_type(&self.context) {
|
let evaluation = match container.type_evaluation(&self.context) {
|
||||||
Ok(Some(r#type)) => r#type,
|
Ok(evaluation) => evaluation,
|
||||||
Ok(None) => {
|
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
|
self.errors
|
||||||
.push(AnalysisError::ExpectedValueFromExpression {
|
.push(AnalysisError::ExpectedValueFromExpression {
|
||||||
expression: container.clone(),
|
expression: container.clone(),
|
||||||
});
|
});
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Err(ast_error) => {
|
|
||||||
self.errors.push(AnalysisError::AstError(ast_error));
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -266,25 +269,17 @@ impl<'a> Analyzer<'a> {
|
|||||||
self.analyze_expression(list, statement_position);
|
self.analyze_expression(list, statement_position);
|
||||||
self.analyze_expression(index, statement_position);
|
self.analyze_expression(index, statement_position);
|
||||||
|
|
||||||
let list_type = match list.return_type(&self.context) {
|
let list_type_evaluation = match list.type_evaluation(&self.context) {
|
||||||
Ok(Some(r#type)) => r#type,
|
Ok(evaluation) => evaluation,
|
||||||
Ok(None) => {
|
|
||||||
self.errors
|
|
||||||
.push(AnalysisError::ExpectedValueFromExpression {
|
|
||||||
expression: list.clone(),
|
|
||||||
});
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Err(ast_error) => {
|
Err(ast_error) => {
|
||||||
self.errors.push(AnalysisError::AstError(ast_error));
|
self.errors.push(AnalysisError::AstError(ast_error));
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let index_type = match index.return_type(&self.context) {
|
let list_type = match list_type_evaluation.r#type() {
|
||||||
Ok(Some(r#type)) => r#type,
|
Some(r#type) => r#type,
|
||||||
Ok(None) => {
|
None => {
|
||||||
self.errors
|
self.errors
|
||||||
.push(AnalysisError::ExpectedValueFromExpression {
|
.push(AnalysisError::ExpectedValueFromExpression {
|
||||||
expression: list.clone(),
|
expression: list.clone(),
|
||||||
@ -292,12 +287,26 @@ impl<'a> Analyzer<'a> {
|
|||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
let index_type_evaluation = match index.type_evaluation(&self.context) {
|
||||||
|
Ok(evaluation) => evaluation,
|
||||||
Err(ast_error) => {
|
Err(ast_error) => {
|
||||||
self.errors.push(AnalysisError::AstError(ast_error));
|
self.errors.push(AnalysisError::AstError(ast_error));
|
||||||
|
|
||||||
return;
|
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 {
|
let literal_type = if let Expression::Literal(Node { inner, .. }) = index {
|
||||||
Some(inner.as_ref().clone())
|
Some(inner.as_ref().clone())
|
||||||
} else {
|
} else {
|
||||||
@ -406,14 +415,29 @@ impl<'a> Analyzer<'a> {
|
|||||||
self.analyze_expression(assignee, statement_position);
|
self.analyze_expression(assignee, statement_position);
|
||||||
self.analyze_expression(modifier, 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 (
|
let (expected_type, actual_type) = match (
|
||||||
assignee.return_type(&self.context),
|
assignee_type_evaluation.r#type(),
|
||||||
modifier.return_type(&self.context),
|
modifier_type_evaluation.r#type(),
|
||||||
) {
|
) {
|
||||||
(Ok(Some(expected_type)), Ok(Some(actual_type))) => {
|
(Some(expected_type), Some(actual_type)) => (expected_type, actual_type),
|
||||||
(expected_type, actual_type)
|
(None, None) => {
|
||||||
}
|
|
||||||
(Ok(None), Ok(None)) => {
|
|
||||||
self.errors
|
self.errors
|
||||||
.push(AnalysisError::ExpectedValueFromExpression {
|
.push(AnalysisError::ExpectedValueFromExpression {
|
||||||
expression: assignee.clone(),
|
expression: assignee.clone(),
|
||||||
@ -424,28 +448,20 @@ impl<'a> Analyzer<'a> {
|
|||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
(Ok(None), _) => {
|
(None, _) => {
|
||||||
self.errors
|
self.errors
|
||||||
.push(AnalysisError::ExpectedValueFromExpression {
|
.push(AnalysisError::ExpectedValueFromExpression {
|
||||||
expression: assignee.clone(),
|
expression: assignee.clone(),
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
(_, Ok(None)) => {
|
(_, None) => {
|
||||||
self.errors
|
self.errors
|
||||||
.push(AnalysisError::ExpectedValueFromExpression {
|
.push(AnalysisError::ExpectedValueFromExpression {
|
||||||
expression: modifier.clone(),
|
expression: modifier.clone(),
|
||||||
});
|
});
|
||||||
return;
|
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 {
|
if actual_type != expected_type {
|
||||||
@ -467,12 +483,29 @@ impl<'a> Analyzer<'a> {
|
|||||||
self.analyze_expression(left, statement_position);
|
self.analyze_expression(left, statement_position);
|
||||||
self.analyze_expression(right, 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 (
|
let (left_type, right_type) = match (
|
||||||
left.return_type(&self.context),
|
left_type_evaluation.r#type(),
|
||||||
right.return_type(&self.context),
|
right_type_evaluation.r#type(),
|
||||||
) {
|
) {
|
||||||
(Ok(Some(left_type)), Ok(Some(right_type))) => (left_type, right_type),
|
(Some(left_type), Some(right_type)) => (left_type, right_type),
|
||||||
(Ok(None), Ok(None)) => {
|
(None, None) => {
|
||||||
self.errors
|
self.errors
|
||||||
.push(AnalysisError::ExpectedValueFromExpression {
|
.push(AnalysisError::ExpectedValueFromExpression {
|
||||||
expression: left.clone(),
|
expression: left.clone(),
|
||||||
@ -483,28 +516,20 @@ impl<'a> Analyzer<'a> {
|
|||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
(Ok(None), _) => {
|
(None, _) => {
|
||||||
self.errors
|
self.errors
|
||||||
.push(AnalysisError::ExpectedValueFromExpression {
|
.push(AnalysisError::ExpectedValueFromExpression {
|
||||||
expression: left.clone(),
|
expression: left.clone(),
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
(_, Ok(None)) => {
|
(_, None) => {
|
||||||
self.errors
|
self.errors
|
||||||
.push(AnalysisError::ExpectedValueFromExpression {
|
.push(AnalysisError::ExpectedValueFromExpression {
|
||||||
expression: right.clone(),
|
expression: right.clone(),
|
||||||
});
|
});
|
||||||
return;
|
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 {
|
match left_type {
|
||||||
@ -554,12 +579,29 @@ impl<'a> Analyzer<'a> {
|
|||||||
self.analyze_expression(left, statement_position);
|
self.analyze_expression(left, statement_position);
|
||||||
self.analyze_expression(right, 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 (
|
let (left_type, right_type) = match (
|
||||||
left.return_type(&self.context),
|
left_type_evaluation.r#type(),
|
||||||
right.return_type(&self.context),
|
right_type_evaluation.r#type(),
|
||||||
) {
|
) {
|
||||||
(Ok(Some(left_type)), Ok(Some(right_type))) => (left_type, right_type),
|
(Some(left_type), Some(right_type)) => (left_type, right_type),
|
||||||
(Ok(None), Ok(None)) => {
|
(None, None) => {
|
||||||
self.errors
|
self.errors
|
||||||
.push(AnalysisError::ExpectedValueFromExpression {
|
.push(AnalysisError::ExpectedValueFromExpression {
|
||||||
expression: left.clone(),
|
expression: left.clone(),
|
||||||
@ -570,28 +612,20 @@ impl<'a> Analyzer<'a> {
|
|||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
(Ok(None), _) => {
|
(None, _) => {
|
||||||
self.errors
|
self.errors
|
||||||
.push(AnalysisError::ExpectedValueFromExpression {
|
.push(AnalysisError::ExpectedValueFromExpression {
|
||||||
expression: left.clone(),
|
expression: left.clone(),
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
(_, Ok(None)) => {
|
(_, None) => {
|
||||||
self.errors
|
self.errors
|
||||||
.push(AnalysisError::ExpectedValueFromExpression {
|
.push(AnalysisError::ExpectedValueFromExpression {
|
||||||
expression: right.clone(),
|
expression: right.clone(),
|
||||||
});
|
});
|
||||||
return;
|
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 {
|
if left_type != right_type {
|
||||||
@ -636,19 +670,23 @@ impl<'a> Analyzer<'a> {
|
|||||||
Expression::TupleAccess(tuple_access) => {
|
Expression::TupleAccess(tuple_access) => {
|
||||||
let TupleAccessExpression { tuple, index } = tuple_access.inner.as_ref();
|
let TupleAccessExpression { tuple, index } = tuple_access.inner.as_ref();
|
||||||
|
|
||||||
let tuple_type = match tuple.return_type(&self.context) {
|
let type_evaluation = match tuple.type_evaluation(&self.context) {
|
||||||
Ok(Some(tuple_type)) => tuple_type,
|
Ok(evaluation) => evaluation,
|
||||||
Ok(None) => {
|
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
|
self.errors
|
||||||
.push(AnalysisError::ExpectedValueFromExpression {
|
.push(AnalysisError::ExpectedValueFromExpression {
|
||||||
expression: tuple.clone(),
|
expression: tuple.clone(),
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Err(ast_error) => {
|
|
||||||
self.errors.push(AnalysisError::AstError(ast_error));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Type::Tuple {
|
if let Type::Tuple {
|
||||||
|
@ -6,7 +6,10 @@ use std::{
|
|||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
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};
|
use super::{AstError, Node, Span, Statement};
|
||||||
|
|
||||||
@ -268,110 +271,152 @@ impl Expression {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn return_type(&self, context: &Context) -> Result<Option<Type>, AstError> {
|
pub fn type_evaluation(&self, context: &Context) -> Result<TypeEvaluation, AstError> {
|
||||||
let return_type = match self {
|
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) => {
|
Expression::Break(expression_node) => {
|
||||||
if let Some(expression) = expression_node.inner.as_ref() {
|
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 {
|
} else {
|
||||||
None
|
TypeEvaluation::Break(None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expression::Call(call_expression) => {
|
Expression::Call(call_expression) => {
|
||||||
let CallExpression { invoker, .. } = call_expression.inner.as_ref();
|
let CallExpression { invoker, .. } = call_expression.inner.as_ref();
|
||||||
|
|
||||||
let invoker_type = invoker.return_type(context)?;
|
let invoker_type = invoker.type_evaluation(context)?.r#type();
|
||||||
|
|
||||||
|
let return_type =
|
||||||
if let Some(Type::Function(FunctionType { return_type, .. })) = invoker_type {
|
if let Some(Type::Function(FunctionType { return_type, .. })) = invoker_type {
|
||||||
return_type.map(|r#type| *r#type)
|
return_type.map(|r#type| *r#type)
|
||||||
} else if let Some(Type::Struct(_)) = invoker_type {
|
} else if let Some(Type::Struct(_)) = invoker_type {
|
||||||
invoker_type
|
invoker_type
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
};
|
||||||
|
|
||||||
|
TypeEvaluation::Return(return_type)
|
||||||
}
|
}
|
||||||
Expression::FieldAccess(field_access_expression) => {
|
Expression::FieldAccess(field_access_expression) => {
|
||||||
let FieldAccessExpression { container, field } =
|
let FieldAccessExpression { container, field } =
|
||||||
field_access_expression.inner.as_ref();
|
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 {
|
if let Some(Type::Struct(StructType::Fields { fields, .. })) = container_type {
|
||||||
fields
|
let found_type = fields
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.find(|(name, _)| name == &field.inner)
|
.find(|(name, _)| name == &field.inner)
|
||||||
.map(|(_, r#type)| r#type)
|
.map(|(_, r#type)| r#type);
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Expression::Grouped(expression) => expression.inner.return_type(context)?,
|
|
||||||
Expression::Identifier(identifier) => {
|
|
||||||
context
|
|
||||||
.get_type(&identifier.inner)
|
|
||||||
.map_err(|error| AstError::ContextError {
|
|
||||||
error,
|
|
||||||
position: identifier.position,
|
|
||||||
})?
|
|
||||||
}
|
|
||||||
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)?;
|
|
||||||
|
|
||||||
if let Some(r#type) = item_type {
|
TypeEvaluation::Return(found_type)
|
||||||
Some(Type::ListOf {
|
|
||||||
item_type: Box::new(r#type),
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
return Err(AstError::ExpectedType {
|
return Err(AstError::ExpectedStructFieldsType {
|
||||||
position: repeat_operand.position(),
|
position: container.position(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Expression::Grouped(expression) => expression.inner.type_evaluation(context)?,
|
||||||
|
Expression::Identifier(identifier) => {
|
||||||
|
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 { .. } => 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,
|
||||||
|
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) => {
|
ListExpression::Ordered(expressions) => {
|
||||||
if expressions.is_empty() {
|
if expressions.is_empty() {
|
||||||
return Ok(Some(Type::ListEmpty));
|
return Ok(TypeEvaluation::Return(Some(Type::ListEmpty)));
|
||||||
}
|
}
|
||||||
|
|
||||||
let item_type = expressions
|
let item_type = expressions
|
||||||
.first()
|
.first()
|
||||||
.ok_or_else(|| AstError::ExpectedNonEmptyList {
|
.unwrap()
|
||||||
position: self.position(),
|
.type_evaluation(context)?
|
||||||
})?
|
.r#type()
|
||||||
.return_type(context)?
|
.ok_or_else(|| AstError::ExpectedNonEmptyEvaluation {
|
||||||
.ok_or_else(|| AstError::ExpectedType {
|
|
||||||
position: expressions.first().unwrap().position(),
|
position: expressions.first().unwrap().position(),
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let length = expressions.len();
|
let length = expressions.len();
|
||||||
|
|
||||||
Some(Type::List {
|
TypeEvaluation::Return(Some(Type::List {
|
||||||
item_type: Box::new(item_type),
|
item_type: Box::new(item_type),
|
||||||
length,
|
length,
|
||||||
})
|
}))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Expression::ListIndex(list_index_expression) => {
|
Expression::ListIndex(list_index_expression) => {
|
||||||
let ListIndexExpression { list, .. } = list_index_expression.inner.as_ref();
|
let ListIndexExpression { list, .. } = list_index_expression.inner.as_ref();
|
||||||
|
|
||||||
let list_type =
|
let list_type = list.type_evaluation(context)?.r#type().ok_or_else(|| {
|
||||||
list.return_type(context)?
|
AstError::ExpectedListType {
|
||||||
.ok_or_else(|| AstError::ExpectedType {
|
|
||||||
position: list.position(),
|
position: list.position(),
|
||||||
|
}
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
if let Type::List { item_type, .. } = list_type {
|
if let Type::List { item_type, .. } = list_type {
|
||||||
Some(*item_type)
|
TypeEvaluation::Return(Some(*item_type))
|
||||||
} else {
|
} else {
|
||||||
None
|
return Err(AstError::ExpectedListType {
|
||||||
|
position: list.position(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expression::Literal(literal_expression) => match literal_expression.inner.as_ref() {
|
Expression::Literal(literal_expression) => {
|
||||||
|
let type_option = match literal_expression.inner.as_ref() {
|
||||||
LiteralExpression::BuiltInFunction(built_in_function) => {
|
LiteralExpression::BuiltInFunction(built_in_function) => {
|
||||||
built_in_function.return_type()
|
built_in_function.return_type()
|
||||||
}
|
}
|
||||||
@ -384,11 +429,14 @@ impl Expression {
|
|||||||
LiteralExpression::String(string) => Some(Type::String {
|
LiteralExpression::String(string) => Some(Type::String {
|
||||||
length: Some(string.len()),
|
length: Some(string.len()),
|
||||||
}),
|
}),
|
||||||
},
|
};
|
||||||
|
|
||||||
|
TypeEvaluation::Return(type_option)
|
||||||
|
}
|
||||||
Expression::Loop(loop_expression) => match loop_expression.inner.as_ref() {
|
Expression::Loop(loop_expression) => match loop_expression.inner.as_ref() {
|
||||||
LoopExpression::For { block, .. } => block.inner.return_type(context)?,
|
LoopExpression::For { block, .. } => block.inner.type_evaluation(context)?,
|
||||||
LoopExpression::Infinite { .. } => None,
|
LoopExpression::Infinite { block } => block.inner.type_evaluation(context)?,
|
||||||
LoopExpression::While { block, .. } => block.inner.return_type(context)?,
|
LoopExpression::While { block, .. } => block.inner.type_evaluation(context)?,
|
||||||
},
|
},
|
||||||
Expression::Map(map_expression) => {
|
Expression::Map(map_expression) => {
|
||||||
let MapExpression { pairs } = map_expression.inner.as_ref();
|
let MapExpression { pairs } = map_expression.inner.as_ref();
|
||||||
@ -396,40 +444,46 @@ impl Expression {
|
|||||||
let mut types = HashMap::with_capacity(pairs.len());
|
let mut types = HashMap::with_capacity(pairs.len());
|
||||||
|
|
||||||
for (key, value) in pairs {
|
for (key, value) in pairs {
|
||||||
let value_type =
|
let value_type = value.type_evaluation(context)?.r#type().ok_or_else(|| {
|
||||||
value
|
AstError::ExpectedNonEmptyEvaluation {
|
||||||
.return_type(context)?
|
|
||||||
.ok_or_else(|| AstError::ExpectedType {
|
|
||||||
position: value.position(),
|
position: value.position(),
|
||||||
|
}
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
types.insert(key.inner.clone(), value_type);
|
types.insert(key.inner.clone(), value_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(Type::Map { pairs: types })
|
TypeEvaluation::Return(Some(Type::Map { pairs: types }))
|
||||||
}
|
}
|
||||||
Expression::Operator(operator_expression) => match operator_expression.inner.as_ref() {
|
Expression::Operator(operator_expression) => {
|
||||||
|
let expected_type = match operator_expression.inner.as_ref() {
|
||||||
OperatorExpression::Assignment { .. } => None,
|
OperatorExpression::Assignment { .. } => None,
|
||||||
OperatorExpression::Comparison { .. } => Some(Type::Boolean),
|
OperatorExpression::Comparison { .. } => Some(Type::Boolean),
|
||||||
OperatorExpression::CompoundAssignment { .. } => None,
|
OperatorExpression::CompoundAssignment { .. } => None,
|
||||||
OperatorExpression::ErrorPropagation(expression) => {
|
OperatorExpression::ErrorPropagation(expression) => {
|
||||||
expression.return_type(context)?
|
expression.type_evaluation(context)?.r#type()
|
||||||
|
}
|
||||||
|
OperatorExpression::Negation(expression) => {
|
||||||
|
expression.type_evaluation(context)?.r#type()
|
||||||
}
|
}
|
||||||
OperatorExpression::Negation(expression) => expression.return_type(context)?,
|
|
||||||
OperatorExpression::Not(_) => Some(Type::Boolean),
|
OperatorExpression::Not(_) => Some(Type::Boolean),
|
||||||
OperatorExpression::Math { left, .. } => left.return_type(context)?,
|
OperatorExpression::Math { left, .. } => {
|
||||||
|
left.type_evaluation(context)?.r#type()
|
||||||
|
}
|
||||||
OperatorExpression::Logic { .. } => Some(Type::Boolean),
|
OperatorExpression::Logic { .. } => Some(Type::Boolean),
|
||||||
},
|
};
|
||||||
|
|
||||||
|
TypeEvaluation::Return(expected_type)
|
||||||
|
}
|
||||||
Expression::Range(range_expression) => {
|
Expression::Range(range_expression) => {
|
||||||
let start = match range_expression.inner.as_ref() {
|
let start = match range_expression.inner.as_ref() {
|
||||||
RangeExpression::Exclusive { start, .. } => start,
|
RangeExpression::Exclusive { start, .. } => start,
|
||||||
RangeExpression::Inclusive { start, .. } => start,
|
RangeExpression::Inclusive { start, .. } => start,
|
||||||
};
|
};
|
||||||
let start_type =
|
let start_type = start.type_evaluation(context)?.r#type().ok_or_else(|| {
|
||||||
start
|
AstError::ExpectedListType {
|
||||||
.return_type(context)?
|
|
||||||
.ok_or_else(|| AstError::ExpectedType {
|
|
||||||
position: start.position(),
|
position: start.position(),
|
||||||
|
}
|
||||||
})?;
|
})?;
|
||||||
let rangeable_type = match start_type {
|
let rangeable_type = match start_type {
|
||||||
Type::Byte => RangeableType::Byte,
|
Type::Byte => RangeableType::Byte,
|
||||||
@ -443,44 +497,41 @@ impl Expression {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Some(Type::Range {
|
TypeEvaluation::Return(Some(Type::Range {
|
||||||
r#type: rangeable_type,
|
r#type: rangeable_type,
|
||||||
})
|
}))
|
||||||
}
|
}
|
||||||
Expression::Struct(struct_expression) => match struct_expression.inner.as_ref() {
|
Expression::Struct(struct_expression) => match struct_expression.inner.as_ref() {
|
||||||
StructExpression::Fields { name, fields } => {
|
StructExpression::Fields { name, fields } => {
|
||||||
let mut types = HashMap::with_capacity(fields.len());
|
let mut types = HashMap::with_capacity(fields.len());
|
||||||
|
|
||||||
for (field, expression) in fields {
|
for (field, expression) in fields {
|
||||||
let r#type = expression.return_type(context)?.ok_or_else(|| {
|
let r#type =
|
||||||
AstError::ExpectedType {
|
expression
|
||||||
|
.type_evaluation(context)?
|
||||||
|
.r#type()
|
||||||
|
.ok_or_else(|| AstError::ExpectedListType {
|
||||||
position: expression.position(),
|
position: expression.position(),
|
||||||
}
|
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
types.insert(field.inner.clone(), r#type);
|
types.insert(field.inner.clone(), r#type);
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(Type::Struct(StructType::Fields {
|
TypeEvaluation::Return(Some(Type::Struct(StructType::Fields {
|
||||||
name: name.inner.clone(),
|
name: name.inner.clone(),
|
||||||
fields: types,
|
fields: types,
|
||||||
}))
|
})))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Expression::TupleAccess(tuple_access_expression) => {
|
Expression::TupleAccess(tuple_access_expression) => {
|
||||||
let TupleAccessExpression { tuple, index } = tuple_access_expression.inner.as_ref();
|
let TupleAccessExpression { tuple, index } = tuple_access_expression.inner.as_ref();
|
||||||
let tuple_value =
|
let tuple_value = tuple.type_evaluation(context)?.r#type();
|
||||||
tuple
|
|
||||||
.return_type(context)?
|
|
||||||
.ok_or_else(|| AstError::ExpectedType {
|
|
||||||
position: tuple.position(),
|
|
||||||
})?;
|
|
||||||
|
|
||||||
if let Type::Tuple {
|
if let Some(Type::Tuple {
|
||||||
fields: Some(fields),
|
fields: Some(fields),
|
||||||
} = tuple_value
|
}) = tuple_value
|
||||||
{
|
{
|
||||||
fields.get(index.inner).cloned()
|
TypeEvaluation::Return(fields.get(index.inner).cloned())
|
||||||
} else {
|
} else {
|
||||||
Err(AstError::ExpectedTupleType {
|
Err(AstError::ExpectedTupleType {
|
||||||
position: tuple.position(),
|
position: tuple.position(),
|
||||||
@ -766,6 +817,15 @@ pub enum LiteralExpression {
|
|||||||
String(String),
|
String(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl LiteralExpression {
|
||||||
|
pub fn as_integer(&self) -> Option<i64> {
|
||||||
|
match self {
|
||||||
|
LiteralExpression::Primitive(PrimitiveValueExpression::Integer(value)) => Some(*value),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Display for LiteralExpression {
|
impl Display for LiteralExpression {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
@ -1051,13 +1111,13 @@ pub enum BlockExpression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl BlockExpression {
|
impl BlockExpression {
|
||||||
fn return_type(&self, context: &Context) -> Result<Option<Type>, AstError> {
|
fn type_evaluation(&self, context: &Context) -> Result<TypeEvaluation, AstError> {
|
||||||
match self {
|
match self {
|
||||||
BlockExpression::Async(statements) | BlockExpression::Sync(statements) => {
|
BlockExpression::Async(statements) | BlockExpression::Sync(statements) => {
|
||||||
if let Some(statement) = statements.last() {
|
if let Some(statement) = statements.last() {
|
||||||
statement.return_type(context)
|
statement.type_evaluation(context)
|
||||||
} else {
|
} else {
|
||||||
Ok(None)
|
Ok(TypeEvaluation::Return(None))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ pub use statement::*;
|
|||||||
use std::{
|
use std::{
|
||||||
collections::VecDeque,
|
collections::VecDeque,
|
||||||
fmt::{self, Display, Formatter},
|
fmt::{self, Display, Formatter},
|
||||||
|
num::TryFromIntError,
|
||||||
};
|
};
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@ -62,21 +63,49 @@ impl<T: Display> Display for Node<T> {
|
|||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum AstError {
|
pub enum AstError {
|
||||||
ContextError { error: ContextError, position: Span },
|
ContextError {
|
||||||
ExpectedType { position: Span },
|
error: ContextError,
|
||||||
ExpectedTupleType { position: Span },
|
position: Span,
|
||||||
ExpectedNonEmptyList { position: Span },
|
},
|
||||||
ExpectedRangeableType { 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 {
|
impl AstError {
|
||||||
pub fn position(&self) -> Span {
|
pub fn position(&self) -> Span {
|
||||||
match self {
|
match self {
|
||||||
AstError::ContextError { position, .. } => *position,
|
AstError::ContextError { position, .. } => *position,
|
||||||
AstError::ExpectedType { position } => *position,
|
AstError::ExpectedInteger { position } => *position,
|
||||||
AstError::ExpectedTupleType { position } => *position,
|
AstError::ExpectedListType { position } => *position,
|
||||||
|
AstError::ExpectedNonEmptyEvaluation { position } => *position,
|
||||||
AstError::ExpectedNonEmptyList { position } => *position,
|
AstError::ExpectedNonEmptyList { position } => *position,
|
||||||
AstError::ExpectedRangeableType { 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 } => {
|
AstError::ContextError { error, position } => {
|
||||||
write!(f, "Context error at {:?}: {}", position, error)
|
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 } => {
|
AstError::ExpectedTupleType { position } => {
|
||||||
write!(f, "Expected a tuple type at {:?}", position)
|
write!(f, "Expected a tuple type at {:?}", position)
|
||||||
}
|
}
|
||||||
|
AstError::ExpectedNonEmptyEvaluation { position } => {
|
||||||
|
write!(f, "Expected a type at {:?}", position)
|
||||||
|
}
|
||||||
AstError::ExpectedNonEmptyList { position } => {
|
AstError::ExpectedNonEmptyList { position } => {
|
||||||
write!(f, "Expected a non-empty list at {:?}", position)
|
write!(f, "Expected a non-empty list at {:?}", position)
|
||||||
}
|
}
|
||||||
AstError::ExpectedRangeableType { position } => {
|
AstError::ExpectedRangeableType { position } => {
|
||||||
write!(f, "Expected a rangeable type at {:?}", 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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ use std::fmt::{self, Display, Formatter};
|
|||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{Context, Identifier, Type};
|
use crate::{Context, Identifier, Type, TypeEvaluation};
|
||||||
|
|
||||||
use super::{AstError, Expression, Node, Span};
|
use super::{AstError, Expression, Node, Span};
|
||||||
|
|
||||||
@ -28,12 +28,20 @@ impl Statement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn return_type(&self, context: &Context) -> Result<Option<Type>, AstError> {
|
pub fn type_evaluation(&self, context: &Context) -> Result<TypeEvaluation, AstError> {
|
||||||
match self {
|
match self {
|
||||||
Statement::Expression(expression) => expression.return_type(context),
|
Statement::Expression(expression) => expression.type_evaluation(context),
|
||||||
Statement::ExpressionNullified(_) => Ok(None),
|
Statement::ExpressionNullified(expression_node) => {
|
||||||
Statement::Let(_) => Ok(None),
|
let type_evaluation = expression_node.inner.type_evaluation(context)?;
|
||||||
Statement::StructDefinition(_) => Ok(None),
|
|
||||||
|
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)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
39
dust-lang/src/evaluation.rs
Normal file
39
dust-lang/src/evaluation.rs
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
use crate::{Constructor, RuntimeError, Span, Type, Value};
|
||||||
|
|
||||||
|
pub enum Evaluation {
|
||||||
|
Break(Option<Value>),
|
||||||
|
Constructor(Constructor),
|
||||||
|
Return(Option<Value>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Evaluation {
|
||||||
|
pub fn value(self) -> Option<Value> {
|
||||||
|
match self {
|
||||||
|
Evaluation::Return(value_option) => value_option,
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn expect_value(self, position: Span) -> Result<Value, RuntimeError> {
|
||||||
|
if let Evaluation::Return(Some(value)) = self {
|
||||||
|
Ok(value)
|
||||||
|
} else {
|
||||||
|
Err(RuntimeError::ExpectedValue { position })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum TypeEvaluation {
|
||||||
|
Break(Option<Type>),
|
||||||
|
Constructor(Type),
|
||||||
|
Return(Option<Type>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TypeEvaluation {
|
||||||
|
pub fn r#type(self) -> Option<Type> {
|
||||||
|
match self {
|
||||||
|
TypeEvaluation::Return(type_option) => type_option,
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -22,6 +22,7 @@ pub mod constructor;
|
|||||||
pub mod context;
|
pub mod context;
|
||||||
pub mod core_library;
|
pub mod core_library;
|
||||||
pub mod dust_error;
|
pub mod dust_error;
|
||||||
|
pub mod evaluation;
|
||||||
pub mod identifier;
|
pub mod identifier;
|
||||||
pub mod lexer;
|
pub mod lexer;
|
||||||
pub mod parser;
|
pub mod parser;
|
||||||
@ -37,6 +38,7 @@ pub use constructor::Constructor;
|
|||||||
pub use context::{Context, ContextData, ContextError};
|
pub use context::{Context, ContextData, ContextError};
|
||||||
pub use core_library::core_library;
|
pub use core_library::core_library;
|
||||||
pub use dust_error::DustError;
|
pub use dust_error::DustError;
|
||||||
|
pub use evaluation::{Evaluation, TypeEvaluation};
|
||||||
pub use identifier::Identifier;
|
pub use identifier::Identifier;
|
||||||
pub use lexer::{lex, LexError, Lexer};
|
pub use lexer::{lex, LexError, Lexer};
|
||||||
pub use parser::{parse, ParseError, Parser};
|
pub use parser::{parse, ParseError, Parser};
|
||||||
|
@ -21,8 +21,8 @@ use crate::{
|
|||||||
StructDefinition, StructExpression,
|
StructDefinition, StructExpression,
|
||||||
},
|
},
|
||||||
constructor::ConstructError,
|
constructor::ConstructError,
|
||||||
core_library, parse, Analyzer, BuiltInFunctionError, Constructor, Context, ContextData,
|
core_library, parse, Analyzer, BuiltInFunctionError, Context, ContextData, ContextError,
|
||||||
ContextError, DustError, Expression, Function, FunctionCallError, Identifier, ParseError,
|
DustError, Evaluation, Expression, Function, FunctionCallError, Identifier, ParseError,
|
||||||
StructType, Type, Value, ValueData, ValueError,
|
StructType, Type, Value, ValueData, ValueError,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1066,29 +1066,6 @@ impl Vm {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Evaluation {
|
|
||||||
Break(Option<Value>),
|
|
||||||
Constructor(Constructor),
|
|
||||||
Return(Option<Value>),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Evaluation {
|
|
||||||
pub fn value(self) -> Option<Value> {
|
|
||||||
match self {
|
|
||||||
Evaluation::Return(value_option) => value_option,
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn expect_value(self, position: Span) -> Result<Value, RuntimeError> {
|
|
||||||
if let Evaluation::Return(Some(value)) = self {
|
|
||||||
Ok(value)
|
|
||||||
} else {
|
|
||||||
Err(RuntimeError::ExpectedValue { position })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub enum RuntimeError {
|
pub enum RuntimeError {
|
||||||
ConstructError {
|
ConstructError {
|
||||||
|
Loading…
Reference in New Issue
Block a user