1
0

Begin preparing for type expressions

This commit is contained in:
Jeff 2024-06-16 03:12:04 -04:00
parent 54071eb8c0
commit a0b754cc1c
26 changed files with 835 additions and 818 deletions

View File

@ -9,31 +9,27 @@ use crate::{
Value, Value,
}; };
use super::{AbstractNode, Action, Expression, Type, WithPosition}; use super::{AbstractNode, Action, ExpectedType, Type, ValueExpression, WithPosition};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct As { pub struct As {
expression: Expression, expression: ValueExpression,
r#type: WithPosition<Type>, r#type: WithPosition<Type>,
} }
impl As { impl As {
pub fn new(expression: Expression, r#type: WithPosition<Type>) -> Self { pub fn new(expression: ValueExpression, r#type: WithPosition<Type>) -> Self {
Self { expression, r#type } Self { expression, r#type }
} }
} }
impl AbstractNode for As { impl AbstractNode for As {
fn expected_type(&self, _: &mut Context) -> Result<Type, ValidationError> {
Ok(self.r#type.item.clone())
}
fn validate( fn validate(
&self, &self,
_context: &mut Context, _context: &mut Context,
_manage_memory: bool, _manage_memory: bool,
) -> Result<(), ValidationError> { ) -> Result<(), ValidationError> {
match self.r#type.item { match self.r#type.node {
Type::Boolean | Type::Float | Type::Integer | Type::String => {} Type::Boolean | Type::Float | Type::Integer | Type::String => {}
_ => todo!("Create an error for this occurence."), _ => todo!("Create an error for this occurence."),
}; };
@ -54,7 +50,7 @@ impl AbstractNode for As {
ValidationError::InterpreterExpectedReturn(expression_position), ValidationError::InterpreterExpectedReturn(expression_position),
)); ));
}; };
let (from_value, to_type): (&ValueInner, Type) = (value.inner().borrow(), self.r#type.item); let (from_value, to_type): (&ValueInner, Type) = (value.inner().borrow(), self.r#type.node);
let converted = match (from_value, to_type) { let converted = match (from_value, to_type) {
(ValueInner::Boolean(boolean), Type::String) => Value::string(boolean.to_string()), (ValueInner::Boolean(boolean), Type::String) => Value::string(boolean.to_string()),
@ -65,3 +61,9 @@ impl AbstractNode for As {
Ok(Action::Return(converted)) Ok(Action::Return(converted))
} }
} }
impl ExpectedType for As {
fn expected_type(&self, _: &mut Context) -> Result<Type, ValidationError> {
Ok(self.r#type.node.clone())
}
}

View File

@ -7,7 +7,7 @@ use crate::{
Context, Value, Context, Value,
}; };
use super::{AbstractNode, Action, Statement, Type, WithPosition}; use super::{AbstractNode, Action, ExpectedType, Statement, Type, WithPosition};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct Assignment { pub struct Assignment {
@ -41,15 +41,11 @@ impl Assignment {
} }
impl AbstractNode for Assignment { impl AbstractNode for Assignment {
fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> {
Ok(Type::None)
}
fn validate(&self, context: &mut Context, manage_memory: bool) -> Result<(), ValidationError> { fn validate(&self, context: &mut Context, manage_memory: bool) -> Result<(), ValidationError> {
let statement_type = self.statement.expected_type(context)?; let statement_type = self.statement.expected_type(context)?;
if let Some(WithPosition { if let Some(WithPosition {
item: expected_type, node: expected_type,
position: expected_position, position: expected_position,
}) = &self.r#type }) = &self.r#type
{ {
@ -61,9 +57,9 @@ impl AbstractNode for Assignment {
} }
})?; })?;
context.set_type(self.identifier.item.clone(), expected_type.clone())?; context.set_type(self.identifier.node.clone(), expected_type.clone())?;
} else { } else {
context.set_type(self.identifier.item.clone(), statement_type)?; context.set_type(self.identifier.node.clone(), statement_type)?;
} }
self.statement.validate(context, manage_memory)?; self.statement.validate(context, manage_memory)?;
@ -80,13 +76,13 @@ impl AbstractNode for Assignment {
match self.operator { match self.operator {
AssignmentOperator::Assign => { AssignmentOperator::Assign => {
context.set_value(self.identifier.item, right)?; context.set_value(self.identifier.node, right)?;
} }
AssignmentOperator::AddAssign => { AssignmentOperator::AddAssign => {
let left_option = if manage_memory { let left_option = if manage_memory {
context.use_value(&self.identifier.item)? context.use_value(&self.identifier.node)?
} else { } else {
context.get_value(&self.identifier.item)? context.get_value(&self.identifier.node)?
}; };
if let Some(left) = left_option { if let Some(left) = left_option {
@ -117,11 +113,11 @@ impl AbstractNode for Assignment {
)) ))
} }
}; };
context.set_value(self.identifier.item, new_value)?; context.set_value(self.identifier.node, new_value)?;
} else { } else {
return Err(RuntimeError::ValidationFailure( return Err(RuntimeError::ValidationFailure(
ValidationError::VariableNotFound { ValidationError::VariableNotFound {
identifier: self.identifier.item, identifier: self.identifier.node,
position: self.identifier.position, position: self.identifier.position,
}, },
)); ));
@ -129,9 +125,9 @@ impl AbstractNode for Assignment {
} }
AssignmentOperator::SubAssign => { AssignmentOperator::SubAssign => {
let left_option = if manage_memory { let left_option = if manage_memory {
context.use_value(&self.identifier.item)? context.use_value(&self.identifier.node)?
} else { } else {
context.get_value(&self.identifier.item)? context.get_value(&self.identifier.node)?
}; };
if let Some(left) = left_option { if let Some(left) = left_option {
@ -162,11 +158,11 @@ impl AbstractNode for Assignment {
)) ))
} }
}; };
context.set_value(self.identifier.item, new_value)?; context.set_value(self.identifier.node, new_value)?;
} else { } else {
return Err(RuntimeError::ValidationFailure( return Err(RuntimeError::ValidationFailure(
ValidationError::VariableNotFound { ValidationError::VariableNotFound {
identifier: self.identifier.item, identifier: self.identifier.node,
position: self.identifier.position, position: self.identifier.position,
}, },
)); ));

View File

@ -8,7 +8,7 @@ use crate::{
error::{RuntimeError, RwLockPoisonError, ValidationError}, error::{RuntimeError, RwLockPoisonError, ValidationError},
}; };
use super::{AbstractNode, Action, Statement, Type}; use super::{AbstractNode, Action, ExpectedType, Statement, Type};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct AsyncBlock { pub struct AsyncBlock {
@ -22,10 +22,6 @@ impl AsyncBlock {
} }
impl AbstractNode for AsyncBlock { impl AbstractNode for AsyncBlock {
fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> {
self.statements.last().unwrap().expected_type(_context)
}
fn validate(&self, _context: &mut Context, manage_memory: bool) -> Result<(), ValidationError> { fn validate(&self, _context: &mut Context, manage_memory: bool) -> Result<(), ValidationError> {
for statement in &self.statements { for statement in &self.statements {
statement.validate(_context, manage_memory)?; statement.validate(_context, manage_memory)?;
@ -65,3 +61,9 @@ impl AbstractNode for AsyncBlock {
) )
} }
} }
impl ExpectedType for AsyncBlock {
fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> {
self.statements.first().unwrap().expected_type(_context)
}
}

View File

@ -5,7 +5,7 @@ use crate::{
error::{RuntimeError, ValidationError}, error::{RuntimeError, ValidationError},
}; };
use super::{AbstractNode, Action, Statement, Type}; use super::{AbstractNode, Action, ExpectedType, Statement};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct Block { pub struct Block {
@ -27,14 +27,6 @@ impl Block {
} }
impl AbstractNode for Block { impl AbstractNode for Block {
fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> {
if let Some(statement) = self.statements.last() {
statement.expected_type(_context)
} else {
Ok(Type::None)
}
}
fn validate( fn validate(
&self, &self,
_context: &mut Context, _context: &mut Context,
@ -58,10 +50,16 @@ impl AbstractNode for Block {
} }
} }
impl ExpectedType for Block {
fn expected_type(&self, _context: &mut Context) -> Result<super::Type, ValidationError> {
self.last_statement().expected_type(_context)
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::{ use crate::{
abstract_tree::{Expression, ValueNode, WithPos}, abstract_tree::{Type, ValueExpression, ValueNode, WithPos},
Value, Value,
}; };
@ -70,13 +68,13 @@ mod tests {
#[test] #[test]
fn run_returns_value_of_final_statement() { fn run_returns_value_of_final_statement() {
let block = Block::new(vec![ let block = Block::new(vec![
Statement::Expression(Expression::Value( Statement::ValueExpression(ValueExpression::Value(
ValueNode::Integer(1).with_position((0, 0)), ValueNode::Integer(1).with_position((0, 0)),
)), )),
Statement::Expression(Expression::Value( Statement::ValueExpression(ValueExpression::Value(
ValueNode::Integer(2).with_position((0, 0)), ValueNode::Integer(2).with_position((0, 0)),
)), )),
Statement::Expression(Expression::Value( Statement::ValueExpression(ValueExpression::Value(
ValueNode::Integer(42).with_position((0, 0)), ValueNode::Integer(42).with_position((0, 0)),
)), )),
]); ]);
@ -90,10 +88,10 @@ mod tests {
#[test] #[test]
fn expected_type_returns_type_of_final_statement() { fn expected_type_returns_type_of_final_statement() {
let block = Block::new(vec![ let block = Block::new(vec![
Statement::Expression(Expression::Value( Statement::ValueExpression(ValueExpression::Value(
ValueNode::String("42".to_string()).with_position((0, 0)), ValueNode::String("42".to_string()).with_position((0, 0)),
)), )),
Statement::Expression(Expression::Value( Statement::ValueExpression(ValueExpression::Value(
ValueNode::Integer(42).with_position((0, 0)), ValueNode::Integer(42).with_position((0, 0)),
)), )),
]); ]);

View File

@ -15,30 +15,19 @@ use crate::{
Value, Value,
}; };
use super::{AbstractNode, Expression, WithPosition}; use super::{AbstractNode, ExpectedType, ValueExpression, WithPosition};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum BuiltInFunctionCall { pub enum BuiltInFunctionCall {
JsonParse(WithPosition<Type>, Expression), JsonParse(WithPosition<Type>, ValueExpression),
Length(Expression), Length(ValueExpression),
ReadFile(Expression), ReadFile(ValueExpression),
ReadLine, ReadLine,
Sleep(Expression), Sleep(ValueExpression),
WriteLine(Expression), WriteLine(ValueExpression),
} }
impl AbstractNode for BuiltInFunctionCall { impl AbstractNode for BuiltInFunctionCall {
fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> {
match self {
BuiltInFunctionCall::JsonParse(r#type, _) => Ok(r#type.item.clone()),
BuiltInFunctionCall::Length(_) => Ok(Type::Integer),
BuiltInFunctionCall::ReadFile(_) => Ok(Type::String),
BuiltInFunctionCall::ReadLine => Ok(Type::String),
BuiltInFunctionCall::Sleep(_) => Ok(Type::None),
BuiltInFunctionCall::WriteLine(_) => Ok(Type::None),
}
}
fn validate( fn validate(
&self, &self,
_context: &mut Context, _context: &mut Context,
@ -64,7 +53,7 @@ impl AbstractNode for BuiltInFunctionCall {
fn run(self, context: &mut Context, _manage_memory: bool) -> Result<Action, RuntimeError> { fn run(self, context: &mut Context, _manage_memory: bool) -> Result<Action, RuntimeError> {
match self { match self {
BuiltInFunctionCall::JsonParse(r#type, expression) => { BuiltInFunctionCall::JsonParse(_type, expression) => {
let action = expression.clone().run(context, _manage_memory)?; let action = expression.clone().run(context, _manage_memory)?;
let value = if let Action::Return(value) = action { let value = if let Action::Return(value) = action {
value value
@ -169,3 +158,16 @@ impl AbstractNode for BuiltInFunctionCall {
} }
} }
} }
impl ExpectedType for BuiltInFunctionCall {
fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> {
match self {
BuiltInFunctionCall::JsonParse(r#type, _) => Ok(r#type.node.clone()),
BuiltInFunctionCall::Length(_) => Ok(Type::Integer),
BuiltInFunctionCall::ReadFile(_) => Ok(Type::String),
BuiltInFunctionCall::ReadLine => Ok(Type::String),
BuiltInFunctionCall::Sleep(_) => Ok(Type::None),
BuiltInFunctionCall::WriteLine(_) => Ok(Type::None),
}
}
}

View File

@ -1,136 +0,0 @@
use serde::{Deserialize, Serialize};
use crate::{
context::Context,
error::{RuntimeError, ValidationError},
identifier::Identifier,
};
use super::{
AbstractNode, Action, As, BuiltInFunctionCall, FunctionCall, ListIndex, Logic, MapIndex, Math,
SourcePosition, Type, ValueNode, WithPosition,
};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum Expression {
As(WithPosition<Box<As>>),
BuiltInFunctionCall(WithPosition<Box<BuiltInFunctionCall>>),
FunctionCall(WithPosition<FunctionCall>),
Identifier(WithPosition<Identifier>),
MapIndex(WithPosition<Box<MapIndex>>),
ListIndex(WithPosition<Box<ListIndex>>),
Logic(WithPosition<Box<Logic>>),
Math(WithPosition<Box<Math>>),
Value(WithPosition<ValueNode>),
}
impl Expression {
pub fn position(&self) -> SourcePosition {
match self {
Expression::As(inner) => inner.position,
Expression::FunctionCall(inner) => inner.position,
Expression::Identifier(inner) => inner.position,
Expression::MapIndex(inner) => inner.position,
Expression::ListIndex(inner) => inner.position,
Expression::Logic(inner) => inner.position,
Expression::Math(inner) => inner.position,
Expression::Value(inner) => inner.position,
Expression::BuiltInFunctionCall(inner) => inner.position,
}
}
}
impl AbstractNode for Expression {
fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> {
match self {
Expression::As(r#as) => r#as.item.expected_type(_context),
Expression::FunctionCall(function_call) => function_call.item.expected_type(_context),
Expression::Identifier(identifier) => {
if let Some(r#type) = _context.get_type(&identifier.item)? {
Ok(r#type)
} else {
Err(ValidationError::VariableNotFound {
identifier: identifier.item.clone(),
position: identifier.position,
})
}
}
Expression::MapIndex(map_index) => map_index.item.expected_type(_context),
Expression::ListIndex(list_index) => list_index.item.expected_type(_context),
Expression::Logic(logic) => logic.item.expected_type(_context),
Expression::Math(math) => math.item.expected_type(_context),
Expression::Value(value_node) => value_node.item.expected_type(_context),
Expression::BuiltInFunctionCall(built_in_function_call) => {
built_in_function_call.item.expected_type(_context)
}
}
}
fn validate(&self, context: &mut Context, manage_memory: bool) -> Result<(), ValidationError> {
match self {
Expression::As(r#as) => r#as.item.validate(context, manage_memory),
Expression::FunctionCall(function_call) => {
function_call.item.validate(context, manage_memory)
}
Expression::Identifier(identifier) => {
let found = if manage_memory {
context.add_expected_use(&identifier.item)?
} else {
context.contains(&identifier.item)?
};
if found {
Ok(())
} else {
Err(ValidationError::VariableNotFound {
identifier: identifier.item.clone(),
position: identifier.position,
})
}
}
Expression::MapIndex(map_index) => map_index.item.validate(context, manage_memory),
Expression::ListIndex(list_index) => list_index.item.validate(context, manage_memory),
Expression::Logic(logic) => logic.item.validate(context, manage_memory),
Expression::Math(math) => math.item.validate(context, manage_memory),
Expression::Value(value_node) => value_node.item.validate(context, manage_memory),
Expression::BuiltInFunctionCall(built_in_function_call) => {
built_in_function_call.item.validate(context, manage_memory)
}
}
}
fn run(self, context: &mut Context, manage_memory: bool) -> Result<Action, RuntimeError> {
match self {
Expression::As(r#as) => r#as.item.run(context, manage_memory),
Expression::FunctionCall(function_call) => {
function_call.item.run(context, manage_memory)
}
Expression::Identifier(identifier) => {
let value_option = if manage_memory {
context.use_value(&identifier.item)?
} else {
context.get_value(&identifier.item)?
};
if let Some(value) = value_option {
Ok(Action::Return(value))
} else {
Err(RuntimeError::ValidationFailure(
ValidationError::VariableNotFound {
identifier: identifier.item.clone(),
position: identifier.position,
},
))
}
}
Expression::MapIndex(map_index) => map_index.item.run(context, manage_memory),
Expression::ListIndex(list_index) => list_index.item.run(context, manage_memory),
Expression::Logic(logic) => logic.item.run(context, manage_memory),
Expression::Math(math) => math.item.run(context, manage_memory),
Expression::Value(value_node) => value_node.item.run(context, manage_memory),
Expression::BuiltInFunctionCall(built_in_function_call) => {
built_in_function_call.item.run(context, manage_memory)
}
}
}
}

View File

@ -6,20 +6,20 @@ use crate::{
value::ValueInner, value::ValueInner,
}; };
use super::{AbstractNode, Action, Expression, Type, WithPosition}; use super::{AbstractNode, Action, ExpectedType, Type, ValueExpression, WithPosition};
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct FunctionCall { pub struct FunctionCall {
function: Box<Expression>, function: Box<ValueExpression>,
type_arguments: Vec<WithPosition<Type>>, type_arguments: Vec<WithPosition<Type>>,
arguments: Vec<Expression>, arguments: Vec<ValueExpression>,
} }
impl FunctionCall { impl FunctionCall {
pub fn new( pub fn new(
function: Expression, function: ValueExpression,
type_arguments: Vec<WithPosition<Type>>, type_arguments: Vec<WithPosition<Type>>,
arguments: Vec<Expression>, arguments: Vec<ValueExpression>,
) -> Self { ) -> Self {
FunctionCall { FunctionCall {
function: Box::new(function), function: Box::new(function),
@ -30,19 +30,6 @@ impl FunctionCall {
} }
impl AbstractNode for FunctionCall { impl AbstractNode for FunctionCall {
fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> {
let function_node_type = self.function.expected_type(_context)?;
if let Type::Function { return_type, .. } = function_node_type {
Ok(return_type.item)
} else {
Err(ValidationError::ExpectedFunction {
actual: function_node_type,
position: self.function.position(),
})
}
}
fn validate(&self, context: &mut Context, manage_memory: bool) -> Result<(), ValidationError> { fn validate(&self, context: &mut Context, manage_memory: bool) -> Result<(), ValidationError> {
self.function.validate(context, manage_memory)?; self.function.validate(context, manage_memory)?;
@ -60,13 +47,13 @@ impl AbstractNode for FunctionCall {
for (type_parameter, type_argument) in for (type_parameter, type_argument) in
parameter_types.iter().zip(self.type_arguments.iter()) parameter_types.iter().zip(self.type_arguments.iter())
{ {
if let Type::Argument(_) = type_parameter.item { if let Type::Argument(_) = type_parameter.node {
continue; continue;
} }
type_parameter type_parameter
.item .node
.check(&type_argument.item) .check(&type_argument.node)
.map_err(|conflict| ValidationError::TypeCheck { .map_err(|conflict| ValidationError::TypeCheck {
conflict, conflict,
actual_position: type_argument.position, actual_position: type_argument.position,
@ -75,13 +62,13 @@ impl AbstractNode for FunctionCall {
} }
for (type_parameter, expression) in parameter_types.iter().zip(self.arguments.iter()) { for (type_parameter, expression) in parameter_types.iter().zip(self.arguments.iter()) {
if let Type::Argument(_) = type_parameter.item { if let Type::Argument(_) = type_parameter.node {
continue; continue;
} }
let actual = expression.expected_type(context)?; let actual = expression.expected_type(context)?;
type_parameter.item.check(&actual).map_err(|conflict| { type_parameter.node.check(&actual).map_err(|conflict| {
ValidationError::TypeCheck { ValidationError::TypeCheck {
conflict, conflict,
actual_position: expression.position(), actual_position: expression.position(),
@ -140,8 +127,8 @@ impl AbstractNode for FunctionCall {
for (type_parameter, type_argument) in function for (type_parameter, type_argument) in function
.type_parameters() .type_parameters()
.iter() .iter()
.map(|r#type| r#type.item.clone()) .map(|r#type| r#type.node.clone())
.zip(self.type_arguments.into_iter().map(|r#type| r#type.item)) .zip(self.type_arguments.into_iter().map(|r#type| r#type.node))
{ {
if let Type::Argument(identifier) = type_parameter { if let Type::Argument(identifier) = type_parameter {
function_context.set_type(identifier, type_argument)?; function_context.set_type(identifier, type_argument)?;
@ -153,3 +140,18 @@ impl AbstractNode for FunctionCall {
.call(arguments, &mut function_context, clear_variables) .call(arguments, &mut function_context, clear_variables)
} }
} }
impl ExpectedType for FunctionCall {
fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> {
let function_node_type = self.function.expected_type(_context)?;
if let Type::Function { return_type, .. } = function_node_type {
Ok(return_type.node)
} else {
Err(ValidationError::ExpectedFunction {
actual: function_node_type,
position: self.function.position(),
})
}
}
}

View File

@ -6,21 +6,21 @@ use crate::{
value::ValueInner, value::ValueInner,
}; };
use super::{AbstractNode, Action, Block, Expression, Type, WithPosition}; use super::{AbstractNode, Action, Block, ExpectedType, Type, ValueExpression, WithPosition};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct IfElse { pub struct IfElse {
if_expression: Expression, if_expression: ValueExpression,
if_block: WithPosition<Block>, if_block: WithPosition<Block>,
else_ifs: Vec<(Expression, WithPosition<Block>)>, else_ifs: Vec<(ValueExpression, WithPosition<Block>)>,
else_block: Option<WithPosition<Block>>, else_block: Option<WithPosition<Block>>,
} }
impl IfElse { impl IfElse {
pub fn new( pub fn new(
if_expression: Expression, if_expression: ValueExpression,
if_block: WithPosition<Block>, if_block: WithPosition<Block>,
else_ifs: Vec<(Expression, WithPosition<Block>)>, else_ifs: Vec<(ValueExpression, WithPosition<Block>)>,
else_block: Option<WithPosition<Block>>, else_block: Option<WithPosition<Block>>,
) -> Self { ) -> Self {
Self { Self {
@ -33,29 +33,25 @@ impl IfElse {
} }
impl AbstractNode for IfElse { impl AbstractNode for IfElse {
fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> {
self.if_block.item.expected_type(_context)
}
fn validate(&self, context: &mut Context, manage_memory: bool) -> Result<(), ValidationError> { fn validate(&self, context: &mut Context, manage_memory: bool) -> Result<(), ValidationError> {
self.if_expression.validate(context, manage_memory)?; self.if_expression.validate(context, manage_memory)?;
self.if_block.item.validate(context, manage_memory)?; self.if_block.node.validate(context, manage_memory)?;
let expected_type = self.if_block.item.expected_type(context)?; let expected_type = self.if_block.node.expected_type(context)?;
let if_expression_type = self.if_expression.expected_type(context)?; let if_expression_type = self.if_expression.expected_type(context)?;
if let Type::Boolean = if_expression_type { if let Type::Boolean = if_expression_type {
if let Some(else_block) = &self.else_block { if let Some(else_block) = &self.else_block {
else_block.item.validate(context, manage_memory)?; else_block.node.validate(context, manage_memory)?;
let actual = else_block.item.expected_type(context)?; let actual = else_block.node.expected_type(context)?;
expected_type expected_type
.check(&actual) .check(&actual)
.map_err(|conflict| ValidationError::TypeCheck { .map_err(|conflict| ValidationError::TypeCheck {
conflict, conflict,
actual_position: else_block.item.last_statement().position(), actual_position: else_block.node.last_statement().position(),
expected_position: self.if_block.item.first_statement().position(), expected_position: self.if_block.node.first_statement().position(),
})?; })?;
} }
} else { } else {
@ -69,15 +65,15 @@ impl AbstractNode for IfElse {
let expression_type = expression.expected_type(context)?; let expression_type = expression.expected_type(context)?;
if let Type::Boolean = expression_type { if let Type::Boolean = expression_type {
block.item.validate(context, manage_memory)?; block.node.validate(context, manage_memory)?;
let actual = block.item.expected_type(context)?; let actual = block.node.expected_type(context)?;
expected_type expected_type
.check(&actual) .check(&actual)
.map_err(|conflict| ValidationError::TypeCheck { .map_err(|conflict| ValidationError::TypeCheck {
conflict, conflict,
actual_position: self.if_block.item.last_statement().position(), actual_position: self.if_block.node.last_statement().position(),
expected_position: self.if_expression.position(), expected_position: self.if_expression.position(),
})?; })?;
} else { } else {
@ -104,7 +100,7 @@ impl AbstractNode for IfElse {
if let ValueInner::Boolean(if_boolean) = value.inner().as_ref() { if let ValueInner::Boolean(if_boolean) = value.inner().as_ref() {
if *if_boolean { if *if_boolean {
self.if_block.item.run(context, _manage_memory) self.if_block.node.run(context, _manage_memory)
} else { } else {
for (expression, block) in self.else_ifs { for (expression, block) in self.else_ifs {
let expression_position = expression.position(); let expression_position = expression.position();
@ -119,7 +115,7 @@ impl AbstractNode for IfElse {
if let ValueInner::Boolean(else_if_boolean) = value.inner().as_ref() { if let ValueInner::Boolean(else_if_boolean) = value.inner().as_ref() {
if *else_if_boolean { if *else_if_boolean {
return block.item.run(context, _manage_memory); return block.node.run(context, _manage_memory);
} }
} else { } else {
return Err(RuntimeError::ValidationFailure( return Err(RuntimeError::ValidationFailure(
@ -132,7 +128,7 @@ impl AbstractNode for IfElse {
} }
if let Some(else_statement) = self.else_block { if let Some(else_statement) = self.else_block {
else_statement.item.run(context, _manage_memory) else_statement.node.run(context, _manage_memory)
} else { } else {
Ok(Action::None) Ok(Action::None)
} }
@ -148,6 +144,12 @@ impl AbstractNode for IfElse {
} }
} }
impl ExpectedType for IfElse {
fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> {
self.if_block.node.expected_type(_context)
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::{ use crate::{
@ -161,8 +163,8 @@ mod tests {
fn simple_if() { fn simple_if() {
assert_eq!( assert_eq!(
IfElse::new( IfElse::new(
Expression::Value(ValueNode::Boolean(true).with_position((0, 0))), ValueExpression::Value(ValueNode::Boolean(true).with_position((0, 0))),
Block::new(vec![Statement::Expression(Expression::Value( Block::new(vec![Statement::ValueExpression(ValueExpression::Value(
ValueNode::String("foo".to_string()).with_position((0, 0)) ValueNode::String("foo".to_string()).with_position((0, 0))
))]) ))])
.with_position((0, 0)), .with_position((0, 0)),

View File

@ -5,50 +5,21 @@ use crate::{
error::{RuntimeError, ValidationError}, error::{RuntimeError, ValidationError},
}; };
use super::{AbstractNode, Action, Expression, Type, ValueNode, WithPosition}; use super::{AbstractNode, Action, ExpectedType, Type, ValueExpression, ValueNode, WithPosition};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct ListIndex { pub struct ListIndex {
left: Expression, left: ValueExpression,
right: Expression, right: ValueExpression,
} }
impl ListIndex { impl ListIndex {
pub fn new(left: Expression, right: Expression) -> Self { pub fn new(left: ValueExpression, right: ValueExpression) -> Self {
Self { left, right } Self { left, right }
} }
} }
impl AbstractNode for ListIndex { impl AbstractNode for ListIndex {
fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> {
let left_type = self.left.expected_type(_context)?;
if let (
Expression::Value(WithPosition {
item: ValueNode::List(expression_list),
..
}),
Expression::Value(WithPosition {
item: ValueNode::Integer(index),
..
}),
) = (&self.left, &self.right)
{
let expression = if let Some(expression) = expression_list.get(*index as usize) {
expression
} else {
return Ok(Type::None);
};
expression.expected_type(_context)
} else {
Err(ValidationError::CannotIndex {
r#type: left_type,
position: self.left.position(),
})
}
}
fn validate(&self, context: &mut Context, _manage_memory: bool) -> Result<(), ValidationError> { fn validate(&self, context: &mut Context, _manage_memory: bool) -> Result<(), ValidationError> {
self.left.validate(context, _manage_memory)?; self.left.validate(context, _manage_memory)?;
self.right.validate(context, _manage_memory)?; self.right.validate(context, _manage_memory)?;
@ -103,7 +74,7 @@ impl AbstractNode for ListIndex {
let found_item = list.get(index as usize); let found_item = list.get(index as usize);
if let Some(item) = found_item { if let Some(item) = found_item {
Ok(Action::Return(item.item.clone())) Ok(Action::Return(item.node.clone()))
} else { } else {
Ok(Action::None) Ok(Action::None)
} }
@ -119,3 +90,34 @@ impl AbstractNode for ListIndex {
} }
} }
} }
impl ExpectedType for ListIndex {
fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> {
let left_type = self.left.expected_type(_context)?;
if let (
ValueExpression::Value(WithPosition {
node: ValueNode::List(expression_list),
..
}),
ValueExpression::Value(WithPosition {
node: ValueNode::Integer(index),
..
}),
) = (&self.left, &self.right)
{
let expression = if let Some(expression) = expression_list.get(*index as usize) {
expression
} else {
return Ok(Type::None);
};
expression.expected_type(_context)
} else {
Err(ValidationError::CannotIndex {
r#type: left_type,
position: self.left.position(),
})
}
}
}

View File

@ -7,26 +7,22 @@ use crate::{
Value, Value,
}; };
use super::{AbstractNode, Action, Expression, Type}; use super::{AbstractNode, Action, ExpectedType, Type, ValueExpression};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum Logic { pub enum Logic {
Equal(Expression, Expression), Equal(ValueExpression, ValueExpression),
NotEqual(Expression, Expression), NotEqual(ValueExpression, ValueExpression),
Greater(Expression, Expression), Greater(ValueExpression, ValueExpression),
Less(Expression, Expression), Less(ValueExpression, ValueExpression),
GreaterOrEqual(Expression, Expression), GreaterOrEqual(ValueExpression, ValueExpression),
LessOrEqual(Expression, Expression), LessOrEqual(ValueExpression, ValueExpression),
And(Expression, Expression), And(ValueExpression, ValueExpression),
Or(Expression, Expression), Or(ValueExpression, ValueExpression),
Not(Expression), Not(ValueExpression),
} }
impl AbstractNode for Logic { impl AbstractNode for Logic {
fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> {
Ok(Type::Boolean)
}
fn validate(&self, context: &mut Context, _manage_memory: bool) -> Result<(), ValidationError> { fn validate(&self, context: &mut Context, _manage_memory: bool) -> Result<(), ValidationError> {
match self { match self {
Logic::Equal(left, right) Logic::Equal(left, right)
@ -94,7 +90,7 @@ impl AbstractNode for Logic {
} }
fn run(self, context: &mut Context, _manage_memory: bool) -> Result<Action, RuntimeError> { fn run(self, context: &mut Context, _manage_memory: bool) -> Result<Action, RuntimeError> {
let run_and_expect_value = |expression: Expression| -> Result<Value, RuntimeError> { let run_and_expect_value = |expression: ValueExpression| -> Result<Value, RuntimeError> {
let expression_position = expression.position(); let expression_position = expression.position();
let action = expression.run(&mut context.clone(), _manage_memory)?; let action = expression.run(&mut context.clone(), _manage_memory)?;
let value = if let Action::Return(value) = action { let value = if let Action::Return(value) = action {
@ -108,7 +104,7 @@ impl AbstractNode for Logic {
Ok(value) Ok(value)
}; };
let run_and_expect_boolean = |expression: Expression| -> Result<bool, RuntimeError> { let run_and_expect_boolean = |expression: ValueExpression| -> Result<bool, RuntimeError> {
let expression_position = expression.position(); let expression_position = expression.position();
let action = expression.run(&mut context.clone(), _manage_memory)?; let action = expression.run(&mut context.clone(), _manage_memory)?;
let value = if let Action::Return(value) = action { let value = if let Action::Return(value) = action {
@ -195,6 +191,12 @@ impl AbstractNode for Logic {
} }
} }
impl ExpectedType for Logic {
fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> {
Ok(Type::Boolean)
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::abstract_tree::{ValueNode, WithPos}; use crate::abstract_tree::{ValueNode, WithPos};
@ -205,8 +207,8 @@ mod tests {
fn equal() { fn equal() {
assert_eq!( assert_eq!(
Logic::Equal( Logic::Equal(
Expression::Value(ValueNode::Integer(42).with_position((0, 0))), ValueExpression::Value(ValueNode::Integer(42).with_position((0, 0))),
Expression::Value(ValueNode::Integer(42).with_position((0, 0))) ValueExpression::Value(ValueNode::Integer(42).with_position((0, 0)))
) )
.run(&mut Context::new(None), true), .run(&mut Context::new(None), true),
Ok(Action::Return(Value::boolean(true))) Ok(Action::Return(Value::boolean(true)))
@ -217,8 +219,8 @@ mod tests {
fn not_equal() { fn not_equal() {
assert_eq!( assert_eq!(
Logic::NotEqual( Logic::NotEqual(
Expression::Value(ValueNode::Integer(42).with_position((0, 0))), ValueExpression::Value(ValueNode::Integer(42).with_position((0, 0))),
Expression::Value(ValueNode::Integer(43).with_position((0, 0))) ValueExpression::Value(ValueNode::Integer(43).with_position((0, 0)))
) )
.run(&mut Context::new(None), true), .run(&mut Context::new(None), true),
Ok(Action::Return(Value::boolean(true))) Ok(Action::Return(Value::boolean(true)))
@ -229,8 +231,8 @@ mod tests {
fn greater() { fn greater() {
assert_eq!( assert_eq!(
Logic::Greater( Logic::Greater(
Expression::Value(ValueNode::Integer(43).with_position((0, 0))), ValueExpression::Value(ValueNode::Integer(43).with_position((0, 0))),
Expression::Value(ValueNode::Integer(42).with_position((0, 0))) ValueExpression::Value(ValueNode::Integer(42).with_position((0, 0)))
) )
.run(&mut Context::new(None), true), .run(&mut Context::new(None), true),
Ok(Action::Return(Value::boolean(true))) Ok(Action::Return(Value::boolean(true)))
@ -241,8 +243,8 @@ mod tests {
fn less() { fn less() {
assert_eq!( assert_eq!(
Logic::Less( Logic::Less(
Expression::Value(ValueNode::Integer(42).with_position((0, 0))), ValueExpression::Value(ValueNode::Integer(42).with_position((0, 0))),
Expression::Value(ValueNode::Integer(43).with_position((0, 0))) ValueExpression::Value(ValueNode::Integer(43).with_position((0, 0)))
) )
.run(&mut Context::new(None), true), .run(&mut Context::new(None), true),
Ok(Action::Return(Value::boolean(true))) Ok(Action::Return(Value::boolean(true)))
@ -253,8 +255,8 @@ mod tests {
fn greater_or_equal() { fn greater_or_equal() {
assert_eq!( assert_eq!(
Logic::GreaterOrEqual( Logic::GreaterOrEqual(
Expression::Value(ValueNode::Integer(42).with_position((0, 0))), ValueExpression::Value(ValueNode::Integer(42).with_position((0, 0))),
Expression::Value(ValueNode::Integer(41).with_position((0, 0))) ValueExpression::Value(ValueNode::Integer(41).with_position((0, 0)))
) )
.run(&mut Context::new(None), true), .run(&mut Context::new(None), true),
Ok(Action::Return(Value::boolean(true))) Ok(Action::Return(Value::boolean(true)))
@ -262,8 +264,8 @@ mod tests {
assert_eq!( assert_eq!(
Logic::GreaterOrEqual( Logic::GreaterOrEqual(
Expression::Value(ValueNode::Integer(42).with_position((0, 0))), ValueExpression::Value(ValueNode::Integer(42).with_position((0, 0))),
Expression::Value(ValueNode::Integer(42).with_position((0, 0))), ValueExpression::Value(ValueNode::Integer(42).with_position((0, 0))),
) )
.run(&mut Context::new(None), true), .run(&mut Context::new(None), true),
Ok(Action::Return(Value::boolean(true))) Ok(Action::Return(Value::boolean(true)))
@ -274,8 +276,8 @@ mod tests {
fn less_or_equal() { fn less_or_equal() {
assert_eq!( assert_eq!(
Logic::LessOrEqual( Logic::LessOrEqual(
Expression::Value(ValueNode::Integer(41).with_position((0, 0))), ValueExpression::Value(ValueNode::Integer(41).with_position((0, 0))),
Expression::Value(ValueNode::Integer(42).with_position((0, 0))), ValueExpression::Value(ValueNode::Integer(42).with_position((0, 0))),
) )
.run(&mut Context::new(None), true), .run(&mut Context::new(None), true),
Ok(Action::Return(Value::boolean(true))) Ok(Action::Return(Value::boolean(true)))
@ -283,8 +285,8 @@ mod tests {
assert_eq!( assert_eq!(
Logic::LessOrEqual( Logic::LessOrEqual(
Expression::Value(ValueNode::Integer(42).with_position((0, 0))), ValueExpression::Value(ValueNode::Integer(42).with_position((0, 0))),
Expression::Value(ValueNode::Integer(42).with_position((0, 0))), ValueExpression::Value(ValueNode::Integer(42).with_position((0, 0))),
) )
.run(&mut Context::new(None), true), .run(&mut Context::new(None), true),
Ok(Action::Return(Value::boolean(true))) Ok(Action::Return(Value::boolean(true)))
@ -295,8 +297,8 @@ mod tests {
fn and() { fn and() {
assert_eq!( assert_eq!(
Logic::And( Logic::And(
Expression::Value(ValueNode::Boolean(true).with_position((0, 0))), ValueExpression::Value(ValueNode::Boolean(true).with_position((0, 0))),
Expression::Value(ValueNode::Boolean(true).with_position((0, 0))), ValueExpression::Value(ValueNode::Boolean(true).with_position((0, 0))),
) )
.run(&mut Context::new(None), true), .run(&mut Context::new(None), true),
Ok(Action::Return(Value::boolean(true))) Ok(Action::Return(Value::boolean(true)))
@ -307,8 +309,8 @@ mod tests {
fn or() { fn or() {
assert_eq!( assert_eq!(
Logic::Or( Logic::Or(
Expression::Value(ValueNode::Boolean(true).with_position((0, 0))), ValueExpression::Value(ValueNode::Boolean(true).with_position((0, 0))),
Expression::Value(ValueNode::Boolean(false).with_position((0, 0))), ValueExpression::Value(ValueNode::Boolean(false).with_position((0, 0))),
) )
.run(&mut Context::new(None), true), .run(&mut Context::new(None), true),
Ok(Action::Return(Value::boolean(true))) Ok(Action::Return(Value::boolean(true)))
@ -318,7 +320,7 @@ mod tests {
#[test] #[test]
fn not() { fn not() {
assert_eq!( assert_eq!(
Logic::Not(Expression::Value( Logic::Not(ValueExpression::Value(
ValueNode::Boolean(false).with_position((0, 0)) ValueNode::Boolean(false).with_position((0, 0))
)) ))
.run(&mut Context::new(None), true), .run(&mut Context::new(None), true),

View File

@ -5,7 +5,7 @@ use crate::{
error::{RuntimeError, ValidationError}, error::{RuntimeError, ValidationError},
}; };
use super::{AbstractNode, Action, Statement, Type}; use super::{AbstractNode, Action, Statement};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct Loop { pub struct Loop {
@ -19,10 +19,6 @@ impl Loop {
} }
impl AbstractNode for Loop { impl AbstractNode for Loop {
fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> {
Ok(Type::None)
}
fn validate( fn validate(
&self, &self,
_context: &mut Context, _context: &mut Context,

View File

@ -6,16 +6,16 @@ use crate::{
value::ValueInner, value::ValueInner,
}; };
use super::{AbstractNode, Action, Expression, Type, ValueNode, WithPosition}; use super::{AbstractNode, Action, ExpectedType, Type, ValueExpression, ValueNode, WithPosition};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct MapIndex { pub struct MapIndex {
collection: Expression, collection: ValueExpression,
index: Expression, index: ValueExpression,
} }
impl MapIndex { impl MapIndex {
pub fn new(left: Expression, right: Expression) -> Self { pub fn new(left: ValueExpression, right: ValueExpression) -> Self {
Self { Self {
collection: left, collection: left,
index: right, index: right,
@ -24,87 +24,6 @@ impl MapIndex {
} }
impl AbstractNode for MapIndex { impl AbstractNode for MapIndex {
fn expected_type(&self, context: &mut Context) -> Result<Type, ValidationError> {
if let (Expression::Identifier(collection), Expression::Identifier(index)) =
(&self.collection, &self.index)
{
let collection = if let Some(collection) = context.get_value(&collection.item)? {
collection
} else {
return Err(ValidationError::VariableNotFound {
identifier: collection.item.clone(),
position: collection.position,
});
};
if let ValueInner::Map(map) = collection.inner().as_ref() {
return if let Some(value) = map.get(&index.item) {
Ok(value.r#type(context)?)
} else {
Err(ValidationError::PropertyNotFound {
identifier: index.item.clone(),
position: index.position,
})
};
};
}
if let (
Expression::Value(WithPosition {
item: ValueNode::Map(properties),
..
}),
Expression::Identifier(index),
) = (&self.collection, &self.index)
{
return if let Some(type_result) =
properties
.iter()
.find_map(|(property, type_option, expression)| {
if property == &index.item {
if let Some(r#type) = type_option {
Some(r#type.item.expected_type(context))
} else {
Some(expression.expected_type(context))
}
} else {
None
}
})
{
type_result
} else {
Ok(Type::None)
};
}
if let (
Expression::Value(WithPosition {
item: ValueNode::Structure { fields, .. },
..
}),
Expression::Identifier(index),
) = (&self.collection, &self.index)
{
return if let Some(type_result) = fields.iter().find_map(|(property, expression)| {
if property == &index.item {
Some(expression.expected_type(context))
} else {
None
}
}) {
type_result
} else {
Ok(Type::None)
};
}
Err(ValidationError::CannotIndex {
r#type: self.collection.expected_type(context)?,
position: self.collection.position(),
})
}
fn validate( fn validate(
&self, &self,
_context: &mut Context, _context: &mut Context,
@ -124,11 +43,11 @@ impl AbstractNode for MapIndex {
)); ));
}; };
if let (ValueInner::Map(map), Expression::Identifier(index)) = if let (ValueInner::Map(map), ValueExpression::Identifier(index)) =
(collection.inner().as_ref(), self.index) (collection.inner().as_ref(), self.index)
{ {
let action = map let action = map
.get(&index.item) .get(&index.node)
.map(|value| Action::Return(value.clone())) .map(|value| Action::Return(value.clone()))
.unwrap_or(Action::None); .unwrap_or(Action::None);
@ -143,3 +62,78 @@ impl AbstractNode for MapIndex {
} }
} }
} }
impl ExpectedType for MapIndex {
fn expected_type(&self, context: &mut Context) -> Result<Type, ValidationError> {
if let (ValueExpression::Identifier(collection), ValueExpression::Identifier(index)) =
(&self.collection, &self.index)
{
let collection = if let Some(collection) = context.get_value(&collection.node)? {
collection
} else {
return Err(ValidationError::VariableNotFound {
identifier: collection.node.clone(),
position: collection.position,
});
};
if let ValueInner::Map(map) = collection.inner().as_ref() {
return if let Some(value) = map.get(&index.node) {
Ok(value.r#type(context)?)
} else {
Err(ValidationError::PropertyNotFound {
identifier: index.node.clone(),
position: index.position,
})
};
};
}
if let (
ValueExpression::Value(WithPosition {
node: ValueNode::Map(properties),
..
}),
ValueExpression::Identifier(index),
) = (&self.collection, &self.index)
{
for (property, type_option, expression) in properties {
if property == &index.node {
return if let Some(r#type) = type_option {
Ok(r#type.node.clone())
} else {
Ok(expression.expected_type(context)?)
};
}
}
return Ok(Type::None);
}
if let (
ValueExpression::Value(WithPosition {
node: ValueNode::Structure { fields, .. },
..
}),
ValueExpression::Identifier(index),
) = (&self.collection, &self.index)
{
return if let Some(type_result) = fields.iter().find_map(|(property, expression)| {
if property == &index.node {
Some(expression.expected_type(context))
} else {
None
}
}) {
type_result
} else {
Ok(Type::None)
};
}
Err(ValidationError::CannotIndex {
r#type: self.collection.expected_type(context)?,
position: self.collection.position(),
})
}
}

View File

@ -7,41 +7,18 @@ use crate::{
Value, Value,
}; };
use super::{AbstractNode, Action, Expression, SourcePosition, Type}; use super::{AbstractNode, Action, ExpectedType, SourcePosition, Type, ValueExpression};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum Math { pub enum Math {
Add(Expression, Expression), Add(ValueExpression, ValueExpression),
Subtract(Expression, Expression), Subtract(ValueExpression, ValueExpression),
Multiply(Expression, Expression), Multiply(ValueExpression, ValueExpression),
Divide(Expression, Expression), Divide(ValueExpression, ValueExpression),
Modulo(Expression, Expression), Modulo(ValueExpression, ValueExpression),
} }
impl AbstractNode for Math { impl AbstractNode for Math {
fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> {
match self {
Math::Add(left, right)
| Math::Subtract(left, right)
| Math::Multiply(left, right)
| Math::Divide(left, right)
| Math::Modulo(left, right) => {
let left_type = left.expected_type(_context)?;
let right_type = right.expected_type(_context)?;
if let Type::Float = left_type {
return Ok(Type::Float);
}
if let Type::Float = right_type {
return Ok(Type::Float);
}
Ok(left_type)
}
}
}
fn validate(&self, context: &mut Context, _manage_memory: bool) -> Result<(), ValidationError> { fn validate(&self, context: &mut Context, _manage_memory: bool) -> Result<(), ValidationError> {
match self { match self {
Math::Add(left, right) => { Math::Add(left, right) => {
@ -91,20 +68,21 @@ impl AbstractNode for Math {
} }
fn run(self, _context: &mut Context, _clear_variables: bool) -> Result<Action, RuntimeError> { fn run(self, _context: &mut Context, _clear_variables: bool) -> Result<Action, RuntimeError> {
let run_and_expect_value = let run_and_expect_value = |position: SourcePosition,
|position: SourcePosition, expression: Expression| -> Result<Value, RuntimeError> { expression: ValueExpression|
let action = expression.run(&mut _context.clone(), _clear_variables)?; -> Result<Value, RuntimeError> {
let value = if let Action::Return(value) = action { let action = expression.run(&mut _context.clone(), _clear_variables)?;
value let value = if let Action::Return(value) = action {
} else { value
return Err(RuntimeError::ValidationFailure( } else {
ValidationError::InterpreterExpectedReturn(position), return Err(RuntimeError::ValidationFailure(
)); ValidationError::InterpreterExpectedReturn(position),
}; ));
Ok(value)
}; };
Ok(value)
};
let value = match self { let value = match self {
Math::Add(left, right) => { Math::Add(left, right) => {
let left_position = left.position(); let left_position = left.position();
@ -313,3 +291,28 @@ impl AbstractNode for Math {
Ok(Action::Return(value)) Ok(Action::Return(value))
} }
} }
impl ExpectedType for Math {
fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> {
match self {
Math::Add(left, right)
| Math::Subtract(left, right)
| Math::Multiply(left, right)
| Math::Divide(left, right)
| Math::Modulo(left, right) => {
let left_type = left.expected_type(_context)?;
let right_type = right.expected_type(_context)?;
if let Type::Float = left_type {
return Ok(Type::Float);
}
if let Type::Float = right_type {
return Ok(Type::Float);
}
Ok(left_type)
}
}
}
}

View File

@ -3,7 +3,6 @@ pub mod assignment;
pub mod async_block; pub mod async_block;
pub mod block; pub mod block;
pub mod built_in_function_call; pub mod built_in_function_call;
pub mod expression;
pub mod function_call; pub mod function_call;
pub mod if_else; pub mod if_else;
pub mod list_index; pub mod list_index;
@ -15,6 +14,7 @@ pub mod statement;
pub mod structure_definition; pub mod structure_definition;
pub mod r#type; pub mod r#type;
pub mod type_alias; pub mod type_alias;
pub mod value_expression;
pub mod value_node; pub mod value_node;
pub mod r#while; pub mod r#while;
@ -28,7 +28,6 @@ pub use self::{
async_block::AsyncBlock, async_block::AsyncBlock,
block::Block, block::Block,
built_in_function_call::BuiltInFunctionCall, built_in_function_call::BuiltInFunctionCall,
expression::Expression,
function_call::FunctionCall, function_call::FunctionCall,
if_else::IfElse, if_else::IfElse,
list_index::ListIndex, list_index::ListIndex,
@ -41,7 +40,8 @@ pub use self::{
r#while::While, r#while::While,
statement::Statement, statement::Statement,
structure_definition::StructureDefinition, structure_definition::StructureDefinition,
type_alias::TypeAlias, type_alias::TypeAssignment,
value_expression::ValueExpression,
value_node::ValueNode, value_node::ValueNode,
}; };
@ -53,14 +53,14 @@ use crate::{
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct WithPosition<T> { pub struct WithPosition<T> {
pub item: T, pub node: T,
pub position: SourcePosition, pub position: SourcePosition,
} }
pub trait WithPos: Sized { pub trait WithPos: Sized {
fn with_position<T: Into<SourcePosition>>(self, span: T) -> WithPosition<Self> { fn with_position<T: Into<SourcePosition>>(self, span: T) -> WithPosition<Self> {
WithPosition { WithPosition {
item: self, node: self,
position: span.into(), position: span.into(),
} }
} }
@ -188,7 +188,10 @@ impl Index<usize> for AbstractTree {
} }
pub trait AbstractNode: Sized { pub trait AbstractNode: Sized {
fn expected_type(&self, context: &mut Context) -> Result<Type, ValidationError>;
fn validate(&self, context: &mut Context, manage_memory: bool) -> Result<(), ValidationError>; fn validate(&self, context: &mut Context, manage_memory: bool) -> Result<(), ValidationError>;
fn run(self, context: &mut Context, manage_memory: bool) -> Result<Action, RuntimeError>; fn run(self, context: &mut Context, manage_memory: bool) -> Result<Action, RuntimeError>;
} }
pub trait ExpectedType {
fn expected_type(&self, context: &mut Context) -> Result<Type, ValidationError>;
}

View File

@ -6,8 +6,9 @@ use crate::{
}; };
use super::{ use super::{
AbstractNode, Action, Assignment, AsyncBlock, Block, Expression, IfElse, Loop, SourcePosition, AbstractNode, Action, Assignment, AsyncBlock, Block, ExpectedType, IfElse, Loop,
StructureDefinition, Type, TypeAlias, While, WithPosition, SourcePosition, StructureDefinition, Type, TypeAssignment, ValueExpression, While,
WithPosition,
}; };
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
@ -16,11 +17,11 @@ pub enum Statement {
AsyncBlock(WithPosition<AsyncBlock>), AsyncBlock(WithPosition<AsyncBlock>),
Block(WithPosition<Block>), Block(WithPosition<Block>),
Break(WithPosition<()>), Break(WithPosition<()>),
Expression(Expression),
IfElse(WithPosition<IfElse>), IfElse(WithPosition<IfElse>),
Loop(WithPosition<Loop>), Loop(WithPosition<Loop>),
StructureDefinition(WithPosition<StructureDefinition>), StructureDefinition(WithPosition<StructureDefinition>),
TypeAlias(WithPosition<TypeAlias>), TypeAssignment(WithPosition<TypeAssignment>),
ValueExpression(ValueExpression),
While(WithPosition<While>), While(WithPosition<While>),
} }
@ -31,71 +32,56 @@ impl Statement {
Statement::AsyncBlock(inner) => inner.position, Statement::AsyncBlock(inner) => inner.position,
Statement::Block(inner) => inner.position, Statement::Block(inner) => inner.position,
Statement::Break(inner) => inner.position, Statement::Break(inner) => inner.position,
Statement::Expression(expression) => expression.position(), Statement::ValueExpression(expression) => expression.position(),
Statement::IfElse(inner) => inner.position, Statement::IfElse(inner) => inner.position,
Statement::Loop(inner) => inner.position, Statement::Loop(inner) => inner.position,
Statement::StructureDefinition(inner) => inner.position, Statement::StructureDefinition(inner) => inner.position,
Statement::TypeAlias(inner) => inner.position, Statement::TypeAssignment(inner) => inner.position,
Statement::While(inner) => inner.position, Statement::While(inner) => inner.position,
} }
} }
} }
impl AbstractNode for Statement { impl AbstractNode for Statement {
fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> {
match self {
Statement::Assignment(assignment) => assignment.item.expected_type(_context),
Statement::AsyncBlock(async_block) => async_block.item.expected_type(_context),
Statement::Block(block) => block.item.expected_type(_context),
Statement::Break(_) => Ok(Type::None),
Statement::Expression(expression) => expression.expected_type(_context),
Statement::IfElse(if_else) => if_else.item.expected_type(_context),
Statement::Loop(r#loop) => r#loop.item.expected_type(_context),
Statement::While(r#while) => r#while.item.expected_type(_context),
Statement::TypeAlias(type_alias) => type_alias.item.expected_type(_context),
Statement::StructureDefinition(structure_definition) => {
structure_definition.item.expected_type(_context)
}
}
}
fn validate( fn validate(
&self, &self,
_context: &mut Context, _context: &mut Context,
_manage_memory: bool, _manage_memory: bool,
) -> Result<(), ValidationError> { ) -> Result<(), ValidationError> {
match self { match self {
Statement::Assignment(assignment) => assignment.item.validate(_context, _manage_memory), Statement::Assignment(assignment) => assignment.node.validate(_context, _manage_memory),
Statement::AsyncBlock(async_block) => { Statement::AsyncBlock(async_block) => {
async_block.item.validate(_context, _manage_memory) async_block.node.validate(_context, _manage_memory)
} }
Statement::Block(block) => block.item.validate(_context, _manage_memory), Statement::Block(block) => block.node.validate(_context, _manage_memory),
Statement::Break(_) => Ok(()), Statement::Break(_) => Ok(()),
Statement::Expression(expression) => expression.validate(_context, _manage_memory), Statement::ValueExpression(expression) => expression.validate(_context, _manage_memory),
Statement::IfElse(if_else) => if_else.item.validate(_context, _manage_memory), Statement::IfElse(if_else) => if_else.node.validate(_context, _manage_memory),
Statement::Loop(r#loop) => r#loop.item.validate(_context, _manage_memory), Statement::Loop(r#loop) => r#loop.node.validate(_context, _manage_memory),
Statement::StructureDefinition(structure_definition) => { Statement::StructureDefinition(structure_definition) => {
structure_definition.item.validate(_context, _manage_memory) structure_definition.node.validate(_context, _manage_memory)
} }
Statement::TypeAlias(type_alias) => type_alias.item.validate(_context, _manage_memory), Statement::TypeAssignment(type_alias) => {
Statement::While(r#while) => r#while.item.validate(_context, _manage_memory), type_alias.node.validate(_context, _manage_memory)
}
Statement::While(r#while) => r#while.node.validate(_context, _manage_memory),
} }
} }
fn run(self, context: &mut Context, manage_memory: bool) -> Result<Action, RuntimeError> { fn run(self, context: &mut Context, manage_memory: bool) -> Result<Action, RuntimeError> {
let result = match self { let result = match self {
Statement::Assignment(assignment) => assignment.item.run(context, manage_memory), Statement::Assignment(assignment) => assignment.node.run(context, manage_memory),
Statement::AsyncBlock(async_block) => async_block.item.run(context, manage_memory), Statement::AsyncBlock(async_block) => async_block.node.run(context, manage_memory),
Statement::Block(block) => block.item.run(context, manage_memory), Statement::Block(block) => block.node.run(context, manage_memory),
Statement::Break(_) => Ok(Action::Break), Statement::Break(_) => Ok(Action::Break),
Statement::Expression(expression) => expression.run(context, manage_memory), Statement::ValueExpression(expression) => expression.run(context, manage_memory),
Statement::IfElse(if_else) => if_else.item.run(context, manage_memory), Statement::IfElse(if_else) => if_else.node.run(context, manage_memory),
Statement::Loop(r#loop) => r#loop.item.run(context, manage_memory), Statement::Loop(r#loop) => r#loop.node.run(context, manage_memory),
Statement::StructureDefinition(structure_definition) => { Statement::StructureDefinition(structure_definition) => {
structure_definition.item.run(context, manage_memory) structure_definition.node.run(context, manage_memory)
} }
Statement::TypeAlias(type_alias) => type_alias.item.run(context, manage_memory), Statement::TypeAssignment(type_alias) => type_alias.node.run(context, manage_memory),
Statement::While(r#while) => r#while.item.run(context, manage_memory), Statement::While(r#while) => r#while.node.run(context, manage_memory),
}; };
if manage_memory { if manage_memory {
@ -105,3 +91,15 @@ impl AbstractNode for Statement {
result result
} }
} }
impl ExpectedType for Statement {
fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> {
match self {
Statement::ValueExpression(expression) => expression.expected_type(_context),
Statement::IfElse(if_else) => if_else.node.expected_type(_context),
Statement::Block(block) => block.node.expected_type(_context),
Statement::AsyncBlock(async_block) => async_block.node.expected_type(_context),
_ => Ok(Type::None),
}
}
}

View File

@ -21,10 +21,6 @@ impl StructureDefinition {
} }
impl AbstractNode for StructureDefinition { impl AbstractNode for StructureDefinition {
fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> {
Ok(Type::None)
}
fn validate( fn validate(
&self, &self,
_context: &mut Context, _context: &mut Context,

View File

@ -58,27 +58,27 @@ impl Type {
} }
} }
(Type::ListOf(left), Type::ListOf(right)) => { (Type::ListOf(left), Type::ListOf(right)) => {
if let Ok(()) = left.item.check(&right.item) { if let Ok(()) = left.node.check(&right.node) {
return Ok(()); return Ok(());
} }
} }
(Type::ListOf(list_of), Type::ListExact(list_exact)) => { (Type::ListOf(list_of), Type::ListExact(list_exact)) => {
for r#type in list_exact { for r#type in list_exact {
list_of.item.check(&r#type.item)?; list_of.node.check(&r#type.node)?;
} }
return Ok(()); return Ok(());
} }
(Type::ListExact(list_exact), Type::ListOf(list_of)) => { (Type::ListExact(list_exact), Type::ListOf(list_of)) => {
for r#type in list_exact { for r#type in list_exact {
r#type.item.check(&list_of.item)?; r#type.node.check(&list_of.node)?;
} }
return Ok(()); return Ok(());
} }
(Type::ListExact(left), Type::ListExact(right)) => { (Type::ListExact(left), Type::ListExact(right)) => {
for (left, right) in left.iter().zip(right.iter()) { for (left, right) in left.iter().zip(right.iter()) {
left.item.check(&right.item)?; left.node.check(&right.node)?;
} }
return Ok(()); return Ok(());
@ -97,7 +97,7 @@ impl Type {
for ((left_field_name, left_type), (right_field_name, right_type)) in for ((left_field_name, left_type), (right_field_name, right_type)) in
left_fields.iter().zip(right_fields.iter()) left_fields.iter().zip(right_fields.iter())
{ {
if left_field_name != right_field_name || left_type.item != right_type.item if left_field_name != right_field_name || left_type.node != right_type.node
{ {
return Err(TypeConflict { return Err(TypeConflict {
actual: other.clone(), actual: other.clone(),
@ -119,11 +119,11 @@ impl Type {
return_type: right_return, return_type: right_return,
}, },
) => { ) => {
if left_return.item == right_return.item { if left_return.node == right_return.node {
for (left_parameter, right_parameter) in for (left_parameter, right_parameter) in
left_parameters.iter().zip(right_parameters.iter()) left_parameters.iter().zip(right_parameters.iter())
{ {
if left_parameter.item != right_parameter.item { if left_parameter.node != right_parameter.node {
return Err(TypeConflict { return Err(TypeConflict {
actual: other.clone(), actual: other.clone(),
expected: self.clone(), expected: self.clone(),
@ -145,10 +145,6 @@ impl Type {
} }
impl AbstractNode for Type { impl AbstractNode for Type {
fn expected_type(&self, _: &mut Context) -> Result<Type, ValidationError> {
Ok(Type::None)
}
fn validate( fn validate(
&self, &self,
_context: &mut Context, _context: &mut Context,
@ -170,15 +166,15 @@ impl Display for Type {
Type::Float => write!(f, "float"), Type::Float => write!(f, "float"),
Type::Integer => write!(f, "int"), Type::Integer => write!(f, "int"),
Type::List => write!(f, "list"), Type::List => write!(f, "list"),
Type::ListOf(item_type) => write!(f, "list({})", item_type.item), Type::ListOf(item_type) => write!(f, "list({})", item_type.node),
Type::ListExact(item_types) => { Type::ListExact(item_types) => {
write!(f, "[")?; write!(f, "[")?;
for (index, item_type) in item_types.into_iter().enumerate() { for (index, item_type) in item_types.into_iter().enumerate() {
if index == item_types.len() - 1 { if index == item_types.len() - 1 {
write!(f, "{}", item_type.item)?; write!(f, "{}", item_type.node)?;
} else { } else {
write!(f, "{}, ", item_type.item)?; write!(f, "{}, ", item_type.node)?;
} }
} }
@ -195,10 +191,10 @@ impl Display for Type {
write!(f, "(")?; write!(f, "(")?;
for r#type in parameter_types { for r#type in parameter_types {
write!(f, "{} ", r#type.item)?; write!(f, "{} ", r#type.node)?;
} }
write!(f, ") : {}", return_type.item) write!(f, ") : {}", return_type.node)
} }
Type::Structure { name, .. } => write!(f, "{name}"), Type::Structure { name, .. } => write!(f, "{name}"),
Type::Argument(identifier) => write!(f, "{identifier}"), Type::Argument(identifier) => write!(f, "{identifier}"),

View File

@ -9,22 +9,18 @@ use crate::{
use super::{AbstractNode, Action, Type, WithPosition}; use super::{AbstractNode, Action, Type, WithPosition};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct TypeAlias { pub struct TypeAssignment {
identifier: WithPosition<Identifier>, identifier: WithPosition<Identifier>,
r#type: WithPosition<Type>, r#type: WithPosition<Type>,
} }
impl TypeAlias { impl TypeAssignment {
pub fn new(identifier: WithPosition<Identifier>, r#type: WithPosition<Type>) -> Self { pub fn new(identifier: WithPosition<Identifier>, r#type: WithPosition<Type>) -> Self {
Self { identifier, r#type } Self { identifier, r#type }
} }
} }
impl AbstractNode for TypeAlias { impl AbstractNode for TypeAssignment {
fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> {
Ok(Type::None)
}
fn validate( fn validate(
&self, &self,
_context: &mut Context, _context: &mut Context,
@ -34,7 +30,7 @@ impl AbstractNode for TypeAlias {
} }
fn run(self, context: &mut Context, _manage_memory: bool) -> Result<Action, RuntimeError> { fn run(self, context: &mut Context, _manage_memory: bool) -> Result<Action, RuntimeError> {
context.set_type(self.identifier.item, self.r#type.item)?; context.set_type(self.identifier.node, self.r#type.node)?;
Ok(Action::None) Ok(Action::None)
} }

View File

@ -0,0 +1,142 @@
use serde::{Deserialize, Serialize};
use crate::{
context::Context,
error::{RuntimeError, ValidationError},
identifier::Identifier,
};
use super::{
AbstractNode, Action, As, BuiltInFunctionCall, ExpectedType, FunctionCall, ListIndex, Logic,
MapIndex, Math, SourcePosition, Type, ValueNode, WithPosition,
};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum ValueExpression {
As(WithPosition<Box<As>>),
BuiltInFunctionCall(WithPosition<Box<BuiltInFunctionCall>>),
FunctionCall(WithPosition<FunctionCall>),
Identifier(WithPosition<Identifier>),
MapIndex(WithPosition<Box<MapIndex>>),
ListIndex(WithPosition<Box<ListIndex>>),
Logic(WithPosition<Box<Logic>>),
Math(WithPosition<Box<Math>>),
Value(WithPosition<ValueNode>),
}
impl ValueExpression {
pub fn position(&self) -> SourcePosition {
match self {
ValueExpression::As(inner) => inner.position,
ValueExpression::FunctionCall(inner) => inner.position,
ValueExpression::Identifier(inner) => inner.position,
ValueExpression::MapIndex(inner) => inner.position,
ValueExpression::ListIndex(inner) => inner.position,
ValueExpression::Logic(inner) => inner.position,
ValueExpression::Math(inner) => inner.position,
ValueExpression::Value(inner) => inner.position,
ValueExpression::BuiltInFunctionCall(inner) => inner.position,
}
}
}
impl AbstractNode for ValueExpression {
fn validate(&self, context: &mut Context, manage_memory: bool) -> Result<(), ValidationError> {
match self {
ValueExpression::As(r#as) => r#as.node.validate(context, manage_memory),
ValueExpression::FunctionCall(function_call) => {
function_call.node.validate(context, manage_memory)
}
ValueExpression::Identifier(identifier) => {
let found = if manage_memory {
context.add_expected_use(&identifier.node)?
} else {
context.contains(&identifier.node)?
};
if found {
Ok(())
} else {
Err(ValidationError::VariableNotFound {
identifier: identifier.node.clone(),
position: identifier.position,
})
}
}
ValueExpression::MapIndex(map_index) => map_index.node.validate(context, manage_memory),
ValueExpression::ListIndex(list_index) => {
list_index.node.validate(context, manage_memory)
}
ValueExpression::Logic(logic) => logic.node.validate(context, manage_memory),
ValueExpression::Math(math) => math.node.validate(context, manage_memory),
ValueExpression::Value(value_node) => value_node.node.validate(context, manage_memory),
ValueExpression::BuiltInFunctionCall(built_in_function_call) => {
built_in_function_call.node.validate(context, manage_memory)
}
}
}
fn run(self, context: &mut Context, manage_memory: bool) -> Result<Action, RuntimeError> {
match self {
ValueExpression::As(r#as) => r#as.node.run(context, manage_memory),
ValueExpression::FunctionCall(function_call) => {
function_call.node.run(context, manage_memory)
}
ValueExpression::Identifier(identifier) => {
let value_option = if manage_memory {
context.use_value(&identifier.node)?
} else {
context.get_value(&identifier.node)?
};
if let Some(value) = value_option {
Ok(Action::Return(value))
} else {
Err(RuntimeError::ValidationFailure(
ValidationError::VariableNotFound {
identifier: identifier.node.clone(),
position: identifier.position,
},
))
}
}
ValueExpression::MapIndex(map_index) => map_index.node.run(context, manage_memory),
ValueExpression::ListIndex(list_index) => list_index.node.run(context, manage_memory),
ValueExpression::Logic(logic) => logic.node.run(context, manage_memory),
ValueExpression::Math(math) => math.node.run(context, manage_memory),
ValueExpression::Value(value_node) => value_node.node.run(context, manage_memory),
ValueExpression::BuiltInFunctionCall(built_in_function_call) => {
built_in_function_call.node.run(context, manage_memory)
}
}
}
}
impl ExpectedType for ValueExpression {
fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> {
match self {
ValueExpression::As(r#as) => r#as.node.expected_type(_context),
ValueExpression::FunctionCall(function_call) => {
function_call.node.expected_type(_context)
}
ValueExpression::Identifier(identifier) => {
if let Some(r#type) = _context.get_type(&identifier.node)? {
Ok(r#type)
} else {
Err(ValidationError::VariableNotFound {
identifier: identifier.node.clone(),
position: identifier.position,
})
}
}
ValueExpression::MapIndex(map_index) => map_index.node.expected_type(_context),
ValueExpression::ListIndex(list_index) => list_index.node.expected_type(_context),
ValueExpression::Logic(logic) => logic.node.expected_type(_context),
ValueExpression::Math(math) => math.node.expected_type(_context),
ValueExpression::Value(value_node) => value_node.node.expected_type(_context),
ValueExpression::BuiltInFunctionCall(built_in_function_call) => {
built_in_function_call.node.expected_type(_context)
}
}
}
}

View File

@ -9,20 +9,22 @@ use crate::{
Value, Value,
}; };
use super::{AbstractNode, Action, Block, Expression, Type, WithPos, WithPosition}; use super::{
AbstractNode, Action, Block, ExpectedType, Type, ValueExpression, WithPos, WithPosition,
};
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum ValueNode { pub enum ValueNode {
Boolean(bool), Boolean(bool),
Float(f64), Float(f64),
Integer(i64), Integer(i64),
List(Vec<Expression>), List(Vec<ValueExpression>),
Map(Vec<(Identifier, Option<WithPosition<Type>>, Expression)>), Map(Vec<(Identifier, Option<WithPosition<Type>>, ValueExpression)>),
Range(Range<i64>), Range(Range<i64>),
String(String), String(String),
Structure { Structure {
name: WithPosition<Identifier>, name: WithPosition<Identifier>,
fields: Vec<(Identifier, Expression)>, fields: Vec<(Identifier, ValueExpression)>,
}, },
ParsedFunction { ParsedFunction {
type_arguments: Vec<WithPosition<Type>>, type_arguments: Vec<WithPosition<Type>>,
@ -33,66 +35,6 @@ pub enum ValueNode {
} }
impl AbstractNode for ValueNode { impl AbstractNode for ValueNode {
fn expected_type(&self, context: &mut Context) -> Result<Type, ValidationError> {
let r#type = match self {
ValueNode::Boolean(_) => Type::Boolean,
ValueNode::Float(_) => Type::Float,
ValueNode::Integer(_) => Type::Integer,
ValueNode::List(items) => {
let mut item_types = Vec::with_capacity(items.len());
for expression in items {
item_types.push(
expression
.expected_type(context)?
.with_position(expression.position()),
);
}
Type::ListExact(item_types)
}
ValueNode::Map(_) => Type::Map,
ValueNode::Range(_) => Type::Range,
ValueNode::String(_) => Type::String,
ValueNode::ParsedFunction {
parameters,
return_type,
..
} => Type::Function {
parameter_types: parameters
.iter()
.map(|(_, r#type)| r#type.clone())
.collect(),
return_type: Box::new(return_type.clone()),
},
ValueNode::Structure {
name,
fields: expressions,
} => {
let mut types = Vec::with_capacity(expressions.len());
for (identifier, expression) in expressions {
let r#type = expression.expected_type(context)?;
types.push((
identifier.clone(),
WithPosition {
item: r#type,
position: expression.position(),
},
));
}
Type::Structure {
name: name.item.clone(),
fields: types,
}
}
};
Ok(r#type)
}
fn validate(&self, context: &mut Context, _manage_memory: bool) -> Result<(), ValidationError> { fn validate(&self, context: &mut Context, _manage_memory: bool) -> Result<(), ValidationError> {
if let ValueNode::Map(map_assignments) = self { if let ValueNode::Map(map_assignments) = self {
for (_identifier, r#type, expression) in map_assignments { for (_identifier, r#type, expression) in map_assignments {
@ -101,7 +43,7 @@ impl AbstractNode for ValueNode {
if let Some(expected_type) = r#type { if let Some(expected_type) = r#type {
let actual_type = expression.expected_type(context)?; let actual_type = expression.expected_type(context)?;
expected_type.item.check(&actual_type).map_err(|conflict| { expected_type.node.check(&actual_type).map_err(|conflict| {
ValidationError::TypeCheck { ValidationError::TypeCheck {
conflict, conflict,
actual_position: expression.position(), actual_position: expression.position(),
@ -124,21 +66,21 @@ impl AbstractNode for ValueNode {
let mut function_context = Context::new(Some(&context)); let mut function_context = Context::new(Some(&context));
for r#type in type_arguments { for r#type in type_arguments {
if let Type::Argument(identifier) = &r#type.item { if let Type::Argument(identifier) = &r#type.node {
function_context.set_type(identifier.clone(), r#type.item.clone())?; function_context.set_type(identifier.clone(), r#type.node.clone())?;
} }
} }
for (identifier, r#type) in parameters { for (identifier, r#type) in parameters {
function_context.set_type(identifier.clone(), r#type.item.clone())?; function_context.set_type(identifier.clone(), r#type.node.clone())?;
} }
body.item.validate(&mut function_context, _manage_memory)?; body.node.validate(&mut function_context, _manage_memory)?;
let actual_return_type = body.item.expected_type(&mut function_context)?; let actual_return_type = body.node.expected_type(&mut function_context)?;
return_type return_type
.item .node
.check(&actual_return_type) .check(&actual_return_type)
.map_err(|conflict| ValidationError::TypeCheck { .map_err(|conflict| ValidationError::TypeCheck {
conflict, conflict,
@ -154,9 +96,9 @@ impl AbstractNode for ValueNode {
fields: expressions, fields: expressions,
} = self } = self
{ {
if !context.contains(&name.item)? { if !context.contains(&name.node)? {
return Err(ValidationError::VariableNotFound { return Err(ValidationError::VariableNotFound {
identifier: name.item.clone(), identifier: name.node.clone(),
position: name.position, position: name.position,
}); });
} }
@ -164,12 +106,12 @@ impl AbstractNode for ValueNode {
if let Some(Type::Structure { if let Some(Type::Structure {
name: _, name: _,
fields: types, fields: types,
}) = context.get_type(&name.item)? }) = context.get_type(&name.node)?
{ {
for ((_, expression), (_, expected_type)) in expressions.iter().zip(types.iter()) { for ((_, expression), (_, expected_type)) in expressions.iter().zip(types.iter()) {
let actual_type = expression.expected_type(context)?; let actual_type = expression.expected_type(context)?;
expected_type.item.check(&actual_type).map_err(|conflict| { expected_type.node.check(&actual_type).map_err(|conflict| {
ValidationError::TypeCheck { ValidationError::TypeCheck {
conflict, conflict,
actual_position: expression.position(), actual_position: expression.position(),
@ -196,7 +138,7 @@ impl AbstractNode for ValueNode {
let action = expression.run(_context, _manage_memory)?; let action = expression.run(_context, _manage_memory)?;
let value = if let Action::Return(value) = action { let value = if let Action::Return(value) = action {
WithPosition { WithPosition {
item: value, node: value,
position: expression_position, position: expression_position,
} }
} else { } else {
@ -357,3 +299,65 @@ impl Ord for ValueNode {
} }
} }
} }
impl ExpectedType for ValueNode {
fn expected_type(&self, context: &mut Context) -> Result<Type, ValidationError> {
let r#type = match self {
ValueNode::Boolean(_) => Type::Boolean,
ValueNode::Float(_) => Type::Float,
ValueNode::Integer(_) => Type::Integer,
ValueNode::List(items) => {
let mut item_types = Vec::with_capacity(items.len());
for expression in items {
item_types.push(
expression
.expected_type(context)?
.with_position(expression.position()),
);
}
Type::ListExact(item_types)
}
ValueNode::Map(_) => Type::Map,
ValueNode::Range(_) => Type::Range,
ValueNode::String(_) => Type::String,
ValueNode::ParsedFunction {
parameters,
return_type,
..
} => Type::Function {
parameter_types: parameters
.iter()
.map(|(_, r#type)| r#type.clone())
.collect(),
return_type: Box::new(return_type.clone()),
},
ValueNode::Structure {
name,
fields: expressions,
} => {
let mut types = Vec::with_capacity(expressions.len());
for (identifier, expression) in expressions {
let r#type = expression.expected_type(context)?;
types.push((
identifier.clone(),
WithPosition {
node: r#type,
position: expression.position(),
},
));
}
Type::Structure {
name: name.node.clone(),
fields: types,
}
}
};
Ok(r#type)
}
}

View File

@ -7,16 +7,16 @@ use crate::{
Value, Value,
}; };
use super::{AbstractNode, Action, Expression, Statement, Type}; use super::{AbstractNode, Action, Statement, ValueExpression};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct While { pub struct While {
expression: Expression, expression: ValueExpression,
statements: Vec<Statement>, statements: Vec<Statement>,
} }
impl While { impl While {
pub fn new(expression: Expression, statements: Vec<Statement>) -> Self { pub fn new(expression: ValueExpression, statements: Vec<Statement>) -> Self {
Self { Self {
expression, expression,
statements, statements,
@ -25,10 +25,6 @@ impl While {
} }
impl AbstractNode for While { impl AbstractNode for While {
fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> {
Ok(Type::None)
}
fn validate( fn validate(
&self, &self,
_context: &mut Context, _context: &mut Context,

View File

@ -403,7 +403,7 @@ impl InterpreterError {
.with_message(format!("This has type {}.", actual.fg(type_color),)), .with_message(format!("This has type {}.", actual.fg(type_color),)),
) )
} }
ValidationError::ExpectedString { actual, position } => todo!(), ValidationError::ExpectedString { .. } => todo!(),
} }
} }
let report = builder.finish(); let report = builder.finish();

File diff suppressed because it is too large Load Diff

View File

@ -109,9 +109,9 @@ impl Display for Value {
for (index, value) in list.into_iter().enumerate() { for (index, value) in list.into_iter().enumerate() {
if index == list.len() - 1 { if index == list.len() - 1 {
write!(f, "{}", value.item)?; write!(f, "{}", value.node)?;
} else { } else {
write!(f, "{}, ", value.item)?; write!(f, "{}, ", value.node)?;
} }
} }
@ -139,9 +139,9 @@ impl Display for Value {
for (index, r#type) in type_arguments.into_iter().enumerate() { for (index, r#type) in type_arguments.into_iter().enumerate() {
if index == type_arguments.len() - 1 { if index == type_arguments.len() - 1 {
write!(f, "{}", r#type.item)?; write!(f, "{}", r#type.node)?;
} else { } else {
write!(f, "{} ", r#type.item)?; write!(f, "{} ", r#type.node)?;
} }
} }
@ -151,13 +151,13 @@ impl Display for Value {
write!(f, "(")?; write!(f, "(")?;
for (identifier, r#type) in parameters { for (identifier, r#type) in parameters {
write!(f, "{identifier}: {}", r#type.item)?; write!(f, "{identifier}: {}", r#type.node)?;
} }
write!(f, "): {} {:?}", return_type.item, body.item) write!(f, "): {} {:?}", return_type.node, body.node)
} }
ValueInner::Structure { name, fields } => { ValueInner::Structure { name, fields } => {
write!(f, "{}\n{{", name.item)?; write!(f, "{}\n{{", name.node)?;
for (key, value) in fields { for (key, value) in fields {
writeln!(f, "{key} = {value},")?; writeln!(f, "{key} = {value},")?;
@ -184,7 +184,7 @@ impl Ord for Value {
} }
impl Serialize for Value { impl Serialize for Value {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> fn serialize<S>(&self, _serializer: S) -> Result<S::Ok, S::Error>
where where
S: serde::Serializer, S: serde::Serializer,
{ {
@ -193,7 +193,7 @@ impl Serialize for Value {
} }
impl<'de> Deserialize<'de> for Value { impl<'de> Deserialize<'de> for Value {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> fn deserialize<D>(_deserializer: D) -> Result<Self, D::Error>
where where
D: serde::Deserializer<'de>, D: serde::Deserializer<'de>,
{ {
@ -227,7 +227,7 @@ impl ValueInner {
let mut types = Vec::with_capacity(values.len()); let mut types = Vec::with_capacity(values.len());
for value in values { for value in values {
types.push(value.item.r#type(context)?.with_position(value.position)); types.push(value.node.r#type(context)?.with_position(value.position));
} }
Type::ListExact(types) Type::ListExact(types)
@ -244,11 +244,11 @@ impl ValueInner {
return_type: Box::new(function.return_type.clone()), return_type: Box::new(function.return_type.clone()),
}, },
ValueInner::Structure { name, .. } => { ValueInner::Structure { name, .. } => {
if let Some(r#type) = context.get_type(&name.item)? { if let Some(r#type) = context.get_type(&name.node)? {
r#type r#type
} else { } else {
return Err(ValidationError::VariableNotFound { return Err(ValidationError::VariableNotFound {
identifier: name.item.clone(), identifier: name.node.clone(),
position: name.position, position: name.position,
}); });
} }
@ -342,6 +342,6 @@ impl Function {
context.set_value(identifier.clone(), value)?; context.set_value(identifier.clone(), value)?;
} }
self.body.item.run(context, clear_variables) self.body.node.run(context, clear_variables)
} }
} }

View File

@ -28,20 +28,6 @@ fn function_call() {
); );
} }
#[test]
fn call_empty_function() {
assert_eq!(
interpret(
"test",
"
foobar = fn (message : str) none {}
foobar('Hiya')
",
),
Ok(None)
);
}
#[test] #[test]
fn callback() { fn callback() {
assert_eq!( assert_eq!(

View File

@ -1,5 +1,5 @@
use dust_lang::{ use dust_lang::{
abstract_tree::{Block, Expression, Statement, Type, WithPos}, abstract_tree::{Block, Statement, Type, ValueExpression, WithPos},
error::{Error, TypeConflict, ValidationError}, error::{Error, TypeConflict, ValidationError},
identifier::Identifier, identifier::Identifier,
*, *,
@ -49,9 +49,9 @@ fn function_variable() {
Vec::with_capacity(0), Vec::with_capacity(0),
vec![(Identifier::new("x"), Type::Integer.with_position((16, 19)))], vec![(Identifier::new("x"), Type::Integer.with_position((16, 19)))],
Type::Integer.with_position((21, 24)), Type::Integer.with_position((21, 24)),
Block::new(vec![Statement::Expression(Expression::Identifier( Block::new(vec![Statement::ValueExpression(
Identifier::new("x").with_position((27, 28)) ValueExpression::Identifier(Identifier::new("x").with_position((27, 28)))
))]) )])
.with_position((25, 30)) .with_position((25, 30))
))) )))
); );