1
0

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

View File

@ -7,12 +7,12 @@ use crate::{
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)]
pub struct Assignment {
identifier: WithPosition<Identifier>,
r#type: Option<WithPosition<Type>>,
constructor: Option<WithPosition<TypeConstructor>>,
operator: AssignmentOperator,
statement: Box<Statement>,
}
@ -27,13 +27,13 @@ pub enum AssignmentOperator {
impl Assignment {
pub fn new(
identifier: WithPosition<Identifier>,
r#type: Option<WithPosition<Type>>,
constructor: Option<WithPosition<TypeConstructor>>,
operator: AssignmentOperator,
statement: Statement,
) -> Self {
Self {
identifier,
r#type,
constructor,
operator,
statement: Box::new(statement),
}
@ -45,19 +45,21 @@ impl AbstractNode for Assignment {
let statement_type = self.statement.expected_type(context)?;
if let Some(WithPosition {
node: expected_type,
node: constructor,
position: expected_position,
}) = &self.r#type
}) = &self.constructor
{
expected_type.check(&statement_type).map_err(|conflict| {
ValidationError::TypeCheck {
let r#type = constructor.clone().construct(&context)?;
r#type
.check(&statement_type)
.map_err(|conflict| ValidationError::TypeCheck {
conflict,
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 {
context.set_type(self.identifier.node.clone(), statement_type)?;
}
@ -67,10 +69,14 @@ impl AbstractNode for Assignment {
Ok(())
}
fn run(self, context: &mut Context, manage_memory: bool) -> Result<Action, RuntimeError> {
let action = self.statement.run(context, manage_memory)?;
fn evaluate(
self,
context: &mut Context,
manage_memory: bool,
) -> Result<Evaluation, RuntimeError> {
let action = self.statement.evaluate(context, manage_memory)?;
let right = match action {
Action::Return(value) => value,
Evaluation::Return(value) => value,
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},
};
use super::{AbstractNode, Action, ExpectedType, Statement, Type};
use super::{AbstractNode, Evaluation, ExpectedType, Statement, Type};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct AsyncBlock {
@ -30,15 +30,19 @@ impl AbstractNode for AsyncBlock {
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 final_result = RwLock::new(Ok(Action::None));
let final_result = RwLock::new(Ok(Evaluation::None));
self.statements
.into_par_iter()
.enumerate()
.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 {
let get_write_lock = final_result.write();

View File

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

View File

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

View File

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

View File

@ -6,21 +6,21 @@ use crate::{
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)]
pub struct IfElse {
if_expression: ValueExpression,
if_expression: Expression,
if_block: WithPosition<Block>,
else_ifs: Vec<(ValueExpression, WithPosition<Block>)>,
else_ifs: Vec<(Expression, WithPosition<Block>)>,
else_block: Option<WithPosition<Block>>,
}
impl IfElse {
pub fn new(
if_expression: ValueExpression,
if_expression: Expression,
if_block: WithPosition<Block>,
else_ifs: Vec<(ValueExpression, WithPosition<Block>)>,
else_ifs: Vec<(Expression, WithPosition<Block>)>,
else_block: Option<WithPosition<Block>>,
) -> Self {
Self {
@ -51,7 +51,7 @@ impl AbstractNode for IfElse {
.map_err(|conflict| ValidationError::TypeCheck {
conflict,
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 {
@ -74,7 +74,7 @@ impl AbstractNode for IfElse {
.map_err(|conflict| ValidationError::TypeCheck {
conflict,
actual_position: self.if_block.node.last_statement().position(),
expected_position: self.if_expression.position(),
expected_position: Some(self.if_expression.position()),
})?;
} else {
return Err(ValidationError::ExpectedBoolean {
@ -87,10 +87,14 @@ impl AbstractNode for IfElse {
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 action = self.if_expression.run(context, _manage_memory)?;
let value = if let Action::Return(value) = action {
let action = self.if_expression.evaluate(context, _manage_memory)?;
let value = if let Evaluation::Return(value) = action {
value
} else {
return Err(RuntimeError::ValidationFailure(
@ -100,12 +104,12 @@ impl AbstractNode for IfElse {
if let ValueInner::Boolean(if_boolean) = value.inner().as_ref() {
if *if_boolean {
self.if_block.node.run(context, _manage_memory)
self.if_block.node.evaluate(context, _manage_memory)
} else {
for (expression, block) in self.else_ifs {
let expression_position = expression.position();
let action = expression.run(context, _manage_memory)?;
let value = if let Action::Return(value) = action {
let action = expression.evaluate(context, _manage_memory)?;
let value = if let Evaluation::Return(value) = action {
value
} else {
return Err(RuntimeError::ValidationFailure(
@ -115,7 +119,7 @@ impl AbstractNode for IfElse {
if let ValueInner::Boolean(else_if_boolean) = value.inner().as_ref() {
if *else_if_boolean {
return block.node.run(context, _manage_memory);
return block.node.evaluate(context, _manage_memory);
}
} else {
return Err(RuntimeError::ValidationFailure(
@ -128,9 +132,9 @@ impl AbstractNode for IfElse {
}
if let Some(else_statement) = self.else_block {
else_statement.node.run(context, _manage_memory)
else_statement.node.evaluate(context, _manage_memory)
} else {
Ok(Action::None)
Ok(Evaluation::None)
}
}
} else {
@ -163,17 +167,17 @@ mod tests {
fn simple_if() {
assert_eq!(
IfElse::new(
ValueExpression::Value(ValueNode::Boolean(true).with_position((0, 0))),
Block::new(vec![Statement::ValueExpression(ValueExpression::Value(
Expression::Value(ValueNode::Boolean(true).with_position((0, 0))),
Block::new(vec![Statement::ValueExpression(Expression::Value(
ValueNode::String("foo".to_string()).with_position((0, 0))
))])
.with_position((0, 0)),
Vec::with_capacity(0),
None
)
.run(&mut Context::new(None), true)
.evaluate(&mut Context::new(None), true)
.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},
};
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)]
pub struct ListIndex {
left: ValueExpression,
right: ValueExpression,
collection: Expression,
index: Expression,
}
impl ListIndex {
pub fn new(left: ValueExpression, right: ValueExpression) -> Self {
Self { left, right }
pub fn new(left: Expression, right: Expression) -> Self {
Self {
collection: left,
index: right,
}
}
}
impl AbstractNode for ListIndex {
fn validate(&self, context: &mut Context, _manage_memory: bool) -> Result<(), ValidationError> {
self.left.validate(context, _manage_memory)?;
self.right.validate(context, _manage_memory)?;
self.collection.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 {
Type::List => todo!(),
Type::ListOf(_) => todo!(),
Type::ListExact(_) => {
let right_type = self.right.expected_type(context)?;
if let Type::Integer = right_type {
match collection_type {
Type::List {
length: _,
item_type: _,
} => {
if index_type == Type::Integer {
Ok(())
} else {
Err(ValidationError::CannotIndexWith {
collection_type: left_type,
collection_position: self.left.position(),
index_type: right_type,
index_position: self.right.position(),
collection_type,
collection_position: self.collection.position(),
index_type,
index_position: self.index.position(),
})
}
}
Type::ListOf(_) => todo!(),
_ => Err(ValidationError::CannotIndex {
r#type: left_type,
position: self.left.position(),
r#type: collection_type,
position: self.collection.position(),
}),
}
}
fn run(self, context: &mut Context, _clear_variables: bool) -> Result<Action, RuntimeError> {
let left_position = self.left.position();
let left_action = self.left.run(context, _clear_variables)?;
let left_value = if let Action::Return(value) = left_action {
fn evaluate(
self,
context: &mut Context,
_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
} else {
return Err(RuntimeError::ValidationFailure(
ValidationError::InterpreterExpectedReturn(left_position),
));
};
let right_position = self.right.position();
let right_action = self.right.run(context, _clear_variables)?;
let right_value = if let Action::Return(value) = right_action {
let right_position = self.index.position();
let right_action = self.index.evaluate(context, _clear_variables)?;
let right_value = if let Evaluation::Return(value) = right_action {
value
} else {
return Err(RuntimeError::ValidationFailure(
@ -74,9 +82,9 @@ impl AbstractNode for ListIndex {
let found_item = list.get(index as usize);
if let Some(item) = found_item {
Ok(Action::Return(item.node.clone()))
Ok(Evaluation::Return(item.node.clone()))
} else {
Ok(Action::None)
Ok(Evaluation::None)
}
} else {
Err(RuntimeError::ValidationFailure(
@ -93,18 +101,18 @@ impl AbstractNode for ListIndex {
impl ExpectedType for ListIndex {
fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> {
let left_type = self.left.expected_type(_context)?;
let left_type = self.collection.expected_type(_context)?;
if let (
ValueExpression::Value(WithPosition {
Expression::Value(WithPosition {
node: ValueNode::List(expression_list),
..
}),
ValueExpression::Value(WithPosition {
Expression::Value(WithPosition {
node: ValueNode::Integer(index),
..
}),
) = (&self.left, &self.right)
) = (&self.collection, &self.index)
{
let expression = if let Some(expression) = expression_list.get(*index as usize) {
expression
@ -116,7 +124,7 @@ impl ExpectedType for ListIndex {
} else {
Err(ValidationError::CannotIndex {
r#type: left_type,
position: self.left.position(),
position: self.collection.position(),
})
}
}

View File

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

View File

@ -5,7 +5,7 @@ use crate::{
error::{RuntimeError, ValidationError},
};
use super::{AbstractNode, Action, Statement};
use super::{AbstractNode, Evaluation, Statement};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct Loop {
@ -31,15 +31,19 @@ impl AbstractNode for Loop {
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 {
for statement in &self.statements {
let action = statement.clone().run(_context, false)?;
let action = statement.clone().evaluate(_context, false)?;
match action {
Action::Return(_) => {}
Action::None => {}
Action::Break => return Ok(Action::Break),
Evaluation::Return(_) => {}
Evaluation::None => {}
Evaluation::Break => return Ok(Evaluation::Break),
}
}
}

View File

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

View File

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

View File

@ -6,9 +6,8 @@ use crate::{
};
use super::{
AbstractNode, Action, Assignment, AsyncBlock, Block, ExpectedType, IfElse, Loop,
SourcePosition, StructureDefinition, Type, TypeAssignment, ValueExpression, While,
WithPosition,
AbstractNode, Assignment, AsyncBlock, Block, Evaluation, ExpectedType, Expression, IfElse,
Loop, SourcePosition, StructureDefinition, Type, TypeAssignment, While, WithPosition,
};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
@ -21,7 +20,7 @@ pub enum Statement {
Loop(WithPosition<Loop>),
StructureDefinition(WithPosition<StructureDefinition>),
TypeAssignment(WithPosition<TypeAssignment>),
ValueExpression(ValueExpression),
ValueExpression(Expression),
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 {
Statement::Assignment(assignment) => assignment.node.run(context, manage_memory),
Statement::AsyncBlock(async_block) => async_block.node.run(context, manage_memory),
Statement::Block(block) => block.node.run(context, manage_memory),
Statement::Break(_) => Ok(Action::Break),
Statement::ValueExpression(expression) => expression.run(context, manage_memory),
Statement::IfElse(if_else) => if_else.node.run(context, manage_memory),
Statement::Loop(r#loop) => r#loop.node.run(context, manage_memory),
Statement::Assignment(assignment) => assignment.node.evaluate(context, manage_memory),
Statement::AsyncBlock(async_block) => async_block.node.evaluate(context, manage_memory),
Statement::Block(block) => block.node.evaluate(context, manage_memory),
Statement::Break(_) => Ok(Evaluation::Break),
Statement::ValueExpression(expression) => expression.evaluate(context, manage_memory),
Statement::IfElse(if_else) => if_else.node.evaluate(context, manage_memory),
Statement::Loop(r#loop) => r#loop.node.evaluate(context, manage_memory),
Statement::StructureDefinition(structure_definition) => {
structure_definition.node.run(context, manage_memory)
structure_definition.node.evaluate(context, manage_memory)
}
Statement::TypeAssignment(type_alias) => type_alias.node.run(context, manage_memory),
Statement::While(r#while) => r#while.node.run(context, manage_memory),
Statement::TypeAssignment(type_alias) => {
type_alias.node.evaluate(context, manage_memory)
}
Statement::While(r#while) => r#while.node.evaluate(context, manage_memory),
};
if manage_memory {

View File

@ -6,16 +6,16 @@ use crate::{
identifier::Identifier,
};
use super::{AbstractNode, Action, Type, WithPosition};
use super::{AbstractNode, Evaluation, Type, TypeConstructor, WithPosition};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct StructureDefinition {
name: Identifier,
fields: Vec<(Identifier, WithPosition<Type>)>,
fields: Vec<(Identifier, WithPosition<TypeConstructor>)>,
}
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 }
}
}
@ -29,14 +29,26 @@ impl AbstractNode for StructureDefinition {
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 {
name: self.name.clone(),
fields: self.fields,
fields,
};
context.set_type(self.name, struct_type)?;
Ok(Action::None)
Ok(Evaluation::None)
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -325,21 +325,23 @@ impl InterpreterError {
} => {
let TypeConflict { actual, expected } = conflict;
builder.add_labels([
Label::new((
self.source_id.clone(),
expected_position.0..expected_position.1,
))
.with_message(format!(
"Type {} established here.",
expected.fg(type_color)
)),
if let Some(position) = expected_position {
builder.add_label(
Label::new((self.source_id.clone(), position.0..position.1))
.with_message(format!(
"Type {} established here.",
expected.fg(type_color)
)),
)
}
builder.add_label(
Label::new((
self.source_id.clone(),
actual_position.0..actual_position.1,
))
.with_message(format!("Got type {} here.", actual.fg(type_color))),
]);
);
}
ValidationError::VariableNotFound {
identifier,
@ -390,6 +392,7 @@ impl InterpreterError {
ValidationError::ExpectedValue(_) => todo!(),
ValidationError::PropertyNotFound { .. } => todo!(),
ValidationError::WrongArguments { .. } => todo!(),
ValidationError::WrongTypeArgumentCount { .. } => todo!(),
ValidationError::ExpectedIntegerFloatOrString { actual, position } => {
builder = builder.with_message(format!(
"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 crate::{
abstract_tree::{AbstractNode, Action, Block, Type, WithPos, WithPosition},
abstract_tree::{AbstractNode, Block, Evaluation, Type, WithPosition},
context::Context,
error::{RuntimeError, ValidationError},
identifier::Identifier,
@ -52,14 +52,14 @@ impl Value {
}
pub fn function(
type_arguments: Vec<WithPosition<Type>>,
parameters: Vec<(Identifier, WithPosition<Type>)>,
return_type: WithPosition<Type>,
body: WithPosition<Block>,
type_parameters: Option<Vec<Identifier>>,
value_parameters: Vec<(Identifier, Type)>,
return_type: Type,
body: Block,
) -> Self {
Value(Arc::new(ValueInner::Function(Function {
type_parameters: type_arguments,
parameters,
type_parameters,
value_parameters,
return_type,
body,
})))
@ -129,19 +129,19 @@ impl Display for Value {
ValueInner::Range(_) => todo!(),
ValueInner::String(string) => write!(f, "{string}"),
ValueInner::Function(Function {
type_parameters: type_arguments,
parameters,
type_parameters,
value_parameters: parameters,
return_type,
body,
}) => {
if !type_arguments.is_empty() {
if let Some(type_parameters) = type_parameters {
write!(f, "(")?;
for (index, r#type) in type_arguments.into_iter().enumerate() {
if index == type_arguments.len() - 1 {
write!(f, "{}", r#type.node)?;
for (index, r#type) in type_parameters.into_iter().enumerate() {
if index == type_parameters.len() - 1 {
write!(f, "{}", r#type)?;
} else {
write!(f, "{} ", r#type.node)?;
write!(f, "{} ", r#type)?;
}
}
@ -151,10 +151,10 @@ impl Display for Value {
write!(f, "(")?;
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 } => {
write!(f, "{}\n{{", name.node)?;
@ -224,23 +224,19 @@ impl ValueInner {
ValueInner::Float(_) => Type::Float,
ValueInner::Integer(_) => Type::Integer,
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 {
types.push(value.node.r#type(context)?.with_position(value.position));
Type::List {
length: values.len(),
item_type: Box::new(item_type),
}
Type::ListExact(types)
}
ValueInner::Map(_) => Type::Map,
ValueInner::Range(_) => Type::Range,
ValueInner::String(_) => Type::String,
ValueInner::Function(function) => Type::Function {
parameter_types: function
.parameters
.iter()
.map(|(_, r#type)| r#type.clone())
.collect(),
type_parameters: None,
value_parameters: function.value_parameters.clone(),
return_type: Box::new(function.return_type.clone()),
},
ValueInner::Structure { name, .. } => {
@ -321,14 +317,14 @@ impl Ord for ValueInner {
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct Function {
type_parameters: Vec<WithPosition<Type>>,
parameters: Vec<(Identifier, WithPosition<Type>)>,
return_type: WithPosition<Type>,
body: WithPosition<Block>,
type_parameters: Option<Vec<Identifier>>,
value_parameters: Vec<(Identifier, Type)>,
return_type: Type,
body: Block,
}
impl Function {
pub fn type_parameters(&self) -> &Vec<WithPosition<Type>> {
pub fn type_parameters(&self) -> &Option<Vec<Identifier>> {
&self.type_parameters
}
@ -337,11 +333,12 @@ impl Function {
arguments: Vec<Value>,
context: &mut Context,
clear_variables: bool,
) -> Result<Action, RuntimeError> {
for ((identifier, _), value) in self.parameters.into_iter().zip(arguments.into_iter()) {
) -> Result<Evaluation, RuntimeError> {
for ((identifier, _), value) in self.value_parameters.into_iter().zip(arguments.into_iter())
{
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
},
actual_position: (128, 134).into(),
expected_position: (56, 59).into()
expected_position: Some((56, 59).into()),
},
position: (96, 153).into()
}]

View File

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

View File

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