Add type constructor

This commit is contained in:
Jeff 2024-06-17 10:10:06 -04:00
parent a0b754cc1c
commit e448c9dd4c
29 changed files with 1126 additions and 1041 deletions

View File

@ -9,17 +9,22 @@ use crate::{
Value, Value,
}; };
use super::{AbstractNode, Action, ExpectedType, Type, ValueExpression, WithPosition}; use super::{
AbstractNode, Evaluation, ExpectedType, Expression, Type, TypeConstructor, 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: ValueExpression, expression: Expression,
r#type: WithPosition<Type>, constructor: WithPosition<TypeConstructor>,
} }
impl As { impl As {
pub fn new(expression: ValueExpression, r#type: WithPosition<Type>) -> Self { pub fn new(expression: Expression, constructor: WithPosition<TypeConstructor>) -> Self {
Self { expression, r#type } Self {
expression,
constructor,
}
} }
} }
@ -29,28 +34,35 @@ impl AbstractNode for As {
_context: &mut Context, _context: &mut Context,
_manage_memory: bool, _manage_memory: bool,
) -> Result<(), ValidationError> { ) -> Result<(), ValidationError> {
match self.r#type.node { match self.constructor.node {
Type::Boolean | Type::Float | Type::Integer | Type::String => {} TypeConstructor::Type(_) => {}
_ => todo!("Create an error for this occurence."), _ => todo!("Create an error for this occurence."),
}; };
match self.expression.expected_type(_context)? { match self.expression.expected_type(_context)? {
Type::Boolean | Type::Float | Type::Integer | Type::String => Ok(()), Type::Boolean | Type::Float | Type::Integer | Type::String => {}
_ => todo!("Create an error for this occurence."), _ => todo!("Create an error for this occurence."),
} };
Ok(())
} }
fn run(self, _context: &mut Context, _manage_memory: bool) -> Result<Action, RuntimeError> { fn evaluate(
self,
context: &mut Context,
_manage_memory: bool,
) -> Result<Evaluation, RuntimeError> {
let expression_position = self.expression.position(); let expression_position = self.expression.position();
let action = self.expression.run(_context, _manage_memory)?; let action = self.expression.evaluate(context, _manage_memory)?;
let value = if let Action::Return(value) = action { let value = if let Evaluation::Return(value) = action {
value value
} else { } else {
return Err(RuntimeError::ValidationFailure( return Err(RuntimeError::ValidationFailure(
ValidationError::InterpreterExpectedReturn(expression_position), ValidationError::InterpreterExpectedReturn(expression_position),
)); ));
}; };
let (from_value, to_type): (&ValueInner, Type) = (value.inner().borrow(), self.r#type.node); let r#type = self.constructor.node.construct(&context)?;
let (from_value, to_type): (&ValueInner, Type) = (value.inner().borrow(), r#type);
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()),
@ -58,12 +70,12 @@ impl AbstractNode for As {
_ => todo!("Create an error for this occurence."), _ => todo!("Create an error for this occurence."),
}; };
Ok(Action::Return(converted)) Ok(Evaluation::Return(converted))
} }
} }
impl ExpectedType for As { impl ExpectedType for As {
fn expected_type(&self, _: &mut Context) -> Result<Type, ValidationError> { fn expected_type(&self, context: &mut Context) -> Result<Type, ValidationError> {
Ok(self.r#type.node.clone()) self.constructor.node.clone().construct(&context)
} }
} }

View File

@ -7,12 +7,12 @@ use crate::{
Context, Value, Context, Value,
}; };
use super::{AbstractNode, Action, ExpectedType, Statement, Type, WithPosition}; use super::{AbstractNode, Evaluation, ExpectedType, Statement, TypeConstructor, 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 {
identifier: WithPosition<Identifier>, identifier: WithPosition<Identifier>,
r#type: Option<WithPosition<Type>>, constructor: Option<WithPosition<TypeConstructor>>,
operator: AssignmentOperator, operator: AssignmentOperator,
statement: Box<Statement>, statement: Box<Statement>,
} }
@ -27,13 +27,13 @@ pub enum AssignmentOperator {
impl Assignment { impl Assignment {
pub fn new( pub fn new(
identifier: WithPosition<Identifier>, identifier: WithPosition<Identifier>,
r#type: Option<WithPosition<Type>>, constructor: Option<WithPosition<TypeConstructor>>,
operator: AssignmentOperator, operator: AssignmentOperator,
statement: Statement, statement: Statement,
) -> Self { ) -> Self {
Self { Self {
identifier, identifier,
r#type, constructor,
operator, operator,
statement: Box::new(statement), statement: Box::new(statement),
} }
@ -45,19 +45,21 @@ impl AbstractNode for Assignment {
let statement_type = self.statement.expected_type(context)?; let statement_type = self.statement.expected_type(context)?;
if let Some(WithPosition { if let Some(WithPosition {
node: expected_type, node: constructor,
position: expected_position, position: expected_position,
}) = &self.r#type }) = &self.constructor
{ {
expected_type.check(&statement_type).map_err(|conflict| { let r#type = constructor.clone().construct(&context)?;
ValidationError::TypeCheck {
r#type
.check(&statement_type)
.map_err(|conflict| ValidationError::TypeCheck {
conflict, conflict,
actual_position: self.statement.position(), actual_position: self.statement.position(),
expected_position: expected_position.clone(), expected_position: Some(expected_position.clone()),
} })?;
})?;
context.set_type(self.identifier.node.clone(), expected_type.clone())?; context.set_type(self.identifier.node.clone(), r#type.clone())?;
} else { } else {
context.set_type(self.identifier.node.clone(), statement_type)?; context.set_type(self.identifier.node.clone(), statement_type)?;
} }
@ -67,10 +69,14 @@ impl AbstractNode for Assignment {
Ok(()) Ok(())
} }
fn run(self, context: &mut Context, manage_memory: bool) -> Result<Action, RuntimeError> { fn evaluate(
let action = self.statement.run(context, manage_memory)?; self,
context: &mut Context,
manage_memory: bool,
) -> Result<Evaluation, RuntimeError> {
let action = self.statement.evaluate(context, manage_memory)?;
let right = match action { let right = match action {
Action::Return(value) => value, Evaluation::Return(value) => value,
r#break => return Ok(r#break), r#break => return Ok(r#break),
}; };
@ -170,6 +176,6 @@ impl AbstractNode for Assignment {
} }
} }
Ok(Action::None) Ok(Evaluation::None)
} }
} }

View File

@ -8,7 +8,7 @@ use crate::{
error::{RuntimeError, RwLockPoisonError, ValidationError}, error::{RuntimeError, RwLockPoisonError, ValidationError},
}; };
use super::{AbstractNode, Action, ExpectedType, Statement, Type}; use super::{AbstractNode, Evaluation, 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 {
@ -30,15 +30,19 @@ impl AbstractNode for AsyncBlock {
Ok(()) Ok(())
} }
fn run(self, _context: &mut Context, _manage_memory: bool) -> Result<Action, RuntimeError> { fn evaluate(
self,
_context: &mut Context,
_manage_memory: bool,
) -> Result<Evaluation, RuntimeError> {
let statement_count = self.statements.len(); let statement_count = self.statements.len();
let final_result = RwLock::new(Ok(Action::None)); let final_result = RwLock::new(Ok(Evaluation::None));
self.statements self.statements
.into_par_iter() .into_par_iter()
.enumerate() .enumerate()
.find_map_first(|(index, statement)| { .find_map_first(|(index, statement)| {
let result = statement.run(&mut _context.clone(), false); let result = statement.evaluate(&mut _context.clone(), false);
if index == statement_count - 1 { if index == statement_count - 1 {
let get_write_lock = final_result.write(); let get_write_lock = final_result.write();

View File

@ -5,7 +5,7 @@ use crate::{
error::{RuntimeError, ValidationError}, error::{RuntimeError, ValidationError},
}; };
use super::{AbstractNode, Action, ExpectedType, Statement}; use super::{AbstractNode, Evaluation, ExpectedType, Statement, Type};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct Block { pub struct Block {
@ -39,11 +39,15 @@ impl AbstractNode for Block {
Ok(()) Ok(())
} }
fn run(self, _context: &mut Context, _manage_memory: bool) -> Result<Action, RuntimeError> { fn evaluate(
let mut previous = Action::None; self,
_context: &mut Context,
_manage_memory: bool,
) -> Result<Evaluation, RuntimeError> {
let mut previous = Evaluation::None;
for statement in self.statements { for statement in self.statements {
previous = statement.run(_context, _manage_memory)?; previous = statement.evaluate(_context, _manage_memory)?;
} }
Ok(previous) Ok(previous)
@ -51,7 +55,7 @@ impl AbstractNode for Block {
} }
impl ExpectedType for Block { impl ExpectedType for Block {
fn expected_type(&self, _context: &mut Context) -> Result<super::Type, ValidationError> { fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> {
self.last_statement().expected_type(_context) self.last_statement().expected_type(_context)
} }
} }
@ -59,7 +63,7 @@ impl ExpectedType for Block {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::{ use crate::{
abstract_tree::{Type, ValueExpression, ValueNode, WithPos}, abstract_tree::{Expression, ValueNode, WithPos},
Value, Value,
}; };
@ -68,30 +72,30 @@ 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::ValueExpression(ValueExpression::Value( Statement::ValueExpression(Expression::Value(
ValueNode::Integer(1).with_position((0, 0)), ValueNode::Integer(1).with_position((0, 0)),
)), )),
Statement::ValueExpression(ValueExpression::Value( Statement::ValueExpression(Expression::Value(
ValueNode::Integer(2).with_position((0, 0)), ValueNode::Integer(2).with_position((0, 0)),
)), )),
Statement::ValueExpression(ValueExpression::Value( Statement::ValueExpression(Expression::Value(
ValueNode::Integer(42).with_position((0, 0)), ValueNode::Integer(42).with_position((0, 0)),
)), )),
]); ]);
assert_eq!( assert_eq!(
block.run(&mut Context::new(None), true).unwrap(), block.evaluate(&mut Context::new(None), true).unwrap(),
Action::Return(Value::integer(42)) Evaluation::Return(Value::integer(42))
) )
} }
#[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::ValueExpression(ValueExpression::Value( Statement::ValueExpression(Expression::Value(
ValueNode::String("42".to_string()).with_position((0, 0)), ValueNode::String("42".to_string()).with_position((0, 0)),
)), )),
Statement::ValueExpression(ValueExpression::Value( Statement::ValueExpression(Expression::Value(
ValueNode::Integer(42).with_position((0, 0)), ValueNode::Integer(42).with_position((0, 0)),
)), )),
]); ]);

View File

@ -8,23 +8,22 @@ use std::{
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{ use crate::{
abstract_tree::{Action, Type},
context::Context, context::Context,
error::{RuntimeError, ValidationError}, error::{RuntimeError, ValidationError},
value::ValueInner, value::ValueInner,
Value, Value,
}; };
use super::{AbstractNode, ExpectedType, ValueExpression, WithPosition}; use super::{AbstractNode, Evaluation, ExpectedType, Expression, Type, TypeConstructor};
#[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>, ValueExpression), JsonParse(TypeConstructor, Expression),
Length(ValueExpression), Length(Expression),
ReadFile(ValueExpression), ReadFile(Expression),
ReadLine, ReadLine,
Sleep(ValueExpression), Sleep(Expression),
WriteLine(ValueExpression), WriteLine(Expression),
} }
impl AbstractNode for BuiltInFunctionCall { impl AbstractNode for BuiltInFunctionCall {
@ -51,11 +50,15 @@ impl AbstractNode for BuiltInFunctionCall {
} }
} }
fn run(self, context: &mut Context, _manage_memory: bool) -> Result<Action, RuntimeError> { fn evaluate(
self,
context: &mut Context,
_manage_memory: bool,
) -> Result<Evaluation, RuntimeError> {
match self { match self {
BuiltInFunctionCall::JsonParse(_type, expression) => { BuiltInFunctionCall::JsonParse(_type, expression) => {
let action = expression.clone().run(context, _manage_memory)?; let action = expression.clone().evaluate(context, _manage_memory)?;
let value = if let Action::Return(value) = action { let value = if let Evaluation::Return(value) = action {
value value
} else { } else {
return Err(RuntimeError::ValidationFailure( return Err(RuntimeError::ValidationFailure(
@ -66,7 +69,7 @@ impl AbstractNode for BuiltInFunctionCall {
if let ValueInner::String(string) = value.inner().as_ref() { if let ValueInner::String(string) = value.inner().as_ref() {
let deserialized = serde_json::from_str(string)?; let deserialized = serde_json::from_str(string)?;
Ok(Action::Return(deserialized)) Ok(Evaluation::Return(deserialized))
} else { } else {
Err(RuntimeError::ValidationFailure( Err(RuntimeError::ValidationFailure(
ValidationError::ExpectedString { ValidationError::ExpectedString {
@ -77,8 +80,8 @@ impl AbstractNode for BuiltInFunctionCall {
} }
} }
BuiltInFunctionCall::Length(expression) => { BuiltInFunctionCall::Length(expression) => {
let action = expression.clone().run(context, _manage_memory)?; let action = expression.clone().evaluate(context, _manage_memory)?;
let value = if let Action::Return(value) = action { let value = if let Evaluation::Return(value) = action {
value value
} else { } else {
return Err(RuntimeError::ValidationFailure( return Err(RuntimeError::ValidationFailure(
@ -91,11 +94,11 @@ impl AbstractNode for BuiltInFunctionCall {
0 0
}; };
Ok(Action::Return(Value::integer(length))) Ok(Evaluation::Return(Value::integer(length)))
} }
BuiltInFunctionCall::ReadFile(expression) => { BuiltInFunctionCall::ReadFile(expression) => {
let action = expression.clone().run(context, _manage_memory)?; let action = expression.clone().evaluate(context, _manage_memory)?;
let value = if let Action::Return(value) = action { let value = if let Evaluation::Return(value) = action {
value value
} else { } else {
return Err(RuntimeError::ValidationFailure( return Err(RuntimeError::ValidationFailure(
@ -108,20 +111,20 @@ impl AbstractNode for BuiltInFunctionCall {
String::with_capacity(0) String::with_capacity(0)
}; };
Ok(Action::Return(Value::string(file_contents))) Ok(Evaluation::Return(Value::string(file_contents)))
} }
BuiltInFunctionCall::ReadLine => { BuiltInFunctionCall::ReadLine => {
let mut buffer = String::new(); let mut buffer = String::new();
stdin().read_line(&mut buffer)?; stdin().read_line(&mut buffer)?;
Ok(Action::Return(Value::string( Ok(Evaluation::Return(Value::string(
buffer.strip_suffix('\n').unwrap_or(&buffer), buffer.strip_suffix('\n').unwrap_or(&buffer),
))) )))
} }
BuiltInFunctionCall::Sleep(expression) => { BuiltInFunctionCall::Sleep(expression) => {
let action = expression.clone().run(context, _manage_memory)?; let action = expression.clone().evaluate(context, _manage_memory)?;
let value = if let Action::Return(value) = action { let value = if let Evaluation::Return(value) = action {
value value
} else { } else {
return Err(RuntimeError::ValidationFailure( return Err(RuntimeError::ValidationFailure(
@ -133,11 +136,11 @@ impl AbstractNode for BuiltInFunctionCall {
thread::sleep(Duration::from_millis(*milliseconds as u64)); thread::sleep(Duration::from_millis(*milliseconds as u64));
} }
Ok(Action::None) Ok(Evaluation::None)
} }
BuiltInFunctionCall::WriteLine(expression) => { BuiltInFunctionCall::WriteLine(expression) => {
let action = expression.clone().run(context, _manage_memory)?; let action = expression.clone().evaluate(context, _manage_memory)?;
let value = if let Action::Return(value) = action { let value = if let Evaluation::Return(value) = action {
value value
} else { } else {
return Err(RuntimeError::ValidationFailure( return Err(RuntimeError::ValidationFailure(
@ -153,16 +156,16 @@ impl AbstractNode for BuiltInFunctionCall {
stdout.flush()?; stdout.flush()?;
} }
Ok(Action::None) Ok(Evaluation::None)
} }
} }
} }
} }
impl ExpectedType for BuiltInFunctionCall { impl ExpectedType for BuiltInFunctionCall {
fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> { fn expected_type(&self, context: &mut Context) -> Result<Type, ValidationError> {
match self { match self {
BuiltInFunctionCall::JsonParse(r#type, _) => Ok(r#type.node.clone()), BuiltInFunctionCall::JsonParse(r#type, _) => Ok(r#type.clone().construct(&context)?),
BuiltInFunctionCall::Length(_) => Ok(Type::Integer), BuiltInFunctionCall::Length(_) => Ok(Type::Integer),
BuiltInFunctionCall::ReadFile(_) => Ok(Type::String), BuiltInFunctionCall::ReadFile(_) => Ok(Type::String),
BuiltInFunctionCall::ReadLine => Ok(Type::String), BuiltInFunctionCall::ReadLine => Ok(Type::String),

View File

@ -6,25 +6,27 @@ use crate::{
value::ValueInner, value::ValueInner,
}; };
use super::{AbstractNode, Action, ExpectedType, Type, ValueExpression, WithPosition}; use super::{
AbstractNode, Evaluation, ExpectedType, Expression, Type, TypeConstructor, 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<ValueExpression>, function: Box<Expression>,
type_arguments: Vec<WithPosition<Type>>, type_arguments: Option<Vec<WithPosition<TypeConstructor>>>,
arguments: Vec<ValueExpression>, value_arguments: Vec<Expression>,
} }
impl FunctionCall { impl FunctionCall {
pub fn new( pub fn new(
function: ValueExpression, function: Expression,
type_arguments: Vec<WithPosition<Type>>, type_arguments: Option<Vec<WithPosition<TypeConstructor>>>,
arguments: Vec<ValueExpression>, value_arguments: Vec<Expression>,
) -> Self { ) -> Self {
FunctionCall { FunctionCall {
function: Box::new(function), function: Box::new(function),
type_arguments, type_arguments,
arguments, value_arguments,
} }
} }
} }
@ -33,48 +35,28 @@ impl AbstractNode for FunctionCall {
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)?;
for expression in &self.arguments { for expression in &self.value_arguments {
expression.validate(context, manage_memory)?; expression.validate(context, manage_memory)?;
} }
let function_node_type = self.function.expected_type(context)?; let function_node_type = self.function.expected_type(context)?;
if let Type::Function { if let Type::Function {
parameter_types, type_parameters,
value_parameters: _,
return_type: _, return_type: _,
} = function_node_type } = function_node_type
{ {
for (type_parameter, type_argument) in match (type_parameters, &self.type_arguments) {
parameter_types.iter().zip(self.type_arguments.iter()) (Some(type_parameters), Some(type_arguments)) => {
{ if type_parameters.len() != type_arguments.len() {
if let Type::Argument(_) = type_parameter.node { return Err(ValidationError::WrongTypeArgumentCount {
continue; actual: type_parameters.len(),
} expected: type_arguments.len(),
});
type_parameter
.node
.check(&type_argument.node)
.map_err(|conflict| ValidationError::TypeCheck {
conflict,
actual_position: type_argument.position,
expected_position: type_parameter.position,
})?;
}
for (type_parameter, expression) in parameter_types.iter().zip(self.arguments.iter()) {
if let Type::Argument(_) = type_parameter.node {
continue;
}
let actual = expression.expected_type(context)?;
type_parameter.node.check(&actual).map_err(|conflict| {
ValidationError::TypeCheck {
conflict,
actual_position: expression.position(),
expected_position: type_parameter.position,
} }
})?; }
_ => {}
} }
Ok(()) Ok(())
@ -86,10 +68,14 @@ impl AbstractNode for FunctionCall {
} }
} }
fn run(self, context: &mut Context, clear_variables: bool) -> Result<Action, RuntimeError> { fn evaluate(
self,
context: &mut Context,
clear_variables: bool,
) -> Result<Evaluation, RuntimeError> {
let function_position = self.function.position(); let function_position = self.function.position();
let action = self.function.run(context, clear_variables)?; let action = self.function.evaluate(context, clear_variables)?;
let value = if let Action::Return(value) = action { let value = if let Evaluation::Return(value) = action {
value value
} else { } else {
return Err(RuntimeError::ValidationFailure( return Err(RuntimeError::ValidationFailure(
@ -97,7 +83,7 @@ impl AbstractNode for FunctionCall {
)); ));
}; };
let function = if let ValueInner::Function(function) = value.inner().as_ref() { let function = if let ValueInner::Function(function) = value.inner().as_ref() {
function function.clone()
} else { } else {
return Err(RuntimeError::ValidationFailure( return Err(RuntimeError::ValidationFailure(
ValidationError::ExpectedFunction { ValidationError::ExpectedFunction {
@ -106,12 +92,12 @@ impl AbstractNode for FunctionCall {
}, },
)); ));
}; };
let mut arguments = Vec::with_capacity(self.arguments.len()); let mut arguments = Vec::with_capacity(self.value_arguments.len());
for expression in self.arguments { for expression in self.value_arguments {
let expression_position = expression.position(); let expression_position = expression.position();
let action = expression.run(context, clear_variables)?; let action = expression.evaluate(context, clear_variables)?;
let value = if let Action::Return(value) = action { let value = if let Evaluation::Return(value) = action {
value value
} else { } else {
return Err(RuntimeError::ValidationFailure( return Err(RuntimeError::ValidationFailure(
@ -124,15 +110,17 @@ impl AbstractNode for FunctionCall {
let mut function_context = Context::new(Some(&context)); let mut function_context = Context::new(Some(&context));
for (type_parameter, type_argument) in function match (function.type_parameters(), self.type_arguments) {
.type_parameters() (Some(type_parameters), Some(type_arguments)) => {
.iter() for (parameter, constructor) in
.map(|r#type| r#type.node.clone()) type_parameters.into_iter().zip(type_arguments.into_iter())
.zip(self.type_arguments.into_iter().map(|r#type| r#type.node)) {
{ let r#type = constructor.node.construct(context)?;
if let Type::Argument(identifier) = type_parameter {
function_context.set_type(identifier, type_argument)?; function_context.set_type(parameter.clone(), r#type)?;
}
} }
_ => {}
} }
function function
@ -146,7 +134,7 @@ impl ExpectedType for FunctionCall {
let function_node_type = self.function.expected_type(_context)?; let function_node_type = self.function.expected_type(_context)?;
if let Type::Function { return_type, .. } = function_node_type { if let Type::Function { return_type, .. } = function_node_type {
Ok(return_type.node) Ok(*return_type)
} else { } else {
Err(ValidationError::ExpectedFunction { Err(ValidationError::ExpectedFunction {
actual: function_node_type, actual: function_node_type,

View File

@ -6,21 +6,21 @@ use crate::{
value::ValueInner, value::ValueInner,
}; };
use super::{AbstractNode, Action, Block, ExpectedType, Type, ValueExpression, WithPosition}; use super::{AbstractNode, Block, Evaluation, ExpectedType, Expression, Type, 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: ValueExpression, if_expression: Expression,
if_block: WithPosition<Block>, if_block: WithPosition<Block>,
else_ifs: Vec<(ValueExpression, WithPosition<Block>)>, else_ifs: Vec<(Expression, WithPosition<Block>)>,
else_block: Option<WithPosition<Block>>, else_block: Option<WithPosition<Block>>,
} }
impl IfElse { impl IfElse {
pub fn new( pub fn new(
if_expression: ValueExpression, if_expression: Expression,
if_block: WithPosition<Block>, if_block: WithPosition<Block>,
else_ifs: Vec<(ValueExpression, WithPosition<Block>)>, else_ifs: Vec<(Expression, WithPosition<Block>)>,
else_block: Option<WithPosition<Block>>, else_block: Option<WithPosition<Block>>,
) -> Self { ) -> Self {
Self { Self {
@ -51,7 +51,7 @@ impl AbstractNode for IfElse {
.map_err(|conflict| ValidationError::TypeCheck { .map_err(|conflict| ValidationError::TypeCheck {
conflict, conflict,
actual_position: else_block.node.last_statement().position(), actual_position: else_block.node.last_statement().position(),
expected_position: self.if_block.node.first_statement().position(), expected_position: Some(self.if_block.node.first_statement().position()),
})?; })?;
} }
} else { } else {
@ -74,7 +74,7 @@ impl AbstractNode for IfElse {
.map_err(|conflict| ValidationError::TypeCheck { .map_err(|conflict| ValidationError::TypeCheck {
conflict, conflict,
actual_position: self.if_block.node.last_statement().position(), actual_position: self.if_block.node.last_statement().position(),
expected_position: self.if_expression.position(), expected_position: Some(self.if_expression.position()),
})?; })?;
} else { } else {
return Err(ValidationError::ExpectedBoolean { return Err(ValidationError::ExpectedBoolean {
@ -87,10 +87,14 @@ impl AbstractNode for IfElse {
Ok(()) Ok(())
} }
fn run(self, context: &mut Context, _manage_memory: bool) -> Result<Action, RuntimeError> { fn evaluate(
self,
context: &mut Context,
_manage_memory: bool,
) -> Result<Evaluation, RuntimeError> {
let if_position = self.if_expression.position(); let if_position = self.if_expression.position();
let action = self.if_expression.run(context, _manage_memory)?; let action = self.if_expression.evaluate(context, _manage_memory)?;
let value = if let Action::Return(value) = action { let value = if let Evaluation::Return(value) = action {
value value
} else { } else {
return Err(RuntimeError::ValidationFailure( return Err(RuntimeError::ValidationFailure(
@ -100,12 +104,12 @@ 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.node.run(context, _manage_memory) self.if_block.node.evaluate(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();
let action = expression.run(context, _manage_memory)?; let action = expression.evaluate(context, _manage_memory)?;
let value = if let Action::Return(value) = action { let value = if let Evaluation::Return(value) = action {
value value
} else { } else {
return Err(RuntimeError::ValidationFailure( return Err(RuntimeError::ValidationFailure(
@ -115,7 +119,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.node.run(context, _manage_memory); return block.node.evaluate(context, _manage_memory);
} }
} else { } else {
return Err(RuntimeError::ValidationFailure( return Err(RuntimeError::ValidationFailure(
@ -128,9 +132,9 @@ impl AbstractNode for IfElse {
} }
if let Some(else_statement) = self.else_block { if let Some(else_statement) = self.else_block {
else_statement.node.run(context, _manage_memory) else_statement.node.evaluate(context, _manage_memory)
} else { } else {
Ok(Action::None) Ok(Evaluation::None)
} }
} }
} else { } else {
@ -163,17 +167,17 @@ mod tests {
fn simple_if() { fn simple_if() {
assert_eq!( assert_eq!(
IfElse::new( IfElse::new(
ValueExpression::Value(ValueNode::Boolean(true).with_position((0, 0))), Expression::Value(ValueNode::Boolean(true).with_position((0, 0))),
Block::new(vec![Statement::ValueExpression(ValueExpression::Value( Block::new(vec![Statement::ValueExpression(Expression::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)),
Vec::with_capacity(0), Vec::with_capacity(0),
None None
) )
.run(&mut Context::new(None), true) .evaluate(&mut Context::new(None), true)
.unwrap(), .unwrap(),
Action::Return(Value::string("foo".to_string())) Evaluation::Return(Value::string("foo".to_string()))
) )
} }
} }

View File

@ -5,64 +5,72 @@ use crate::{
error::{RuntimeError, ValidationError}, error::{RuntimeError, ValidationError},
}; };
use super::{AbstractNode, Action, ExpectedType, Type, ValueExpression, ValueNode, WithPosition}; use super::{AbstractNode, Evaluation, ExpectedType, Expression, Type, 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: ValueExpression, collection: Expression,
right: ValueExpression, index: Expression,
} }
impl ListIndex { impl ListIndex {
pub fn new(left: ValueExpression, right: ValueExpression) -> Self { pub fn new(left: Expression, right: Expression) -> Self {
Self { left, right } Self {
collection: left,
index: right,
}
} }
} }
impl AbstractNode for ListIndex { impl AbstractNode for ListIndex {
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.collection.validate(context, _manage_memory)?;
self.right.validate(context, _manage_memory)?; self.index.validate(context, _manage_memory)?;
let left_type = self.left.expected_type(context)?; let collection_type = self.collection.expected_type(context)?;
let index_type = self.index.expected_type(context)?;
match left_type { match collection_type {
Type::List => todo!(), Type::List {
Type::ListOf(_) => todo!(), length: _,
Type::ListExact(_) => { item_type: _,
let right_type = self.right.expected_type(context)?; } => {
if index_type == Type::Integer {
if let Type::Integer = right_type {
Ok(()) Ok(())
} else { } else {
Err(ValidationError::CannotIndexWith { Err(ValidationError::CannotIndexWith {
collection_type: left_type, collection_type,
collection_position: self.left.position(), collection_position: self.collection.position(),
index_type: right_type, index_type,
index_position: self.right.position(), index_position: self.index.position(),
}) })
} }
} }
Type::ListOf(_) => todo!(),
_ => Err(ValidationError::CannotIndex { _ => Err(ValidationError::CannotIndex {
r#type: left_type, r#type: collection_type,
position: self.left.position(), position: self.collection.position(),
}), }),
} }
} }
fn run(self, context: &mut Context, _clear_variables: bool) -> Result<Action, RuntimeError> { fn evaluate(
let left_position = self.left.position(); self,
let left_action = self.left.run(context, _clear_variables)?; context: &mut Context,
let left_value = if let Action::Return(value) = left_action { _clear_variables: bool,
) -> Result<Evaluation, RuntimeError> {
let left_position = self.collection.position();
let left_action = self.collection.evaluate(context, _clear_variables)?;
let left_value = if let Evaluation::Return(value) = left_action {
value value
} else { } else {
return Err(RuntimeError::ValidationFailure( return Err(RuntimeError::ValidationFailure(
ValidationError::InterpreterExpectedReturn(left_position), ValidationError::InterpreterExpectedReturn(left_position),
)); ));
}; };
let right_position = self.right.position(); let right_position = self.index.position();
let right_action = self.right.run(context, _clear_variables)?; let right_action = self.index.evaluate(context, _clear_variables)?;
let right_value = if let Action::Return(value) = right_action { let right_value = if let Evaluation::Return(value) = right_action {
value value
} else { } else {
return Err(RuntimeError::ValidationFailure( return Err(RuntimeError::ValidationFailure(
@ -74,9 +82,9 @@ 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.node.clone())) Ok(Evaluation::Return(item.node.clone()))
} else { } else {
Ok(Action::None) Ok(Evaluation::None)
} }
} else { } else {
Err(RuntimeError::ValidationFailure( Err(RuntimeError::ValidationFailure(
@ -93,18 +101,18 @@ impl AbstractNode for ListIndex {
impl ExpectedType for ListIndex { impl ExpectedType for ListIndex {
fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> { fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> {
let left_type = self.left.expected_type(_context)?; let left_type = self.collection.expected_type(_context)?;
if let ( if let (
ValueExpression::Value(WithPosition { Expression::Value(WithPosition {
node: ValueNode::List(expression_list), node: ValueNode::List(expression_list),
.. ..
}), }),
ValueExpression::Value(WithPosition { Expression::Value(WithPosition {
node: ValueNode::Integer(index), node: ValueNode::Integer(index),
.. ..
}), }),
) = (&self.left, &self.right) ) = (&self.collection, &self.index)
{ {
let expression = if let Some(expression) = expression_list.get(*index as usize) { let expression = if let Some(expression) = expression_list.get(*index as usize) {
expression expression
@ -116,7 +124,7 @@ impl ExpectedType for ListIndex {
} else { } else {
Err(ValidationError::CannotIndex { Err(ValidationError::CannotIndex {
r#type: left_type, r#type: left_type,
position: self.left.position(), position: self.collection.position(),
}) })
} }
} }

View File

@ -7,19 +7,19 @@ use crate::{
Value, Value,
}; };
use super::{AbstractNode, Action, ExpectedType, Type, ValueExpression}; use super::{AbstractNode, Evaluation, ExpectedType, Expression, Type};
#[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(ValueExpression, ValueExpression), Equal(Expression, Expression),
NotEqual(ValueExpression, ValueExpression), NotEqual(Expression, Expression),
Greater(ValueExpression, ValueExpression), Greater(Expression, Expression),
Less(ValueExpression, ValueExpression), Less(Expression, Expression),
GreaterOrEqual(ValueExpression, ValueExpression), GreaterOrEqual(Expression, Expression),
LessOrEqual(ValueExpression, ValueExpression), LessOrEqual(Expression, Expression),
And(ValueExpression, ValueExpression), And(Expression, Expression),
Or(ValueExpression, ValueExpression), Or(Expression, Expression),
Not(ValueExpression), Not(Expression),
} }
impl AbstractNode for Logic { impl AbstractNode for Logic {
@ -42,7 +42,7 @@ impl AbstractNode for Logic {
.map_err(|conflict| ValidationError::TypeCheck { .map_err(|conflict| ValidationError::TypeCheck {
conflict, conflict,
actual_position: left.position(), actual_position: left.position(),
expected_position: right.position(), expected_position: Some(right.position()),
})?; })?;
Ok(()) Ok(())
@ -89,11 +89,15 @@ impl AbstractNode for Logic {
} }
} }
fn run(self, context: &mut Context, _manage_memory: bool) -> Result<Action, RuntimeError> { fn evaluate(
let run_and_expect_value = |expression: ValueExpression| -> Result<Value, RuntimeError> { self,
context: &mut Context,
_manage_memory: bool,
) -> Result<Evaluation, RuntimeError> {
let run_and_expect_value = |expression: Expression| -> 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.evaluate(&mut context.clone(), _manage_memory)?;
let value = if let Action::Return(value) = action { let value = if let Evaluation::Return(value) = action {
value value
} else { } else {
return Err(RuntimeError::ValidationFailure( return Err(RuntimeError::ValidationFailure(
@ -104,10 +108,10 @@ impl AbstractNode for Logic {
Ok(value) Ok(value)
}; };
let run_and_expect_boolean = |expression: ValueExpression| -> Result<bool, RuntimeError> { let run_and_expect_boolean = |expression: Expression| -> 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.evaluate(&mut context.clone(), _manage_memory)?;
let value = if let Action::Return(value) = action { let value = if let Evaluation::Return(value) = action {
value value
} else { } else {
return Err(RuntimeError::ValidationFailure( return Err(RuntimeError::ValidationFailure(
@ -187,7 +191,7 @@ impl AbstractNode for Logic {
} }
}; };
Ok(Action::Return(Value::boolean(boolean))) Ok(Evaluation::Return(Value::boolean(boolean)))
} }
} }
@ -207,11 +211,11 @@ mod tests {
fn equal() { fn equal() {
assert_eq!( assert_eq!(
Logic::Equal( Logic::Equal(
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))) Expression::Value(ValueNode::Integer(42).with_position((0, 0)))
) )
.run(&mut Context::new(None), true), .evaluate(&mut Context::new(None), true),
Ok(Action::Return(Value::boolean(true))) Ok(Evaluation::Return(Value::boolean(true)))
) )
} }
@ -219,11 +223,11 @@ mod tests {
fn not_equal() { fn not_equal() {
assert_eq!( assert_eq!(
Logic::NotEqual( Logic::NotEqual(
ValueExpression::Value(ValueNode::Integer(42).with_position((0, 0))), Expression::Value(ValueNode::Integer(42).with_position((0, 0))),
ValueExpression::Value(ValueNode::Integer(43).with_position((0, 0))) Expression::Value(ValueNode::Integer(43).with_position((0, 0)))
) )
.run(&mut Context::new(None), true), .evaluate(&mut Context::new(None), true),
Ok(Action::Return(Value::boolean(true))) Ok(Evaluation::Return(Value::boolean(true)))
) )
} }
@ -231,11 +235,11 @@ mod tests {
fn greater() { fn greater() {
assert_eq!( assert_eq!(
Logic::Greater( Logic::Greater(
ValueExpression::Value(ValueNode::Integer(43).with_position((0, 0))), Expression::Value(ValueNode::Integer(43).with_position((0, 0))),
ValueExpression::Value(ValueNode::Integer(42).with_position((0, 0))) Expression::Value(ValueNode::Integer(42).with_position((0, 0)))
) )
.run(&mut Context::new(None), true), .evaluate(&mut Context::new(None), true),
Ok(Action::Return(Value::boolean(true))) Ok(Evaluation::Return(Value::boolean(true)))
) )
} }
@ -243,11 +247,11 @@ mod tests {
fn less() { fn less() {
assert_eq!( assert_eq!(
Logic::Less( Logic::Less(
ValueExpression::Value(ValueNode::Integer(42).with_position((0, 0))), Expression::Value(ValueNode::Integer(42).with_position((0, 0))),
ValueExpression::Value(ValueNode::Integer(43).with_position((0, 0))) Expression::Value(ValueNode::Integer(43).with_position((0, 0)))
) )
.run(&mut Context::new(None), true), .evaluate(&mut Context::new(None), true),
Ok(Action::Return(Value::boolean(true))) Ok(Evaluation::Return(Value::boolean(true)))
) )
} }
@ -255,20 +259,20 @@ mod tests {
fn greater_or_equal() { fn greater_or_equal() {
assert_eq!( assert_eq!(
Logic::GreaterOrEqual( Logic::GreaterOrEqual(
ValueExpression::Value(ValueNode::Integer(42).with_position((0, 0))), Expression::Value(ValueNode::Integer(42).with_position((0, 0))),
ValueExpression::Value(ValueNode::Integer(41).with_position((0, 0))) Expression::Value(ValueNode::Integer(41).with_position((0, 0)))
) )
.run(&mut Context::new(None), true), .evaluate(&mut Context::new(None), true),
Ok(Action::Return(Value::boolean(true))) Ok(Evaluation::Return(Value::boolean(true)))
); );
assert_eq!( assert_eq!(
Logic::GreaterOrEqual( Logic::GreaterOrEqual(
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))), Expression::Value(ValueNode::Integer(42).with_position((0, 0))),
) )
.run(&mut Context::new(None), true), .evaluate(&mut Context::new(None), true),
Ok(Action::Return(Value::boolean(true))) Ok(Evaluation::Return(Value::boolean(true)))
); );
} }
@ -276,20 +280,20 @@ mod tests {
fn less_or_equal() { fn less_or_equal() {
assert_eq!( assert_eq!(
Logic::LessOrEqual( Logic::LessOrEqual(
ValueExpression::Value(ValueNode::Integer(41).with_position((0, 0))), Expression::Value(ValueNode::Integer(41).with_position((0, 0))),
ValueExpression::Value(ValueNode::Integer(42).with_position((0, 0))), Expression::Value(ValueNode::Integer(42).with_position((0, 0))),
) )
.run(&mut Context::new(None), true), .evaluate(&mut Context::new(None), true),
Ok(Action::Return(Value::boolean(true))) Ok(Evaluation::Return(Value::boolean(true)))
); );
assert_eq!( assert_eq!(
Logic::LessOrEqual( Logic::LessOrEqual(
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))), Expression::Value(ValueNode::Integer(42).with_position((0, 0))),
) )
.run(&mut Context::new(None), true), .evaluate(&mut Context::new(None), true),
Ok(Action::Return(Value::boolean(true))) Ok(Evaluation::Return(Value::boolean(true)))
); );
} }
@ -297,11 +301,11 @@ mod tests {
fn and() { fn and() {
assert_eq!( assert_eq!(
Logic::And( Logic::And(
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))), Expression::Value(ValueNode::Boolean(true).with_position((0, 0))),
) )
.run(&mut Context::new(None), true), .evaluate(&mut Context::new(None), true),
Ok(Action::Return(Value::boolean(true))) Ok(Evaluation::Return(Value::boolean(true)))
) )
} }
@ -309,22 +313,22 @@ mod tests {
fn or() { fn or() {
assert_eq!( assert_eq!(
Logic::Or( Logic::Or(
ValueExpression::Value(ValueNode::Boolean(true).with_position((0, 0))), Expression::Value(ValueNode::Boolean(true).with_position((0, 0))),
ValueExpression::Value(ValueNode::Boolean(false).with_position((0, 0))), Expression::Value(ValueNode::Boolean(false).with_position((0, 0))),
) )
.run(&mut Context::new(None), true), .evaluate(&mut Context::new(None), true),
Ok(Action::Return(Value::boolean(true))) Ok(Evaluation::Return(Value::boolean(true)))
) )
} }
#[test] #[test]
fn not() { fn not() {
assert_eq!( assert_eq!(
Logic::Not(ValueExpression::Value( Logic::Not(Expression::Value(
ValueNode::Boolean(false).with_position((0, 0)) ValueNode::Boolean(false).with_position((0, 0))
)) ))
.run(&mut Context::new(None), true), .evaluate(&mut Context::new(None), true),
Ok(Action::Return(Value::boolean(true))) Ok(Evaluation::Return(Value::boolean(true)))
) )
} }
} }

View File

@ -5,7 +5,7 @@ use crate::{
error::{RuntimeError, ValidationError}, error::{RuntimeError, ValidationError},
}; };
use super::{AbstractNode, Action, Statement}; use super::{AbstractNode, Evaluation, 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 {
@ -31,15 +31,19 @@ impl AbstractNode for Loop {
Ok(()) Ok(())
} }
fn run(self, _context: &mut Context, _manage_memory: bool) -> Result<Action, RuntimeError> { fn evaluate(
self,
_context: &mut Context,
_manage_memory: bool,
) -> Result<Evaluation, RuntimeError> {
loop { loop {
for statement in &self.statements { for statement in &self.statements {
let action = statement.clone().run(_context, false)?; let action = statement.clone().evaluate(_context, false)?;
match action { match action {
Action::Return(_) => {} Evaluation::Return(_) => {}
Action::None => {} Evaluation::None => {}
Action::Break => return Ok(Action::Break), Evaluation::Break => return Ok(Evaluation::Break),
} }
} }
} }

View File

@ -6,16 +6,16 @@ use crate::{
value::ValueInner, value::ValueInner,
}; };
use super::{AbstractNode, Action, ExpectedType, Type, ValueExpression, ValueNode, WithPosition}; use super::{AbstractNode, Evaluation, ExpectedType, Expression, Type, 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: ValueExpression, collection: Expression,
index: ValueExpression, index: Expression,
} }
impl MapIndex { impl MapIndex {
pub fn new(left: ValueExpression, right: ValueExpression) -> Self { pub fn new(left: Expression, right: Expression) -> Self {
Self { Self {
collection: left, collection: left,
index: right, index: right,
@ -32,10 +32,14 @@ impl AbstractNode for MapIndex {
self.collection.validate(_context, _manage_memory) self.collection.validate(_context, _manage_memory)
} }
fn run(self, context: &mut Context, _manage_memory: bool) -> Result<Action, RuntimeError> { fn evaluate(
self,
context: &mut Context,
_manage_memory: bool,
) -> Result<Evaluation, RuntimeError> {
let collection_position = self.collection.position(); let collection_position = self.collection.position();
let action = self.collection.run(context, _manage_memory)?; let action = self.collection.evaluate(context, _manage_memory)?;
let collection = if let Action::Return(value) = action { let collection = if let Evaluation::Return(value) = action {
value value
} else { } else {
return Err(RuntimeError::ValidationFailure( return Err(RuntimeError::ValidationFailure(
@ -43,13 +47,13 @@ impl AbstractNode for MapIndex {
)); ));
}; };
if let (ValueInner::Map(map), ValueExpression::Identifier(index)) = if let (ValueInner::Map(map), Expression::Identifier(index)) =
(collection.inner().as_ref(), self.index) (collection.inner().as_ref(), self.index)
{ {
let action = map let action = map
.get(&index.node) .get(&index.node)
.map(|value| Action::Return(value.clone())) .map(|value| Evaluation::Return(value.clone()))
.unwrap_or(Action::None); .unwrap_or(Evaluation::None);
Ok(action) Ok(action)
} else { } else {
@ -65,7 +69,7 @@ impl AbstractNode for MapIndex {
impl ExpectedType for MapIndex { impl ExpectedType for MapIndex {
fn expected_type(&self, context: &mut Context) -> Result<Type, ValidationError> { fn expected_type(&self, context: &mut Context) -> Result<Type, ValidationError> {
if let (ValueExpression::Identifier(collection), ValueExpression::Identifier(index)) = if let (Expression::Identifier(collection), Expression::Identifier(index)) =
(&self.collection, &self.index) (&self.collection, &self.index)
{ {
let collection = if let Some(collection) = context.get_value(&collection.node)? { let collection = if let Some(collection) = context.get_value(&collection.node)? {
@ -90,17 +94,19 @@ impl ExpectedType for MapIndex {
} }
if let ( if let (
ValueExpression::Value(WithPosition { Expression::Value(WithPosition {
node: ValueNode::Map(properties), node: ValueNode::Map(properties),
.. ..
}), }),
ValueExpression::Identifier(index), Expression::Identifier(index),
) = (&self.collection, &self.index) ) = (&self.collection, &self.index)
{ {
for (property, type_option, expression) in properties { for (property, constructor_option, expression) in properties {
if property == &index.node { if property == &index.node {
return if let Some(r#type) = type_option { return if let Some(constructor) = constructor_option {
Ok(r#type.node.clone()) let r#type = constructor.node.clone().construct(&context)?;
Ok(r#type)
} else { } else {
Ok(expression.expected_type(context)?) Ok(expression.expected_type(context)?)
}; };
@ -111,15 +117,15 @@ impl ExpectedType for MapIndex {
} }
if let ( if let (
ValueExpression::Value(WithPosition { Expression::Value(WithPosition {
node: ValueNode::Structure { fields, .. }, node: ValueNode::Structure { fields, .. },
.. ..
}), }),
ValueExpression::Identifier(index), Expression::Identifier(index),
) = (&self.collection, &self.index) ) = (&self.collection, &self.index)
{ {
return if let Some(type_result) = fields.iter().find_map(|(property, expression)| { return if let Some(type_result) = fields.iter().find_map(|(property, expression)| {
if property == &index.node { if property.node == index.node {
Some(expression.expected_type(context)) Some(expression.expected_type(context))
} else { } else {
None None

View File

@ -7,15 +7,15 @@ use crate::{
Value, Value,
}; };
use super::{AbstractNode, Action, ExpectedType, SourcePosition, Type, ValueExpression}; use super::{AbstractNode, Evaluation, ExpectedType, Expression, SourcePosition, Type};
#[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(ValueExpression, ValueExpression), Add(Expression, Expression),
Subtract(ValueExpression, ValueExpression), Subtract(Expression, Expression),
Multiply(ValueExpression, ValueExpression), Multiply(Expression, Expression),
Divide(ValueExpression, ValueExpression), Divide(Expression, Expression),
Modulo(ValueExpression, ValueExpression), Modulo(Expression, Expression),
} }
impl AbstractNode for Math { impl AbstractNode for Math {
@ -67,21 +67,24 @@ impl AbstractNode for Math {
} }
} }
fn run(self, _context: &mut Context, _clear_variables: bool) -> Result<Action, RuntimeError> { fn evaluate(
let run_and_expect_value = |position: SourcePosition, self,
expression: ValueExpression| _context: &mut Context,
-> Result<Value, RuntimeError> { _clear_variables: bool,
let action = expression.run(&mut _context.clone(), _clear_variables)?; ) -> Result<Evaluation, RuntimeError> {
let value = if let Action::Return(value) = action { let run_and_expect_value =
value |position: SourcePosition, expression: Expression| -> Result<Value, RuntimeError> {
} else { let action = expression.evaluate(&mut _context.clone(), _clear_variables)?;
return Err(RuntimeError::ValidationFailure( let value = if let Evaluation::Return(value) = action {
ValidationError::InterpreterExpectedReturn(position), value
)); } else {
}; 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) => {
@ -288,7 +291,7 @@ impl AbstractNode for Math {
} }
}; };
Ok(Action::Return(value)) Ok(Evaluation::Return(value))
} }
} }

View File

@ -14,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 type_constructor;
pub mod value_expression; pub mod value_expression;
pub mod value_node; pub mod value_node;
pub mod r#while; pub mod r#while;
@ -41,7 +42,8 @@ pub use self::{
statement::Statement, statement::Statement,
structure_definition::StructureDefinition, structure_definition::StructureDefinition,
type_alias::TypeAssignment, type_alias::TypeAssignment,
value_expression::ValueExpression, type_constructor::TypeConstructor,
value_expression::Expression,
value_node::ValueNode, value_node::ValueNode,
}; };
@ -84,7 +86,7 @@ impl From<(usize, usize)> for SourcePosition {
} }
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord)] #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord)]
pub enum Action { pub enum Evaluation {
Return(Value), Return(Value),
Break, Break,
None, None,
@ -114,12 +116,12 @@ impl AbstractTree {
for statement in valid_statements { for statement in valid_statements {
let position = statement.position(); let position = statement.position();
let run = statement.run(context, manage_memory); let run = statement.evaluate(context, manage_memory);
match run { match run {
Ok(action) => match action { Ok(action) => match action {
Action::Return(value) => previous_value = Some(value), Evaluation::Return(value) => previous_value = Some(value),
Action::None => previous_value = None, Evaluation::None => previous_value = None,
_ => {} _ => {}
}, },
Err(runtime_error) => { Err(runtime_error) => {
@ -153,7 +155,7 @@ impl AbstractTree {
} else if errors.is_empty() { } else if errors.is_empty() {
if let Statement::StructureDefinition(_) = statement { if let Statement::StructureDefinition(_) = statement {
let position = statement.position(); let position = statement.position();
let run = statement.run(context, true); let run = statement.evaluate(context, true);
if let Err(runtime_error) = run { if let Err(runtime_error) = run {
errors.push(Error::Runtime { errors.push(Error::Runtime {
@ -189,7 +191,11 @@ impl Index<usize> for AbstractTree {
pub trait AbstractNode: Sized { pub trait AbstractNode: Sized {
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 evaluate(
self,
context: &mut Context,
manage_memory: bool,
) -> Result<Evaluation, RuntimeError>;
} }
pub trait ExpectedType { pub trait ExpectedType {

View File

@ -6,9 +6,8 @@ use crate::{
}; };
use super::{ use super::{
AbstractNode, Action, Assignment, AsyncBlock, Block, ExpectedType, IfElse, Loop, AbstractNode, Assignment, AsyncBlock, Block, Evaluation, ExpectedType, Expression, IfElse,
SourcePosition, StructureDefinition, Type, TypeAssignment, ValueExpression, While, Loop, SourcePosition, StructureDefinition, Type, TypeAssignment, While, WithPosition,
WithPosition,
}; };
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
@ -21,7 +20,7 @@ pub enum Statement {
Loop(WithPosition<Loop>), Loop(WithPosition<Loop>),
StructureDefinition(WithPosition<StructureDefinition>), StructureDefinition(WithPosition<StructureDefinition>),
TypeAssignment(WithPosition<TypeAssignment>), TypeAssignment(WithPosition<TypeAssignment>),
ValueExpression(ValueExpression), ValueExpression(Expression),
While(WithPosition<While>), While(WithPosition<While>),
} }
@ -68,20 +67,26 @@ impl AbstractNode for Statement {
} }
} }
fn run(self, context: &mut Context, manage_memory: bool) -> Result<Action, RuntimeError> { fn evaluate(
self,
context: &mut Context,
manage_memory: bool,
) -> Result<Evaluation, RuntimeError> {
let result = match self { let result = match self {
Statement::Assignment(assignment) => assignment.node.run(context, manage_memory), Statement::Assignment(assignment) => assignment.node.evaluate(context, manage_memory),
Statement::AsyncBlock(async_block) => async_block.node.run(context, manage_memory), Statement::AsyncBlock(async_block) => async_block.node.evaluate(context, manage_memory),
Statement::Block(block) => block.node.run(context, manage_memory), Statement::Block(block) => block.node.evaluate(context, manage_memory),
Statement::Break(_) => Ok(Action::Break), Statement::Break(_) => Ok(Evaluation::Break),
Statement::ValueExpression(expression) => expression.run(context, manage_memory), Statement::ValueExpression(expression) => expression.evaluate(context, manage_memory),
Statement::IfElse(if_else) => if_else.node.run(context, manage_memory), Statement::IfElse(if_else) => if_else.node.evaluate(context, manage_memory),
Statement::Loop(r#loop) => r#loop.node.run(context, manage_memory), Statement::Loop(r#loop) => r#loop.node.evaluate(context, manage_memory),
Statement::StructureDefinition(structure_definition) => { Statement::StructureDefinition(structure_definition) => {
structure_definition.node.run(context, manage_memory) structure_definition.node.evaluate(context, manage_memory)
} }
Statement::TypeAssignment(type_alias) => type_alias.node.run(context, manage_memory), Statement::TypeAssignment(type_alias) => {
Statement::While(r#while) => r#while.node.run(context, manage_memory), type_alias.node.evaluate(context, manage_memory)
}
Statement::While(r#while) => r#while.node.evaluate(context, manage_memory),
}; };
if manage_memory { if manage_memory {

View File

@ -6,16 +6,16 @@ use crate::{
identifier::Identifier, identifier::Identifier,
}; };
use super::{AbstractNode, Action, Type, WithPosition}; use super::{AbstractNode, Evaluation, Type, TypeConstructor, WithPosition};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct StructureDefinition { pub struct StructureDefinition {
name: Identifier, name: Identifier,
fields: Vec<(Identifier, WithPosition<Type>)>, fields: Vec<(Identifier, WithPosition<TypeConstructor>)>,
} }
impl StructureDefinition { impl StructureDefinition {
pub fn new(name: Identifier, fields: Vec<(Identifier, WithPosition<Type>)>) -> Self { pub fn new(name: Identifier, fields: Vec<(Identifier, WithPosition<TypeConstructor>)>) -> Self {
Self { name, fields } Self { name, fields }
} }
} }
@ -29,14 +29,26 @@ impl AbstractNode for StructureDefinition {
Ok(()) Ok(())
} }
fn run(self, context: &mut Context, _manage_memory: bool) -> Result<Action, RuntimeError> { fn evaluate(
self,
context: &mut Context,
_manage_memory: bool,
) -> Result<Evaluation, RuntimeError> {
let mut fields = Vec::with_capacity(self.fields.len());
for (identifier, constructor) in self.fields {
let r#type = constructor.node.construct(&context)?;
fields.push((identifier, r#type));
}
let struct_type = Type::Structure { let struct_type = Type::Structure {
name: self.name.clone(), name: self.name.clone(),
fields: self.fields, fields,
}; };
context.set_type(self.name, struct_type)?; context.set_type(self.name, struct_type)?;
Ok(Action::None) Ok(Evaluation::None)
} }
} }

View File

@ -9,29 +9,31 @@ use crate::{
identifier::Identifier, identifier::Identifier,
}; };
use super::{AbstractNode, Action, WithPosition}; use super::{AbstractNode, Evaluation};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum Type { pub enum Type {
Any, Any,
Argument(Identifier),
Boolean, Boolean,
Float, Float,
Function { Function {
parameter_types: Vec<WithPosition<Type>>, type_parameters: Option<Vec<Identifier>>,
return_type: Box<WithPosition<Type>>, value_parameters: Vec<(Identifier, Type)>,
return_type: Box<Type>,
}, },
Integer, Integer,
List, List {
ListOf(Box<WithPosition<Type>>), length: usize,
ListExact(Vec<WithPosition<Type>>), item_type: Box<Type>,
},
ListOf(Box<Type>),
Map, Map,
None, None,
Range, Range,
String, String,
Structure { Structure {
name: Identifier, name: Identifier,
fields: Vec<(Identifier, WithPosition<Type>)>, fields: Vec<(Identifier, Type)>,
}, },
} }
@ -43,46 +45,15 @@ impl Type {
| (Type::Boolean, Type::Boolean) | (Type::Boolean, Type::Boolean)
| (Type::Float, Type::Float) | (Type::Float, Type::Float)
| (Type::Integer, Type::Integer) | (Type::Integer, Type::Integer)
| (Type::List, Type::List)
| (Type::List, Type::ListOf(_))
| (Type::List, Type::ListExact(_))
| (Type::ListOf(_), Type::List)
| (Type::ListExact(_), Type::List)
| (Type::Map, Type::Map) | (Type::Map, Type::Map)
| (Type::None, Type::None) | (Type::None, Type::None)
| (Type::Range, Type::Range) | (Type::Range, Type::Range)
| (Type::String, Type::String) => return Ok(()), | (Type::String, Type::String) => return Ok(()),
(Type::Argument(left), Type::Argument(right)) => {
if left == right {
return Ok(());
}
}
(Type::ListOf(left), Type::ListOf(right)) => { (Type::ListOf(left), Type::ListOf(right)) => {
if let Ok(()) = left.node.check(&right.node) { if let Ok(()) = left.check(&right) {
return Ok(()); return Ok(());
} }
} }
(Type::ListOf(list_of), Type::ListExact(list_exact)) => {
for r#type in list_exact {
list_of.node.check(&r#type.node)?;
}
return Ok(());
}
(Type::ListExact(list_exact), Type::ListOf(list_of)) => {
for r#type in list_exact {
r#type.node.check(&list_of.node)?;
}
return Ok(());
}
(Type::ListExact(left), Type::ListExact(right)) => {
for (left, right) in left.iter().zip(right.iter()) {
left.node.check(&right.node)?;
}
return Ok(());
}
( (
Type::Structure { Type::Structure {
name: left_name, name: left_name,
@ -97,8 +68,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.node != right_type.node if left_field_name != right_field_name || left_type != right_type {
{
return Err(TypeConflict { return Err(TypeConflict {
actual: other.clone(), actual: other.clone(),
expected: self.clone(), expected: self.clone(),
@ -111,19 +81,33 @@ impl Type {
} }
( (
Type::Function { Type::Function {
parameter_types: left_parameters, type_parameters: left_type_parameters,
value_parameters: left_value_parameters,
return_type: left_return, return_type: left_return,
}, },
Type::Function { Type::Function {
parameter_types: right_parameters, type_parameters: right_type_parameters,
value_parameters: right_value_parameters,
return_type: right_return, return_type: right_return,
}, },
) => { ) => {
if left_return.node == right_return.node { if left_return == right_return {
for (left_parameter, right_parameter) in for (left_parameter, right_parameter) in left_type_parameters
left_parameters.iter().zip(right_parameters.iter()) .iter()
.zip(right_type_parameters.iter())
{ {
if left_parameter.node != right_parameter.node { if left_parameter != right_parameter {
return Err(TypeConflict {
actual: other.clone(),
expected: self.clone(),
});
}
}
for (left_parameter, right_parameter) in left_value_parameters
.iter()
.zip(right_value_parameters.iter())
{
if left_parameter != right_parameter {
return Err(TypeConflict { return Err(TypeConflict {
actual: other.clone(), actual: other.clone(),
expected: self.clone(), expected: self.clone(),
@ -153,8 +137,12 @@ impl AbstractNode for Type {
Ok(()) Ok(())
} }
fn run(self, _context: &mut Context, _manage_memory: bool) -> Result<Action, RuntimeError> { fn evaluate(
Ok(Action::None) self,
_context: &mut Context,
_manage_memory: bool,
) -> Result<Evaluation, RuntimeError> {
Ok(Evaluation::None)
} }
} }
@ -165,47 +153,40 @@ impl Display for Type {
Type::Boolean => write!(f, "bool"), Type::Boolean => write!(f, "bool"),
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 { length, item_type } => write!(f, "[{length}; {}]", item_type),
Type::ListOf(item_type) => write!(f, "list({})", item_type.node), Type::ListOf(item_type) => write!(f, "list({})", item_type),
Type::ListExact(item_types) => {
write!(f, "[")?;
for (index, item_type) in item_types.into_iter().enumerate() {
if index == item_types.len() - 1 {
write!(f, "{}", item_type.node)?;
} else {
write!(f, "{}, ", item_type.node)?;
}
}
write!(f, "]")
}
Type::Map => write!(f, "map"), Type::Map => write!(f, "map"),
Type::None => write!(f, "none"), Type::None => write!(f, "none"),
Type::Range => write!(f, "range"), Type::Range => write!(f, "range"),
Type::String => write!(f, "str"), Type::String => write!(f, "str"),
Type::Function { Type::Function {
parameter_types, type_parameters,
value_parameters,
return_type, return_type,
} => { } => {
write!(f, "(")?; write!(f, "(")?;
for r#type in parameter_types { if let Some(type_parameters) = type_parameters {
write!(f, "{} ", r#type.node)?; for identifier in type_parameters {
write!(f, "{} ", identifier)?;
}
write!(f, ")(")?;
} }
write!(f, ") : {}", return_type.node) for (identifier, r#type) in value_parameters {
write!(f, "{identifier}: {type}")?;
}
write!(f, ") : {}", return_type)
} }
Type::Structure { name, .. } => write!(f, "{name}"), Type::Structure { name, .. } => write!(f, "{name}"),
Type::Argument(identifier) => write!(f, "{identifier}"),
} }
} }
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::abstract_tree::WithPos;
use super::*; use super::*;
#[test] #[test]
@ -214,18 +195,22 @@ mod tests {
assert_eq!(Type::Boolean.check(&Type::Boolean), Ok(())); assert_eq!(Type::Boolean.check(&Type::Boolean), Ok(()));
assert_eq!(Type::Float.check(&Type::Float), Ok(())); assert_eq!(Type::Float.check(&Type::Float), Ok(()));
assert_eq!(Type::Integer.check(&Type::Integer), Ok(())); assert_eq!(Type::Integer.check(&Type::Integer), Ok(()));
assert_eq!(Type::List.check(&Type::List), Ok(()));
assert_eq!( assert_eq!(
Type::ListOf(Box::new(Type::Integer.with_position((0, 0)))) Type::List {
.check(&Type::ListOf(Box::new(Type::Integer.with_position((0, 0))))), length: 4,
item_type: Box::new(Type::Boolean),
}
.check(&Type::List {
length: 4,
item_type: Box::new(Type::Boolean),
}),
Ok(())
);
assert_eq!(
Type::ListOf(Box::new(Type::Integer)).check(&Type::ListOf(Box::new(Type::Integer))),
Ok(()) Ok(())
); );
assert_eq!(
Type::ListExact(vec![Type::Float.with_position((0, 0))])
.check(&Type::ListExact(vec![Type::Float.with_position((0, 0))])),
Ok(())
);
assert_eq!(Type::Map.check(&Type::Map), Ok(())); assert_eq!(Type::Map.check(&Type::Map), Ok(()));
assert_eq!(Type::None.check(&Type::None), Ok(())); assert_eq!(Type::None.check(&Type::None), Ok(()));
assert_eq!(Type::Range.check(&Type::Range), Ok(())); assert_eq!(Type::Range.check(&Type::Range), Ok(()));
@ -257,9 +242,11 @@ mod tests {
Type::Boolean, Type::Boolean,
Type::Float, Type::Float,
Type::Integer, Type::Integer,
Type::List, Type::List {
Type::ListOf(Box::new(Type::Boolean.with_position((0, 0)))), length: 10,
Type::ListExact(vec![Type::Integer.with_position((0, 0))]), item_type: Box::new(Type::Integer),
},
Type::ListOf(Box::new(Type::Boolean)),
Type::Map, Type::Map,
Type::None, Type::None,
Type::Range, Type::Range,
@ -283,18 +270,13 @@ mod tests {
#[test] #[test]
fn check_list_types() { fn check_list_types() {
let list = Type::List; let list = Type::List {
let list_exact = Type::ListExact(vec![ length: 42,
Type::Integer.with_position((0, 0)), item_type: Box::new(Type::Integer),
Type::Integer.with_position((0, 0)), };
]); let list_of = Type::ListOf(Box::new(Type::Integer));
let list_of = Type::ListOf(Box::new(Type::Integer.with_position((0, 0))));
assert_eq!(list.check(&list_exact), Ok(()));
assert_eq!(list.check(&list_of), Ok(())); assert_eq!(list.check(&list_of), Ok(()));
assert_eq!(list_exact.check(&list), Ok(()));
assert_eq!(list_exact.check(&list_of), Ok(()));
assert_eq!(list_of.check(&list), Ok(())); assert_eq!(list_of.check(&list), Ok(()));
assert_eq!(list_of.check(&list_exact), Ok(()));
} }
} }

View File

@ -6,17 +6,23 @@ use crate::{
identifier::Identifier, identifier::Identifier,
}; };
use super::{AbstractNode, Action, Type, WithPosition}; use super::{AbstractNode, Evaluation, TypeConstructor, WithPosition};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct TypeAssignment { pub struct TypeAssignment {
identifier: WithPosition<Identifier>, identifier: WithPosition<Identifier>,
r#type: WithPosition<Type>, constructor: WithPosition<TypeConstructor>,
} }
impl TypeAssignment { impl TypeAssignment {
pub fn new(identifier: WithPosition<Identifier>, r#type: WithPosition<Type>) -> Self { pub fn new(
Self { identifier, r#type } identifier: WithPosition<Identifier>,
constructor: WithPosition<TypeConstructor>,
) -> Self {
Self {
identifier,
constructor,
}
} }
} }
@ -29,9 +35,15 @@ impl AbstractNode for TypeAssignment {
Ok(()) Ok(())
} }
fn run(self, context: &mut Context, _manage_memory: bool) -> Result<Action, RuntimeError> { fn evaluate(
context.set_type(self.identifier.node, self.r#type.node)?; self,
context: &mut Context,
_manage_memory: bool,
) -> Result<Evaluation, RuntimeError> {
let r#type = self.constructor.node.construct(&context)?;
Ok(Action::None) context.set_type(self.identifier.node, r#type)?;
Ok(Evaluation::None)
} }
} }

View File

@ -0,0 +1,78 @@
use std::fmt::{self, Display, Formatter};
use serde::{Deserialize, Serialize};
use crate::{context::Context, error::ValidationError, identifier::Identifier};
use super::{ExpectedType, Type, WithPosition};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum TypeConstructor {
Function {
type_parameters: Option<Vec<WithPosition<Identifier>>>,
value_parameters: Vec<(WithPosition<Identifier>, Box<WithPosition<TypeConstructor>>)>,
return_type: Box<WithPosition<TypeConstructor>>,
},
Identifier(WithPosition<Identifier>),
List {
length: usize,
item_type: Box<WithPosition<TypeConstructor>>,
},
ListOf(WithPosition<Box<TypeConstructor>>),
Type(Type),
}
impl TypeConstructor {
pub fn validate(
&self,
_context: &mut Context,
_manage_memory: bool,
) -> Result<(), ValidationError> {
todo!()
}
pub fn construct(self, context: &Context) -> Result<Type, ValidationError> {
match self {
TypeConstructor::Function {
type_parameters: _,
value_parameters: _,
return_type: _,
} => todo!(),
TypeConstructor::Identifier(WithPosition {
node: identifier,
position,
}) => {
if let Some(r#type) = context.get_type(&identifier)? {
Ok(r#type)
} else {
Err(ValidationError::VariableNotFound {
identifier,
position,
})
}
}
TypeConstructor::List { length, item_type } => {
let constructed_type = item_type.node.construct(context)?;
Ok(Type::List {
length,
item_type: Box::new(constructed_type),
})
}
TypeConstructor::Type(r#type) => Ok(r#type),
TypeConstructor::ListOf(_) => todo!(),
}
}
}
impl ExpectedType for TypeConstructor {
fn expected_type(&self, _: &mut Context) -> Result<Type, ValidationError> {
Ok(Type::None)
}
}
impl Display for TypeConstructor {
fn fmt(&self, _: &mut Formatter) -> fmt::Result {
todo!()
}
}

View File

@ -7,12 +7,12 @@ use crate::{
}; };
use super::{ use super::{
AbstractNode, Action, As, BuiltInFunctionCall, ExpectedType, FunctionCall, ListIndex, Logic, AbstractNode, As, BuiltInFunctionCall, Evaluation, ExpectedType, FunctionCall, ListIndex,
MapIndex, Math, SourcePosition, Type, ValueNode, WithPosition, Logic, MapIndex, Math, SourcePosition, Type, ValueNode, WithPosition,
}; };
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum ValueExpression { pub enum Expression {
As(WithPosition<Box<As>>), As(WithPosition<Box<As>>),
BuiltInFunctionCall(WithPosition<Box<BuiltInFunctionCall>>), BuiltInFunctionCall(WithPosition<Box<BuiltInFunctionCall>>),
FunctionCall(WithPosition<FunctionCall>), FunctionCall(WithPosition<FunctionCall>),
@ -24,30 +24,30 @@ pub enum ValueExpression {
Value(WithPosition<ValueNode>), Value(WithPosition<ValueNode>),
} }
impl ValueExpression { impl Expression {
pub fn position(&self) -> SourcePosition { pub fn position(&self) -> SourcePosition {
match self { match self {
ValueExpression::As(inner) => inner.position, Expression::As(inner) => inner.position,
ValueExpression::FunctionCall(inner) => inner.position, Expression::FunctionCall(inner) => inner.position,
ValueExpression::Identifier(inner) => inner.position, Expression::Identifier(inner) => inner.position,
ValueExpression::MapIndex(inner) => inner.position, Expression::MapIndex(inner) => inner.position,
ValueExpression::ListIndex(inner) => inner.position, Expression::ListIndex(inner) => inner.position,
ValueExpression::Logic(inner) => inner.position, Expression::Logic(inner) => inner.position,
ValueExpression::Math(inner) => inner.position, Expression::Math(inner) => inner.position,
ValueExpression::Value(inner) => inner.position, Expression::Value(inner) => inner.position,
ValueExpression::BuiltInFunctionCall(inner) => inner.position, Expression::BuiltInFunctionCall(inner) => inner.position,
} }
} }
} }
impl AbstractNode for ValueExpression { impl AbstractNode for Expression {
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 {
ValueExpression::As(r#as) => r#as.node.validate(context, manage_memory), Expression::As(r#as) => r#as.node.validate(context, manage_memory),
ValueExpression::FunctionCall(function_call) => { Expression::FunctionCall(function_call) => {
function_call.node.validate(context, manage_memory) function_call.node.validate(context, manage_memory)
} }
ValueExpression::Identifier(identifier) => { Expression::Identifier(identifier) => {
let found = if manage_memory { let found = if manage_memory {
context.add_expected_use(&identifier.node)? context.add_expected_use(&identifier.node)?
} else { } else {
@ -63,26 +63,28 @@ impl AbstractNode for ValueExpression {
}) })
} }
} }
ValueExpression::MapIndex(map_index) => map_index.node.validate(context, manage_memory), Expression::MapIndex(map_index) => map_index.node.validate(context, manage_memory),
ValueExpression::ListIndex(list_index) => { Expression::ListIndex(list_index) => list_index.node.validate(context, manage_memory),
list_index.node.validate(context, manage_memory) Expression::Logic(logic) => logic.node.validate(context, manage_memory),
} Expression::Math(math) => math.node.validate(context, manage_memory),
ValueExpression::Logic(logic) => logic.node.validate(context, manage_memory), Expression::Value(value_node) => value_node.node.validate(context, manage_memory),
ValueExpression::Math(math) => math.node.validate(context, manage_memory), Expression::BuiltInFunctionCall(built_in_function_call) => {
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) built_in_function_call.node.validate(context, manage_memory)
} }
} }
} }
fn run(self, context: &mut Context, manage_memory: bool) -> Result<Action, RuntimeError> { fn evaluate(
self,
context: &mut Context,
manage_memory: bool,
) -> Result<Evaluation, RuntimeError> {
match self { match self {
ValueExpression::As(r#as) => r#as.node.run(context, manage_memory), Expression::As(r#as) => r#as.node.evaluate(context, manage_memory),
ValueExpression::FunctionCall(function_call) => { Expression::FunctionCall(function_call) => {
function_call.node.run(context, manage_memory) function_call.node.evaluate(context, manage_memory)
} }
ValueExpression::Identifier(identifier) => { Expression::Identifier(identifier) => {
let value_option = if manage_memory { let value_option = if manage_memory {
context.use_value(&identifier.node)? context.use_value(&identifier.node)?
} else { } else {
@ -90,7 +92,7 @@ impl AbstractNode for ValueExpression {
}; };
if let Some(value) = value_option { if let Some(value) = value_option {
Ok(Action::Return(value)) Ok(Evaluation::Return(value))
} else { } else {
Err(RuntimeError::ValidationFailure( Err(RuntimeError::ValidationFailure(
ValidationError::VariableNotFound { ValidationError::VariableNotFound {
@ -100,26 +102,24 @@ impl AbstractNode for ValueExpression {
)) ))
} }
} }
ValueExpression::MapIndex(map_index) => map_index.node.run(context, manage_memory), Expression::MapIndex(map_index) => map_index.node.evaluate(context, manage_memory),
ValueExpression::ListIndex(list_index) => list_index.node.run(context, manage_memory), Expression::ListIndex(list_index) => list_index.node.evaluate(context, manage_memory),
ValueExpression::Logic(logic) => logic.node.run(context, manage_memory), Expression::Logic(logic) => logic.node.evaluate(context, manage_memory),
ValueExpression::Math(math) => math.node.run(context, manage_memory), Expression::Math(math) => math.node.evaluate(context, manage_memory),
ValueExpression::Value(value_node) => value_node.node.run(context, manage_memory), Expression::Value(value_node) => value_node.node.evaluate(context, manage_memory),
ValueExpression::BuiltInFunctionCall(built_in_function_call) => { Expression::BuiltInFunctionCall(built_in_function_call) => {
built_in_function_call.node.run(context, manage_memory) built_in_function_call.node.evaluate(context, manage_memory)
} }
} }
} }
} }
impl ExpectedType for ValueExpression { impl ExpectedType for Expression {
fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> { fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> {
match self { match self {
ValueExpression::As(r#as) => r#as.node.expected_type(_context), Expression::As(r#as) => r#as.node.expected_type(_context),
ValueExpression::FunctionCall(function_call) => { Expression::FunctionCall(function_call) => function_call.node.expected_type(_context),
function_call.node.expected_type(_context) Expression::Identifier(identifier) => {
}
ValueExpression::Identifier(identifier) => {
if let Some(r#type) = _context.get_type(&identifier.node)? { if let Some(r#type) = _context.get_type(&identifier.node)? {
Ok(r#type) Ok(r#type)
} else { } else {
@ -129,12 +129,12 @@ impl ExpectedType for ValueExpression {
}) })
} }
} }
ValueExpression::MapIndex(map_index) => map_index.node.expected_type(_context), Expression::MapIndex(map_index) => map_index.node.expected_type(_context),
ValueExpression::ListIndex(list_index) => list_index.node.expected_type(_context), Expression::ListIndex(list_index) => list_index.node.expected_type(_context),
ValueExpression::Logic(logic) => logic.node.expected_type(_context), Expression::Logic(logic) => logic.node.expected_type(_context),
ValueExpression::Math(math) => math.node.expected_type(_context), Expression::Math(math) => math.node.expected_type(_context),
ValueExpression::Value(value_node) => value_node.node.expected_type(_context), Expression::Value(value_node) => value_node.node.expected_type(_context),
ValueExpression::BuiltInFunctionCall(built_in_function_call) => { Expression::BuiltInFunctionCall(built_in_function_call) => {
built_in_function_call.node.expected_type(_context) built_in_function_call.node.expected_type(_context)
} }
} }

View File

@ -10,7 +10,7 @@ use crate::{
}; };
use super::{ use super::{
AbstractNode, Action, Block, ExpectedType, Type, ValueExpression, WithPos, WithPosition, AbstractNode, Block, Evaluation, ExpectedType, Expression, Type, TypeConstructor, WithPosition,
}; };
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
@ -18,18 +18,24 @@ pub enum ValueNode {
Boolean(bool), Boolean(bool),
Float(f64), Float(f64),
Integer(i64), Integer(i64),
List(Vec<ValueExpression>), List(Vec<Expression>),
Map(Vec<(Identifier, Option<WithPosition<Type>>, ValueExpression)>), Map(
Vec<(
Identifier,
Option<WithPosition<TypeConstructor>>,
Expression,
)>,
),
Range(Range<i64>), Range(Range<i64>),
String(String), String(String),
Structure { Structure {
name: WithPosition<Identifier>, name: WithPosition<Identifier>,
fields: Vec<(Identifier, ValueExpression)>, fields: Vec<(WithPosition<Identifier>, Expression)>,
}, },
ParsedFunction { ParsedFunction {
type_arguments: Vec<WithPosition<Type>>, type_parameters: Option<Vec<WithPosition<Identifier>>>,
parameters: Vec<(Identifier, WithPosition<Type>)>, value_parameters: Vec<(Identifier, WithPosition<TypeConstructor>)>,
return_type: WithPosition<Type>, return_type: WithPosition<TypeConstructor>,
body: WithPosition<Block>, body: WithPosition<Block>,
}, },
} }
@ -37,17 +43,18 @@ pub enum ValueNode {
impl AbstractNode for ValueNode { impl AbstractNode for ValueNode {
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, constructor_option, expression) in map_assignments {
expression.validate(context, _manage_memory)?; expression.validate(context, _manage_memory)?;
if let Some(expected_type) = r#type { if let Some(constructor) = constructor_option {
let actual_type = expression.expected_type(context)?; let actual_type = expression.expected_type(context)?;
let exprected_type = constructor.node.clone().construct(&context)?;
expected_type.node.check(&actual_type).map_err(|conflict| { exprected_type.check(&actual_type).map_err(|conflict| {
ValidationError::TypeCheck { ValidationError::TypeCheck {
conflict, conflict,
actual_position: expression.position(), actual_position: expression.position(),
expected_position: expected_type.position, expected_position: Some(constructor.position),
} }
})?; })?;
} }
@ -57,22 +64,18 @@ impl AbstractNode for ValueNode {
} }
if let ValueNode::ParsedFunction { if let ValueNode::ParsedFunction {
type_arguments, type_parameters: _,
parameters, value_parameters,
return_type, return_type,
body, body,
} = self } = self
{ {
let mut function_context = Context::new(Some(&context)); let mut function_context = Context::new(Some(&context));
for r#type in type_arguments { for (identifier, type_constructor) in value_parameters {
if let Type::Argument(identifier) = &r#type.node { let r#type = type_constructor.node.clone().construct(&function_context)?;
function_context.set_type(identifier.clone(), r#type.node.clone())?;
}
}
for (identifier, r#type) in parameters { function_context.set_type(identifier.clone(), r#type)?;
function_context.set_type(identifier.clone(), r#type.node.clone())?;
} }
body.node.validate(&mut function_context, _manage_memory)?; body.node.validate(&mut function_context, _manage_memory)?;
@ -81,11 +84,13 @@ impl AbstractNode for ValueNode {
return_type return_type
.node .node
.clone()
.construct(&function_context)?
.check(&actual_return_type) .check(&actual_return_type)
.map_err(|conflict| ValidationError::TypeCheck { .map_err(|conflict| ValidationError::TypeCheck {
conflict, conflict,
actual_position: body.position, actual_position: body.position,
expected_position: return_type.position, expected_position: Some(return_type.position),
})?; })?;
return Ok(()); return Ok(());
@ -111,11 +116,11 @@ impl AbstractNode for ValueNode {
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.node.check(&actual_type).map_err(|conflict| { expected_type.check(&actual_type).map_err(|conflict| {
ValidationError::TypeCheck { ValidationError::TypeCheck {
conflict, conflict,
actual_position: expression.position(), actual_position: expression.position(),
expected_position: expected_type.position, expected_position: None,
} }
})? })?
} }
@ -125,7 +130,11 @@ impl AbstractNode for ValueNode {
Ok(()) Ok(())
} }
fn run(self, _context: &mut Context, _manage_memory: bool) -> Result<Action, RuntimeError> { fn evaluate(
self,
context: &mut Context,
_manage_memory: bool,
) -> Result<Evaluation, RuntimeError> {
let value = match self { let value = match self {
ValueNode::Boolean(boolean) => Value::boolean(boolean), ValueNode::Boolean(boolean) => Value::boolean(boolean),
ValueNode::Float(float) => Value::float(float), ValueNode::Float(float) => Value::float(float),
@ -135,8 +144,8 @@ impl AbstractNode for ValueNode {
for expression in expression_list { for expression in expression_list {
let expression_position = expression.position(); let expression_position = expression.position();
let action = expression.run(_context, _manage_memory)?; let action = expression.evaluate(context, _manage_memory)?;
let value = if let Action::Return(value) = action { let value = if let Evaluation::Return(value) = action {
WithPosition { WithPosition {
node: value, node: value,
position: expression_position, position: expression_position,
@ -157,8 +166,8 @@ impl AbstractNode for ValueNode {
for (identifier, _type, expression) in property_list { for (identifier, _type, expression) in property_list {
let expression_position = expression.position(); let expression_position = expression.position();
let action = expression.run(_context, _manage_memory)?; let action = expression.evaluate(context, _manage_memory)?;
let value = if let Action::Return(value) = action { let value = if let Evaluation::Return(value) = action {
value value
} else { } else {
return Err(RuntimeError::ValidationFailure( return Err(RuntimeError::ValidationFailure(
@ -174,11 +183,29 @@ impl AbstractNode for ValueNode {
ValueNode::Range(range) => Value::range(range), ValueNode::Range(range) => Value::range(range),
ValueNode::String(string) => Value::string(string), ValueNode::String(string) => Value::string(string),
ValueNode::ParsedFunction { ValueNode::ParsedFunction {
type_arguments, type_parameters,
parameters, value_parameters: constructors,
return_type, return_type,
body, body,
} => Value::function(type_arguments, parameters, return_type, body), } => {
let type_parameters = type_parameters.map(|parameter_list| {
parameter_list
.into_iter()
.map(|parameter| parameter.node)
.collect()
});
let mut value_parameters = Vec::with_capacity(constructors.len());
for (identifier, constructor) in constructors {
let r#type = constructor.node.construct(&context)?;
value_parameters.push((identifier, r#type));
}
let return_type = return_type.node.construct(&context)?;
Value::function(type_parameters, value_parameters, return_type, body.node)
}
ValueNode::Structure { ValueNode::Structure {
name, name,
fields: expressions, fields: expressions,
@ -187,8 +214,8 @@ impl AbstractNode for ValueNode {
for (identifier, expression) in expressions { for (identifier, expression) in expressions {
let expression_position = expression.position(); let expression_position = expression.position();
let action = expression.run(_context, _manage_memory)?; let action = expression.evaluate(context, _manage_memory)?;
let value = if let Action::Return(value) = action { let value = if let Evaluation::Return(value) = action {
value value
} else { } else {
return Err(RuntimeError::ValidationFailure( return Err(RuntimeError::ValidationFailure(
@ -196,14 +223,14 @@ impl AbstractNode for ValueNode {
)); ));
}; };
fields.push((identifier, value)); fields.push((identifier.node, value));
} }
Value::structure(name, fields) Value::structure(name, fields)
} }
}; };
Ok(Action::Return(value)) Ok(Evaluation::Return(value))
} }
} }
@ -244,14 +271,14 @@ impl Ord for ValueNode {
(String(_), _) => Ordering::Greater, (String(_), _) => Ordering::Greater,
( (
ParsedFunction { ParsedFunction {
type_arguments: left_type_arguments, type_parameters: left_type_arguments,
parameters: left_parameters, value_parameters: left_parameters,
return_type: left_return, return_type: left_return,
body: left_body, body: left_body,
}, },
ParsedFunction { ParsedFunction {
type_arguments: right_type_arguments, type_parameters: right_type_arguments,
parameters: right_parameters, value_parameters: right_parameters,
return_type: right_return, return_type: right_return,
body: right_body, body: right_body,
}, },
@ -307,32 +334,44 @@ impl ExpectedType for ValueNode {
ValueNode::Float(_) => Type::Float, ValueNode::Float(_) => Type::Float,
ValueNode::Integer(_) => Type::Integer, ValueNode::Integer(_) => Type::Integer,
ValueNode::List(items) => { ValueNode::List(items) => {
let mut item_types = Vec::with_capacity(items.len()); let item_type = items.first().unwrap().expected_type(context)?;
for expression in items { Type::List {
item_types.push( length: items.len(),
expression item_type: Box::new(item_type),
.expected_type(context)?
.with_position(expression.position()),
);
} }
Type::ListExact(item_types)
} }
ValueNode::Map(_) => Type::Map, ValueNode::Map(_) => Type::Map,
ValueNode::Range(_) => Type::Range, ValueNode::Range(_) => Type::Range,
ValueNode::String(_) => Type::String, ValueNode::String(_) => Type::String,
ValueNode::ParsedFunction { ValueNode::ParsedFunction {
parameters, type_parameters,
value_parameters,
return_type, return_type,
.. ..
} => Type::Function { } => {
parameter_types: parameters let mut value_parameter_types = Vec::with_capacity(value_parameters.len());
.iter()
.map(|(_, r#type)| r#type.clone()) for (identifier, type_constructor) in value_parameters {
.collect(), let r#type = type_constructor.node.clone().construct(&context)?;
return_type: Box::new(return_type.clone()),
}, value_parameter_types.push((identifier.clone(), r#type));
}
let type_parameters = type_parameters.clone().map(|parameters| {
parameters
.iter()
.map(|identifier| identifier.node.clone())
.collect()
});
let return_type = return_type.node.clone().construct(&context)?;
Type::Function {
type_parameters,
value_parameters: value_parameter_types,
return_type: Box::new(return_type),
}
}
ValueNode::Structure { ValueNode::Structure {
name, name,
fields: expressions, fields: expressions,
@ -353,7 +392,10 @@ impl ExpectedType for ValueNode {
Type::Structure { Type::Structure {
name: name.node.clone(), name: name.node.clone(),
fields: types, fields: types
.into_iter()
.map(|(identifier, r#type)| (identifier.node, r#type.node))
.collect(),
} }
} }
}; };

View File

@ -7,16 +7,16 @@ use crate::{
Value, Value,
}; };
use super::{AbstractNode, Action, Statement, ValueExpression}; use super::{AbstractNode, Evaluation, Expression, Statement};
#[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: ValueExpression, expression: Expression,
statements: Vec<Statement>, statements: Vec<Statement>,
} }
impl While { impl While {
pub fn new(expression: ValueExpression, statements: Vec<Statement>) -> Self { pub fn new(expression: Expression, statements: Vec<Statement>) -> Self {
Self { Self {
expression, expression,
statements, statements,
@ -39,12 +39,19 @@ impl AbstractNode for While {
Ok(()) Ok(())
} }
fn run(self, _context: &mut Context, _manage_memory: bool) -> Result<Action, RuntimeError> { fn evaluate(
self,
_context: &mut Context,
_manage_memory: bool,
) -> Result<Evaluation, RuntimeError> {
let get_boolean = || -> Result<Value, RuntimeError> { let get_boolean = || -> Result<Value, RuntimeError> {
let expression_position = self.expression.position(); let expression_position = self.expression.position();
let action = self.expression.clone().run(&mut _context.clone(), false)?; let action = self
.expression
.clone()
.evaluate(&mut _context.clone(), false)?;
if let Action::Return(value) = action { if let Evaluation::Return(value) = action {
Ok(value) Ok(value)
} else { } else {
Err(RuntimeError::ValidationFailure( Err(RuntimeError::ValidationFailure(
@ -55,16 +62,16 @@ impl AbstractNode for While {
while let ValueInner::Boolean(true) = get_boolean()?.inner().as_ref() { while let ValueInner::Boolean(true) = get_boolean()?.inner().as_ref() {
for statement in &self.statements { for statement in &self.statements {
let action = statement.clone().run(&mut _context.clone(), false)?; let action = statement.clone().evaluate(&mut _context.clone(), false)?;
match action { match action {
Action::Return(_) => {} Evaluation::Return(_) => {}
Action::None => {} Evaluation::None => {}
Action::Break => return Ok(Action::Break), Evaluation::Break => return Ok(Evaluation::Break),
} }
} }
} }
Ok(Action::None) Ok(Evaluation::None)
} }
} }

View File

@ -12,7 +12,7 @@ use crate::{
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Context<'a> { pub struct Context<'a> {
variables: Arc<RwLock<BTreeMap<Identifier, (ValueData, UsageData)>>>, variables: Arc<RwLock<BTreeMap<Identifier, (VariableData, UsageData)>>>,
parent: Option<&'a Context<'a>>, parent: Option<&'a Context<'a>>,
is_clean: Arc<RwLock<bool>>, is_clean: Arc<RwLock<bool>>,
} }
@ -28,7 +28,7 @@ impl<'a> Context<'a> {
pub fn inner( pub fn inner(
&self, &self,
) -> Result<RwLockReadGuard<BTreeMap<Identifier, (ValueData, UsageData)>>, RwLockPoisonError> ) -> Result<RwLockReadGuard<BTreeMap<Identifier, (VariableData, UsageData)>>, RwLockPoisonError>
{ {
Ok(self.variables.read()?) Ok(self.variables.read()?)
} }
@ -50,8 +50,8 @@ impl<'a> Context<'a> {
log::trace!("Getting {identifier}'s type."); log::trace!("Getting {identifier}'s type.");
let r#type = match value_data { let r#type = match value_data {
ValueData::Type(r#type) => r#type.clone(), VariableData::Type(r#type) => r#type.clone(),
ValueData::Value(value) => value.r#type(self)?, VariableData::Value(value) => value.r#type(self)?,
}; };
Ok(Some(r#type.clone())) Ok(Some(r#type.clone()))
@ -63,7 +63,8 @@ impl<'a> Context<'a> {
} }
pub fn use_value(&self, identifier: &Identifier) -> Result<Option<Value>, RwLockPoisonError> { pub fn use_value(&self, identifier: &Identifier) -> Result<Option<Value>, RwLockPoisonError> {
if let Some((ValueData::Value(value), usage_data)) = self.variables.read()?.get(identifier) if let Some((VariableData::Value(value), usage_data)) =
self.variables.read()?.get(identifier)
{ {
log::trace!("Using {identifier}'s value."); log::trace!("Using {identifier}'s value.");
@ -79,7 +80,7 @@ impl<'a> Context<'a> {
} }
pub fn get_value(&self, identifier: &Identifier) -> Result<Option<Value>, RwLockPoisonError> { pub fn get_value(&self, identifier: &Identifier) -> Result<Option<Value>, RwLockPoisonError> {
if let Some((ValueData::Value(value), _)) = self.variables.read()?.get(identifier) { if let Some((VariableData::Value(value), _)) = self.variables.read()?.get(identifier) {
log::trace!("Getting {identifier}'s value."); log::trace!("Getting {identifier}'s value.");
Ok(Some(value.clone())) Ok(Some(value.clone()))
@ -93,7 +94,7 @@ impl<'a> Context<'a> {
pub fn get_data( pub fn get_data(
&self, &self,
identifier: &Identifier, identifier: &Identifier,
) -> Result<Option<(ValueData, UsageData)>, RwLockPoisonError> { ) -> Result<Option<(VariableData, UsageData)>, RwLockPoisonError> {
if let Some(full_data) = self.variables.read()?.get(identifier) { if let Some(full_data) = self.variables.read()?.get(identifier) {
log::trace!("Getting {identifier}'s value."); log::trace!("Getting {identifier}'s value.");
@ -110,7 +111,7 @@ impl<'a> Context<'a> {
self.variables self.variables
.write()? .write()?
.insert(identifier, (ValueData::Type(r#type), UsageData::new())); .insert(identifier, (VariableData::Type(r#type), UsageData::new()));
Ok(()) Ok(())
} }
@ -128,9 +129,9 @@ impl<'a> Context<'a> {
.map(|(_, usage_data)| usage_data); .map(|(_, usage_data)| usage_data);
if let Some(usage_data) = old_usage_data { if let Some(usage_data) = old_usage_data {
variables.insert(identifier, (ValueData::Value(value), usage_data)); variables.insert(identifier, (VariableData::Value(value), usage_data));
} else { } else {
variables.insert(identifier, (ValueData::Value(value), UsageData::new())); variables.insert(identifier, (VariableData::Value(value), UsageData::new()));
} }
Ok(()) Ok(())
@ -144,7 +145,7 @@ impl<'a> Context<'a> {
self.variables self.variables
.write()? .write()?
.retain(|identifier, (value_data, usage_data)| { .retain(|identifier, (value_data, usage_data)| {
if let ValueData::Value(_) = value_data { if let VariableData::Value(_) = value_data {
let usage = usage_data.inner().read().unwrap(); let usage = usage_data.inner().read().unwrap();
if usage.actual < usage.expected { if usage.actual < usage.expected {
@ -196,7 +197,7 @@ impl<'a> Context<'a> {
} }
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
pub enum ValueData { pub enum VariableData {
Type(Type), Type(Type),
Value(Value), Value(Value),
} }

View File

@ -3,7 +3,7 @@ use std::{io, sync::PoisonError};
use chumsky::{prelude::Rich, span::Span}; use chumsky::{prelude::Rich, span::Span};
use crate::{ use crate::{
abstract_tree::{SourcePosition, Type}, abstract_tree::{r#type::Type, SourcePosition, TypeConstructor},
identifier::Identifier, identifier::Identifier,
lexer::Token, lexer::Token,
}; };
@ -141,11 +141,15 @@ pub enum ValidationError {
actual_position: SourcePosition, actual_position: SourcePosition,
/// The position of the item that gave the "expected" type. /// The position of the item that gave the "expected" type.
expected_position: SourcePosition, expected_position: Option<SourcePosition>,
},
WrongTypeArgumentCount {
expected: usize,
actual: usize,
}, },
WrongArguments { WrongArguments {
expected: Vec<Type>, expected: Vec<TypeConstructor>,
actual: Vec<Type>, actual: Vec<TypeConstructor>,
}, },
VariableNotFound { VariableNotFound {
identifier: Identifier, identifier: Identifier,

View File

@ -325,21 +325,23 @@ impl InterpreterError {
} => { } => {
let TypeConflict { actual, expected } = conflict; let TypeConflict { actual, expected } = conflict;
builder.add_labels([ if let Some(position) = expected_position {
Label::new(( builder.add_label(
self.source_id.clone(), Label::new((self.source_id.clone(), position.0..position.1))
expected_position.0..expected_position.1, .with_message(format!(
)) "Type {} established here.",
.with_message(format!( expected.fg(type_color)
"Type {} established here.", )),
expected.fg(type_color) )
)), }
builder.add_label(
Label::new(( Label::new((
self.source_id.clone(), self.source_id.clone(),
actual_position.0..actual_position.1, actual_position.0..actual_position.1,
)) ))
.with_message(format!("Got type {} here.", actual.fg(type_color))), .with_message(format!("Got type {} here.", actual.fg(type_color))),
]); );
} }
ValidationError::VariableNotFound { ValidationError::VariableNotFound {
identifier, identifier,
@ -390,6 +392,7 @@ impl InterpreterError {
ValidationError::ExpectedValue(_) => todo!(), ValidationError::ExpectedValue(_) => todo!(),
ValidationError::PropertyNotFound { .. } => todo!(), ValidationError::PropertyNotFound { .. } => todo!(),
ValidationError::WrongArguments { .. } => todo!(), ValidationError::WrongArguments { .. } => todo!(),
ValidationError::WrongTypeArgumentCount { .. } => todo!(),
ValidationError::ExpectedIntegerFloatOrString { actual, position } => { ValidationError::ExpectedIntegerFloatOrString { actual, position } => {
builder = builder.with_message(format!( builder = builder.with_message(format!(
"Expected an {}, {} or {}.", "Expected an {}, {} or {}.",

File diff suppressed because it is too large Load Diff

View File

@ -9,7 +9,7 @@ use std::{
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{ use crate::{
abstract_tree::{AbstractNode, Action, Block, Type, WithPos, WithPosition}, abstract_tree::{AbstractNode, Block, Evaluation, Type, WithPosition},
context::Context, context::Context,
error::{RuntimeError, ValidationError}, error::{RuntimeError, ValidationError},
identifier::Identifier, identifier::Identifier,
@ -52,14 +52,14 @@ impl Value {
} }
pub fn function( pub fn function(
type_arguments: Vec<WithPosition<Type>>, type_parameters: Option<Vec<Identifier>>,
parameters: Vec<(Identifier, WithPosition<Type>)>, value_parameters: Vec<(Identifier, Type)>,
return_type: WithPosition<Type>, return_type: Type,
body: WithPosition<Block>, body: Block,
) -> Self { ) -> Self {
Value(Arc::new(ValueInner::Function(Function { Value(Arc::new(ValueInner::Function(Function {
type_parameters: type_arguments, type_parameters,
parameters, value_parameters,
return_type, return_type,
body, body,
}))) })))
@ -129,19 +129,19 @@ impl Display for Value {
ValueInner::Range(_) => todo!(), ValueInner::Range(_) => todo!(),
ValueInner::String(string) => write!(f, "{string}"), ValueInner::String(string) => write!(f, "{string}"),
ValueInner::Function(Function { ValueInner::Function(Function {
type_parameters: type_arguments, type_parameters,
parameters, value_parameters: parameters,
return_type, return_type,
body, body,
}) => { }) => {
if !type_arguments.is_empty() { if let Some(type_parameters) = type_parameters {
write!(f, "(")?; write!(f, "(")?;
for (index, r#type) in type_arguments.into_iter().enumerate() { for (index, r#type) in type_parameters.into_iter().enumerate() {
if index == type_arguments.len() - 1 { if index == type_parameters.len() - 1 {
write!(f, "{}", r#type.node)?; write!(f, "{}", r#type)?;
} else { } else {
write!(f, "{} ", r#type.node)?; write!(f, "{} ", r#type)?;
} }
} }
@ -151,10 +151,10 @@ 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.node)?; write!(f, "{identifier}: {}", r#type)?;
} }
write!(f, "): {} {:?}", return_type.node, body.node) write!(f, "): {} {:?}", return_type, body)
} }
ValueInner::Structure { name, fields } => { ValueInner::Structure { name, fields } => {
write!(f, "{}\n{{", name.node)?; write!(f, "{}\n{{", name.node)?;
@ -224,23 +224,19 @@ impl ValueInner {
ValueInner::Float(_) => Type::Float, ValueInner::Float(_) => Type::Float,
ValueInner::Integer(_) => Type::Integer, ValueInner::Integer(_) => Type::Integer,
ValueInner::List(values) => { ValueInner::List(values) => {
let mut types = Vec::with_capacity(values.len()); let item_type = values.first().unwrap().node.r#type(context)?;
for value in values { Type::List {
types.push(value.node.r#type(context)?.with_position(value.position)); length: values.len(),
item_type: Box::new(item_type),
} }
Type::ListExact(types)
} }
ValueInner::Map(_) => Type::Map, ValueInner::Map(_) => Type::Map,
ValueInner::Range(_) => Type::Range, ValueInner::Range(_) => Type::Range,
ValueInner::String(_) => Type::String, ValueInner::String(_) => Type::String,
ValueInner::Function(function) => Type::Function { ValueInner::Function(function) => Type::Function {
parameter_types: function type_parameters: None,
.parameters value_parameters: function.value_parameters.clone(),
.iter()
.map(|(_, r#type)| r#type.clone())
.collect(),
return_type: Box::new(function.return_type.clone()), return_type: Box::new(function.return_type.clone()),
}, },
ValueInner::Structure { name, .. } => { ValueInner::Structure { name, .. } => {
@ -321,14 +317,14 @@ impl Ord for ValueInner {
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct Function { pub struct Function {
type_parameters: Vec<WithPosition<Type>>, type_parameters: Option<Vec<Identifier>>,
parameters: Vec<(Identifier, WithPosition<Type>)>, value_parameters: Vec<(Identifier, Type)>,
return_type: WithPosition<Type>, return_type: Type,
body: WithPosition<Block>, body: Block,
} }
impl Function { impl Function {
pub fn type_parameters(&self) -> &Vec<WithPosition<Type>> { pub fn type_parameters(&self) -> &Option<Vec<Identifier>> {
&self.type_parameters &self.type_parameters
} }
@ -337,11 +333,12 @@ impl Function {
arguments: Vec<Value>, arguments: Vec<Value>,
context: &mut Context, context: &mut Context,
clear_variables: bool, clear_variables: bool,
) -> Result<Action, RuntimeError> { ) -> Result<Evaluation, RuntimeError> {
for ((identifier, _), value) in self.parameters.into_iter().zip(arguments.into_iter()) { for ((identifier, _), value) in self.value_parameters.into_iter().zip(arguments.into_iter())
{
context.set_value(identifier.clone(), value)?; context.set_value(identifier.clone(), value)?;
} }
self.body.node.run(context, clear_variables) self.body.evaluate(context, clear_variables)
} }
} }

View File

@ -56,7 +56,7 @@ fn field_type_error() {
expected: Type::Integer expected: Type::Integer
}, },
actual_position: (128, 134).into(), actual_position: (128, 134).into(),
expected_position: (56, 59).into() expected_position: Some((56, 59).into()),
}, },
position: (96, 153).into() position: (96, 153).into()
}] }]

View File

@ -148,7 +148,7 @@ fn map_type_errors() {
expected: Type::Boolean expected: Type::Boolean
}, },
actual_position: (15, 20).into(), actual_position: (15, 20).into(),
expected_position: (8, 12).into(), expected_position: Some((8, 12).into()),
}, },
position: (0, 22).into() position: (0, 22).into()
}] }]

View File

@ -1,5 +1,5 @@
use dust_lang::{ use dust_lang::{
abstract_tree::{Block, Statement, Type, ValueExpression, WithPos}, abstract_tree::{Block, Expression, Statement, Type, WithPos},
error::{Error, TypeConflict, ValidationError}, error::{Error, TypeConflict, ValidationError},
identifier::Identifier, identifier::Identifier,
*, *,
@ -34,7 +34,7 @@ fn set_variable_with_type_error() {
expected: Type::String expected: Type::String
}, },
actual_position: (14, 18).into(), actual_position: (14, 18).into(),
expected_position: (8, 11).into() expected_position: Some((8, 11).into())
}, },
position: (0, 18).into() position: (0, 18).into()
}] }]
@ -46,13 +46,12 @@ fn function_variable() {
assert_eq!( assert_eq!(
interpret("test", "foobar = fn (x: int) int { x }; foobar"), interpret("test", "foobar = fn (x: int) int { x }; foobar"),
Ok(Some(Value::function( Ok(Some(Value::function(
Vec::with_capacity(0), Some(Vec::with_capacity(0)),
vec![(Identifier::new("x"), Type::Integer.with_position((16, 19)))], vec![(Identifier::new("x"), Type::Integer)],
Type::Integer.with_position((21, 24)), Type::Integer,
Block::new(vec![Statement::ValueExpression( Block::new(vec![Statement::ValueExpression(Expression::Identifier(
ValueExpression::Identifier(Identifier::new("x").with_position((27, 28))) Identifier::new("x").with_position((27, 28))
)]) ))])
.with_position((25, 30))
))) )))
); );
} }