1
0

Continue refactoring

This commit is contained in:
Jeff 2024-06-22 00:58:30 -04:00
parent 88906fb6d7
commit 4b89ea0e96
22 changed files with 227 additions and 156 deletions

View File

@ -27,7 +27,7 @@ impl As {
} }
impl AbstractNode for As { impl AbstractNode for As {
fn define_types(&self, context: &Context) -> Result<(), ValidationError> { fn define_types(&self, _: &Context) -> Result<(), ValidationError> {
Ok(()) Ok(())
} }

View File

@ -8,8 +8,8 @@ use crate::{
}; };
use super::{ use super::{
type_constructor::{RawTypeConstructor, TypeInvokationConstructor}, type_constructor::TypeInvokationConstructor, AbstractNode, Evaluation, Expression, Statement,
AbstractNode, Evaluation, Expression, Statement, Type, TypeConstructor, WithPosition, Type, TypeConstructor, WithPosition,
}; };
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
@ -74,14 +74,6 @@ impl AbstractNode for Assignment {
} }
fn validate(&self, context: &Context, manage_memory: bool) -> Result<(), ValidationError> { fn validate(&self, context: &Context, manage_memory: bool) -> Result<(), ValidationError> {
if let Some(TypeConstructor::Raw(WithPosition {
node: RawTypeConstructor::None,
position,
})) = &self.constructor
{
return Err(ValidationError::CannotAssignToNone(position.clone()));
}
let relevant_statement = self.statement.last_evaluated_statement(); let relevant_statement = self.statement.last_evaluated_statement();
let statement_type = if let Some(r#type) = relevant_statement.expected_type(context)? { let statement_type = if let Some(r#type) = relevant_statement.expected_type(context)? {
r#type r#type
@ -144,7 +136,7 @@ impl AbstractNode for Assignment {
.. ..
}) = function_type }) = function_type
{ {
if let Type::Generic { identifier, .. } = *return_type { if let Some(Type::Generic { identifier, .. }) = return_type.map(|r#box| *r#box) {
let returned_parameter = type_parameters let returned_parameter = type_parameters
.into_iter() .into_iter()
.find(|parameter| parameter == &identifier); .find(|parameter| parameter == &identifier);

View File

@ -163,10 +163,12 @@ impl AbstractNode for FunctionCall {
.. ..
} = function_type } = function_type
{ {
if let Type::Generic { let return_type = return_type.map(|r#box| *r#box);
if let Some(Type::Generic {
identifier: return_identifier, identifier: return_identifier,
.. ..
} = *return_type.clone() }) = &return_type
{ {
if let (Some(type_arguments), Some(type_parameters)) = if let (Some(type_arguments), Some(type_parameters)) =
(&self.type_arguments, &type_parameters) (&self.type_arguments, &type_parameters)
@ -174,7 +176,7 @@ impl AbstractNode for FunctionCall {
for (constructor, identifier) in for (constructor, identifier) in
type_arguments.into_iter().zip(type_parameters.into_iter()) type_arguments.into_iter().zip(type_parameters.into_iter())
{ {
if identifier == &return_identifier { if identifier == return_identifier {
let concrete_type = constructor.clone().construct(&context)?; let concrete_type = constructor.clone().construct(&context)?;
return Ok(Some(Type::Generic { return Ok(Some(Type::Generic {
@ -190,7 +192,7 @@ impl AbstractNode for FunctionCall {
.into_iter() .into_iter()
.zip(type_parameters.into_iter()) .zip(type_parameters.into_iter())
{ {
if identifier == return_identifier { if &identifier == return_identifier {
let concrete_type = let concrete_type =
if let Some(r#type) = expression.expected_type(context)? { if let Some(r#type) = expression.expected_type(context)? {
r#type r#type
@ -209,7 +211,7 @@ impl AbstractNode for FunctionCall {
} }
} }
Ok(Some(*return_type)) Ok(return_type)
} else { } else {
Err(ValidationError::ExpectedFunction { Err(ValidationError::ExpectedFunction {
actual: function_type, actual: function_type,

View File

@ -32,19 +32,25 @@ impl AbstractNode for ListIndex {
self.collection.validate(context, _manage_memory)?; self.collection.validate(context, _manage_memory)?;
self.index.validate(context, _manage_memory)?; self.index.validate(context, _manage_memory)?;
let collection_type = self.collection.expected_type(context)?; let collection_type = if let Some(r#type) = self.index.expected_type(context)? {
let index_type = self.index.expected_type(context)?; r#type
} else {
if index_type.is_none() { return Err(ValidationError::ExpectedExpression(
return Err(ValidationError::CannotIndexWithVoid(self.index.position())); self.collection.position(),
} ));
};
let index_type = if let Some(r#type) = self.index.expected_type(context)? {
r#type
} else {
return Err(ValidationError::ExpectedExpression(self.index.position()));
};
match collection_type { match collection_type {
Type::List { Type::List {
length: _, length: _,
item_type: _, item_type: _,
} => { } => {
if index_type == Some(Type::Integer) { if index_type == Type::Integer {
Ok(()) Ok(())
} else { } else {
Err(ValidationError::CannotIndexWith { Err(ValidationError::CannotIndexWith {
@ -69,8 +75,8 @@ impl AbstractNode for ListIndex {
_clear_variables: bool, _clear_variables: bool,
) -> Result<Option<Evaluation>, RuntimeError> { ) -> Result<Option<Evaluation>, RuntimeError> {
let left_position = self.collection.position(); let left_position = self.collection.position();
let left_action = self.collection.evaluate(context, _clear_variables)?; let left_evaluation = self.collection.evaluate(context, _clear_variables)?;
let left_value = if let Evaluation::Return(value) = left_action { let left_value = if let Some(Evaluation::Return(value)) = left_evaluation {
value value
} else { } else {
return Err(RuntimeError::ValidationFailure( return Err(RuntimeError::ValidationFailure(
@ -78,8 +84,8 @@ impl AbstractNode for ListIndex {
)); ));
}; };
let right_position = self.index.position(); let right_position = self.index.position();
let right_action = self.index.evaluate(context, _clear_variables)?; let right_evaluation = self.index.evaluate(context, _clear_variables)?;
let right_value = if let Evaluation::Return(value) = right_action { let right_value = if let Some(Evaluation::Return(value)) = right_evaluation {
value value
} else { } else {
return Err(RuntimeError::ValidationFailure( return Err(RuntimeError::ValidationFailure(
@ -93,7 +99,7 @@ impl AbstractNode for ListIndex {
if let Some(item) = found_item { if let Some(item) = found_item {
Ok(Some(Evaluation::Return(item.clone()))) Ok(Some(Evaluation::Return(item.clone())))
} else { } else {
Ok(Evaluation::Void) Ok(None)
} }
} else { } else {
Err(RuntimeError::ValidationFailure( Err(RuntimeError::ValidationFailure(
@ -108,7 +114,13 @@ impl AbstractNode for ListIndex {
} }
fn expected_type(&self, _context: &Context) -> Result<Option<Type>, ValidationError> { fn expected_type(&self, _context: &Context) -> Result<Option<Type>, ValidationError> {
let left_type = self.collection.expected_type(_context)?; let left_type = if let Some(r#type) = self.collection.expected_type(_context)? {
r#type
} else {
return Err(ValidationError::ExpectedExpression(
self.collection.position(),
));
};
if let ( if let (
Expression::Value(WithPosition { Expression::Value(WithPosition {
@ -124,7 +136,7 @@ impl AbstractNode for ListIndex {
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
} else { } else {
return Ok(Type::Void); return Ok(None);
}; };
expression.expected_type(_context) expression.expected_type(_context)

View File

@ -72,8 +72,16 @@ impl AbstractNode for Logic {
left.validate(context, _manage_memory)?; left.validate(context, _manage_memory)?;
right.validate(context, _manage_memory)?; right.validate(context, _manage_memory)?;
let left_type = left.expected_type(context)?; let left_type = if let Some(r#type) = left.expected_type(context)? {
let right_type = right.expected_type(context)?; r#type
} else {
return Err(ValidationError::ExpectedExpression(left.position()));
};
let right_type = if let Some(r#type) = right.expected_type(context)? {
r#type
} else {
return Err(ValidationError::ExpectedExpression(right.position()));
};
left_type left_type
.check(&right_type) .check(&right_type)
@ -89,8 +97,16 @@ impl AbstractNode for Logic {
left.validate(context, _manage_memory)?; left.validate(context, _manage_memory)?;
right.validate(context, _manage_memory)?; right.validate(context, _manage_memory)?;
let left_type = left.expected_type(context)?; let left_type = if let Some(r#type) = left.expected_type(context)? {
let right_type = right.expected_type(context)?; r#type
} else {
return Err(ValidationError::ExpectedExpression(left.position()));
};
let right_type = if let Some(r#type) = right.expected_type(context)? {
r#type
} else {
return Err(ValidationError::ExpectedExpression(right.position()));
};
if let Type::Boolean = left_type { if let Type::Boolean = left_type {
} else { } else {
@ -113,7 +129,11 @@ impl AbstractNode for Logic {
Logic::Not(expression) => { Logic::Not(expression) => {
expression.validate(context, _manage_memory)?; expression.validate(context, _manage_memory)?;
let expression_type = expression.expected_type(context)?; let expression_type = if let Some(r#type) = expression.expected_type(context)? {
r#type
} else {
return Err(ValidationError::ExpectedExpression(expression.position()));
};
if let Type::Boolean = expression_type { if let Type::Boolean = expression_type {
Ok(()) Ok(())
@ -134,8 +154,8 @@ impl AbstractNode for Logic {
) -> Result<Option<Evaluation>, RuntimeError> { ) -> Result<Option<Evaluation>, RuntimeError> {
let run_and_expect_value = |expression: Expression| -> Result<Value, RuntimeError> { let run_and_expect_value = |expression: Expression| -> Result<Value, RuntimeError> {
let expression_position = expression.position(); let expression_position = expression.position();
let action = expression.evaluate(&mut context.clone(), _manage_memory)?; let evaluation = expression.evaluate(&mut context.clone(), _manage_memory)?;
let value = if let Evaluation::Return(value) = action { let value = if let Some(Evaluation::Return(value)) = evaluation {
value value
} else { } else {
return Err(RuntimeError::ValidationFailure( return Err(RuntimeError::ValidationFailure(
@ -148,8 +168,8 @@ impl AbstractNode for Logic {
let run_and_expect_boolean = |expression: Expression| -> 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.evaluate(&mut context.clone(), _manage_memory)?; let evaluation = expression.evaluate(&mut context.clone(), _manage_memory)?;
let value = if let Evaluation::Return(value) = action { let value = if let Some(Evaluation::Return(value)) = evaluation {
value value
} else { } else {
return Err(RuntimeError::ValidationFailure( return Err(RuntimeError::ValidationFailure(
@ -251,7 +271,7 @@ mod tests {
Expression::Value(ValueNode::Integer(42).with_position((0, 0))) Expression::Value(ValueNode::Integer(42).with_position((0, 0)))
) )
.evaluate(&mut Context::new(None), true), .evaluate(&mut Context::new(None), true),
Ok(Evaluation::Return(Value::boolean(true))) Ok(Some(Evaluation::Return(Value::boolean(true))))
) )
} }
@ -263,7 +283,7 @@ mod tests {
Expression::Value(ValueNode::Integer(43).with_position((0, 0))) Expression::Value(ValueNode::Integer(43).with_position((0, 0)))
) )
.evaluate(&mut Context::new(None), true), .evaluate(&mut Context::new(None), true),
Ok(Evaluation::Return(Value::boolean(true))) Ok(Some(Evaluation::Return(Value::boolean(true))))
) )
} }
@ -275,7 +295,7 @@ mod tests {
Expression::Value(ValueNode::Integer(42).with_position((0, 0))) Expression::Value(ValueNode::Integer(42).with_position((0, 0)))
) )
.evaluate(&mut Context::new(None), true), .evaluate(&mut Context::new(None), true),
Ok(Evaluation::Return(Value::boolean(true))) Ok(Some(Evaluation::Return(Value::boolean(true))))
) )
} }
@ -287,7 +307,7 @@ mod tests {
Expression::Value(ValueNode::Integer(43).with_position((0, 0))) Expression::Value(ValueNode::Integer(43).with_position((0, 0)))
) )
.evaluate(&mut Context::new(None), true), .evaluate(&mut Context::new(None), true),
Ok(Evaluation::Return(Value::boolean(true))) Ok(Some(Evaluation::Return(Value::boolean(true))))
) )
} }
@ -299,7 +319,7 @@ mod tests {
Expression::Value(ValueNode::Integer(41).with_position((0, 0))) Expression::Value(ValueNode::Integer(41).with_position((0, 0)))
) )
.evaluate(&mut Context::new(None), true), .evaluate(&mut Context::new(None), true),
Ok(Evaluation::Return(Value::boolean(true))) Ok(Some(Evaluation::Return(Value::boolean(true))))
); );
assert_eq!( assert_eq!(
@ -308,7 +328,7 @@ mod tests {
Expression::Value(ValueNode::Integer(42).with_position((0, 0))), Expression::Value(ValueNode::Integer(42).with_position((0, 0))),
) )
.evaluate(&mut Context::new(None), true), .evaluate(&mut Context::new(None), true),
Ok(Evaluation::Return(Value::boolean(true))) Ok(Some(Evaluation::Return(Value::boolean(true))))
); );
} }
@ -320,7 +340,7 @@ mod tests {
Expression::Value(ValueNode::Integer(42).with_position((0, 0))), Expression::Value(ValueNode::Integer(42).with_position((0, 0))),
) )
.evaluate(&mut Context::new(None), true), .evaluate(&mut Context::new(None), true),
Ok(Evaluation::Return(Value::boolean(true))) Ok(Some(Evaluation::Return(Value::boolean(true))))
); );
assert_eq!( assert_eq!(
@ -329,7 +349,7 @@ mod tests {
Expression::Value(ValueNode::Integer(42).with_position((0, 0))), Expression::Value(ValueNode::Integer(42).with_position((0, 0))),
) )
.evaluate(&mut Context::new(None), true), .evaluate(&mut Context::new(None), true),
Ok(Evaluation::Return(Value::boolean(true))) Ok(Some(Evaluation::Return(Value::boolean(true))))
); );
} }
@ -341,7 +361,7 @@ mod tests {
Expression::Value(ValueNode::Boolean(true).with_position((0, 0))), Expression::Value(ValueNode::Boolean(true).with_position((0, 0))),
) )
.evaluate(&mut Context::new(None), true), .evaluate(&mut Context::new(None), true),
Ok(Evaluation::Return(Value::boolean(true))) Ok(Some(Evaluation::Return(Value::boolean(true))))
) )
} }
@ -353,7 +373,7 @@ mod tests {
Expression::Value(ValueNode::Boolean(false).with_position((0, 0))), Expression::Value(ValueNode::Boolean(false).with_position((0, 0))),
) )
.evaluate(&mut Context::new(None), true), .evaluate(&mut Context::new(None), true),
Ok(Evaluation::Return(Value::boolean(true))) Ok(Some(Evaluation::Return(Value::boolean(true))))
) )
} }
@ -364,7 +384,7 @@ mod tests {
ValueNode::Boolean(false).with_position((0, 0)) ValueNode::Boolean(false).with_position((0, 0))
)) ))
.evaluate(&mut Context::new(None), true), .evaluate(&mut Context::new(None), true),
Ok(Evaluation::Return(Value::boolean(true))) Ok(Some(Evaluation::Return(Value::boolean(true))))
) )
} }
} }

View File

@ -45,7 +45,7 @@ impl AbstractNode for Loop {
) -> Result<Option<Evaluation>, RuntimeError> { ) -> Result<Option<Evaluation>, RuntimeError> {
loop { loop {
for statement in &self.statements { for statement in &self.statements {
let run = statement.clone().run(_context, false)?; let run = statement.clone().evaluate(_context, false)?;
if let Some(Evaluation::Break) = run { if let Some(Evaluation::Break) = run {
return Ok(run); return Ok(run);

View File

@ -39,8 +39,8 @@ impl AbstractNode for MapIndex {
_manage_memory: bool, _manage_memory: bool,
) -> Result<Option<Evaluation>, RuntimeError> { ) -> Result<Option<Evaluation>, RuntimeError> {
let collection_position = self.collection.position(); let collection_position = self.collection.position();
let action = self.collection.evaluate(context, _manage_memory)?; let evaluation = self.collection.evaluate(context, _manage_memory)?;
let collection = if let Evaluation::Return(value) = action { let collection = if let Some(Evaluation::Return(value)) = evaluation {
value value
} else { } else {
return Err(RuntimeError::ValidationFailure( return Err(RuntimeError::ValidationFailure(
@ -51,11 +51,12 @@ impl AbstractNode for MapIndex {
if let (ValueInner::Map(map), Expression::Identifier(index)) = if let (ValueInner::Map(map), Expression::Identifier(index)) =
(collection.inner().as_ref(), self.index) (collection.inner().as_ref(), self.index)
{ {
let evaluation = map let eval_option = map
.get(&index.node) .get(&index.node)
.map(|value| Some(Evaluation::Return(value.clone()))); .cloned()
.map(|value| Evaluation::Return(value));
Ok(evaluation) Ok(eval_option)
} else { } else {
Err(RuntimeError::ValidationFailure( Err(RuntimeError::ValidationFailure(
ValidationError::CannotIndex { ValidationError::CannotIndex {
@ -111,7 +112,7 @@ impl AbstractNode for MapIndex {
} }
} }
return Ok(Type::Void); return Ok(None);
} }
if let ( if let (
@ -131,12 +132,20 @@ impl AbstractNode for MapIndex {
}) { }) {
type_result type_result
} else { } else {
Ok(Type::Void) Ok(None)
}; };
} }
let collection_type = if let Some(r#type) = self.collection.expected_type(context)? {
r#type
} else {
return Err(ValidationError::ExpectedExpression(
self.collection.position(),
));
};
Err(ValidationError::CannotIndex { Err(ValidationError::CannotIndex {
r#type: self.collection.expected_type(context)?, r#type: collection_type,
position: self.collection.position(), position: self.collection.position(),
}) })
} }

View File

@ -47,25 +47,30 @@ impl AbstractNode for Math {
fn validate(&self, context: &Context, _manage_memory: bool) -> Result<(), ValidationError> { fn validate(&self, context: &Context, _manage_memory: bool) -> Result<(), ValidationError> {
match self { match self {
Math::Add(left, right) => { Math::Add(left, right) => {
let left_position = left.position(); let left_type = if let Some(r#type) = left.expected_type(context)? {
let left_type = left.expected_type(context)?; r#type
} else {
return Err(ValidationError::ExpectedExpression(left.position()));
};
let right_type = if let Some(r#type) = right.expected_type(context)? {
r#type
} else {
return Err(ValidationError::ExpectedExpression(right.position()));
};
if let Type::Integer | Type::Float | Type::String = left_type { if let Type::Integer | Type::Float | Type::String = left_type {
let right_position = right.position();
let right_type = right.expected_type(context)?;
if let Type::Integer | Type::Float | Type::String = right_type { if let Type::Integer | Type::Float | Type::String = right_type {
Ok(()) Ok(())
} else { } else {
Err(ValidationError::ExpectedIntegerFloatOrString { Err(ValidationError::ExpectedIntegerFloatOrString {
actual: right_type, actual: right_type,
position: right_position, position: right.position(),
}) })
} }
} else { } else {
Err(ValidationError::ExpectedIntegerFloatOrString { Err(ValidationError::ExpectedIntegerFloatOrString {
actual: left_type, actual: left_type,
position: left_position, position: left.position(),
}) })
} }
} }
@ -73,20 +78,25 @@ impl AbstractNode for Math {
| Math::Multiply(left, right) | Math::Multiply(left, right)
| Math::Divide(left, right) | Math::Divide(left, right)
| Math::Modulo(left, right) => { | Math::Modulo(left, right) => {
let left_position = left.position(); let left_type = if let Some(r#type) = left.expected_type(context)? {
let left_type = left.expected_type(context)?; r#type
} else {
return Err(ValidationError::ExpectedExpression(left.position()));
};
let right_type = if let Some(r#type) = right.expected_type(context)? {
r#type
} else {
return Err(ValidationError::ExpectedExpression(right.position()));
};
if let Type::Integer | Type::Float = left_type { if let Type::Integer | Type::Float = left_type {
let right_position = right.position();
let right_type = right.expected_type(context)?;
if let Type::Integer | Type::Float = right_type { if let Type::Integer | Type::Float = right_type {
Ok(()) Ok(())
} else { } else {
Err(ValidationError::ExpectedIntegerOrFloat(right_position)) Err(ValidationError::ExpectedIntegerOrFloat(right.position()))
} }
} else { } else {
Err(ValidationError::ExpectedIntegerOrFloat(left_position)) Err(ValidationError::ExpectedIntegerOrFloat(left.position()))
} }
} }
} }
@ -99,8 +109,8 @@ impl AbstractNode for Math {
) -> Result<Option<Evaluation>, RuntimeError> { ) -> Result<Option<Evaluation>, RuntimeError> {
let run_and_expect_value = let run_and_expect_value =
|position: SourcePosition, expression: Expression| -> Result<Value, RuntimeError> { |position: SourcePosition, expression: Expression| -> Result<Value, RuntimeError> {
let action = expression.evaluate(&mut _context.clone(), _clear_variables)?; let evaluation = expression.evaluate(&mut _context.clone(), _clear_variables)?;
let value = if let Evaluation::Return(value) = action { let value = if let Some(Evaluation::Return(value)) = evaluation {
value value
} else { } else {
return Err(RuntimeError::ValidationFailure( return Err(RuntimeError::ValidationFailure(
@ -326,8 +336,16 @@ impl AbstractNode for Math {
| Math::Multiply(left, right) | Math::Multiply(left, right)
| Math::Divide(left, right) | Math::Divide(left, right)
| Math::Modulo(left, right) => { | Math::Modulo(left, right) => {
let left_type = left.expected_type(_context)?; let left_type = if let Some(r#type) = left.expected_type(_context)? {
let right_type = right.expected_type(_context)?; r#type
} else {
return Err(ValidationError::ExpectedExpression(left.position()));
};
let right_type = if let Some(r#type) = right.expected_type(_context)? {
r#type
} else {
return Err(ValidationError::ExpectedExpression(right.position()));
};
if let Type::Float = left_type { if let Type::Float = left_type {
return Ok(Some(Type::Float)); return Ok(Some(Type::Float));
@ -337,7 +355,7 @@ impl AbstractNode for Math {
return Ok(Some(Type::Float)); return Ok(Some(Type::Float));
} }
Ok(left_type) Ok(Some(left_type))
} }
} }
} }

View File

@ -147,12 +147,12 @@ impl AbstractTree {
for statement in self.0 { for statement in self.0 {
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(evaluation) => match evaluation { Ok(evaluation) => match evaluation {
Some(Evaluation::Return(value)) => previous_value = Some(value), Some(Evaluation::Return(value)) => previous_value = Some(value),
Some(Evaluation::Void) | None => previous_value = None, None => previous_value = None,
_ => {} _ => {}
}, },
Err(runtime_error) => { Err(runtime_error) => {

View File

@ -59,7 +59,7 @@ impl AbstractNode for Statement {
Statement::Block(block) => block.node.define_types(_context), Statement::Block(block) => block.node.define_types(_context),
Statement::AsyncBlock(async_block) => async_block.node.define_types(_context), Statement::AsyncBlock(async_block) => async_block.node.define_types(_context),
Statement::Assignment(assignment) => assignment.node.define_types(_context), Statement::Assignment(assignment) => assignment.node.define_types(_context),
Statement::Break(_) => Ok(None), Statement::Break(_) => Ok(()),
Statement::Loop(r#loop) => r#loop.node.define_types(_context), Statement::Loop(r#loop) => r#loop.node.define_types(_context),
Statement::StructureDefinition(struct_definition) => { Statement::StructureDefinition(struct_definition) => {
struct_definition.node.define_types(_context) struct_definition.node.define_types(_context)

View File

@ -24,10 +24,10 @@ impl AbstractNode for StructureDefinition {
fn define_types(&self, context: &Context) -> Result<(), ValidationError> { fn define_types(&self, context: &Context) -> Result<(), ValidationError> {
let mut fields = Vec::with_capacity(self.fields.len()); let mut fields = Vec::with_capacity(self.fields.len());
for (identifier, constructor) in self.fields { for (identifier, constructor) in &self.fields {
let r#type = constructor.construct(&context)?; let r#type = constructor.construct(&context)?;
fields.push((identifier, r#type)); fields.push((identifier.clone(), r#type));
} }
let struct_type = Type::Structure { let struct_type = Type::Structure {
@ -35,12 +35,12 @@ impl AbstractNode for StructureDefinition {
fields, fields,
}; };
context.set_type(self.name, struct_type)?; context.set_type(self.name.clone(), struct_type)?;
Ok(None) Ok(())
} }
fn validate(&self, context: &Context, manage_memory: bool) -> Result<(), ValidationError> { fn validate(&self, _: &Context, _: bool) -> Result<(), ValidationError> {
Ok(()) Ok(())
} }
@ -67,7 +67,7 @@ impl AbstractNode for StructureDefinition {
Ok(None) Ok(None)
} }
fn expected_type(&self, context: &Context) -> Result<Option<Type>, ValidationError> { fn expected_type(&self, _: &Context) -> Result<Option<Type>, ValidationError> {
Ok(None) Ok(None)
} }
} }

View File

@ -18,7 +18,7 @@ pub enum Type {
Function { Function {
type_parameters: Option<Vec<Identifier>>, type_parameters: Option<Vec<Identifier>>,
value_parameters: Vec<Type>, value_parameters: Vec<Type>,
return_type: Box<Type>, return_type: Option<Box<Type>>,
}, },
Generic { Generic {
identifier: Identifier, identifier: Identifier,
@ -48,7 +48,6 @@ impl Type {
| (Type::Float, Type::Float) | (Type::Float, Type::Float)
| (Type::Integer, Type::Integer) | (Type::Integer, Type::Integer)
| (Type::Map, Type::Map) | (Type::Map, Type::Map)
| (Type::Void, Type::Void)
| (Type::Range, Type::Range) | (Type::Range, Type::Range)
| (Type::String, Type::String) => return Ok(()), | (Type::String, Type::String) => return Ok(()),
( (
@ -239,7 +238,6 @@ impl Display for Type {
Type::List { length, item_type } => write!(f, "[{length}; {}]", item_type), Type::List { length, item_type } => write!(f, "[{length}; {}]", item_type),
Type::ListOf(item_type) => write!(f, "list({})", item_type), Type::ListOf(item_type) => write!(f, "list({})", item_type),
Type::Map => write!(f, "map"), Type::Map => write!(f, "map"),
Type::Void => 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 {
@ -261,7 +259,13 @@ impl Display for Type {
write!(f, "{type}")?; write!(f, "{type}")?;
} }
write!(f, ") : {}", return_type) write!(f, ")")?;
if let Some(r#type) = return_type {
write!(f, " -> {}", r#type)
} else {
Ok(())
}
} }
Type::Structure { name, .. } => write!(f, "{name}"), Type::Structure { name, .. } => write!(f, "{name}"),
} }
@ -295,7 +299,6 @@ mod tests {
); );
assert_eq!(Type::Map.check(&Type::Map), Ok(())); assert_eq!(Type::Map.check(&Type::Map), Ok(()));
assert_eq!(Type::Void.check(&Type::Void), Ok(()));
assert_eq!(Type::Range.check(&Type::Range), Ok(())); assert_eq!(Type::Range.check(&Type::Range), Ok(()));
assert_eq!(Type::String.check(&Type::String), Ok(())); assert_eq!(Type::String.check(&Type::String), Ok(()));
} }
@ -321,7 +324,6 @@ mod tests {
); );
let types = [ let types = [
Type::Any,
Type::Boolean, Type::Boolean,
Type::Float, Type::Float,
Type::Integer, Type::Integer,
@ -331,18 +333,18 @@ mod tests {
}, },
Type::ListOf(Box::new(Type::Boolean)), Type::ListOf(Box::new(Type::Boolean)),
Type::Map, Type::Map,
Type::Void,
Type::Range, Type::Range,
Type::String, Type::String,
]; ];
for (left, right) in types.iter().zip(types.iter()) { for left in types.clone() {
for right in types.clone() {
if left == right { if left == right {
continue; continue;
} }
assert_eq!( assert_eq!(
left.check(right), left.check(&right),
Err(TypeConflict { Err(TypeConflict {
actual: right.clone(), actual: right.clone(),
expected: left.clone() expected: left.clone()
@ -350,6 +352,7 @@ mod tests {
); );
} }
} }
}
#[test] #[test]
fn check_list_types() { fn check_list_types() {

View File

@ -27,24 +27,20 @@ impl AbstractNode for TypeAlias {
fn define_types(&self, context: &Context) -> Result<(), ValidationError> { fn define_types(&self, context: &Context) -> Result<(), ValidationError> {
let r#type = self.constructor.construct(&context)?; let r#type = self.constructor.construct(&context)?;
context.set_type(self.identifier.node, r#type)?; context.set_type(self.identifier.node.clone(), r#type)?;
Ok(()) Ok(())
} }
fn validate(&self, context: &Context, manage_memory: bool) -> Result<(), ValidationError> { fn validate(&self, _: &Context, _: bool) -> Result<(), ValidationError> {
Ok(()) Ok(())
} }
fn evaluate( fn evaluate(self, _: &Context, _: bool) -> Result<Option<Evaluation>, RuntimeError> {
self,
context: &Context,
manage_memory: bool,
) -> Result<Option<Evaluation>, RuntimeError> {
Ok(None) Ok(None)
} }
fn expected_type(&self, context: &Context) -> Result<Option<Type>, ValidationError> { fn expected_type(&self, _: &Context) -> Result<Option<Type>, ValidationError> {
Ok(None) Ok(None)
} }
} }

View File

@ -23,7 +23,6 @@ pub enum RawTypeConstructor {
Float, Float,
Integer, Integer,
Map, Map,
None,
Range, Range,
String, String,
} }
@ -144,7 +143,11 @@ impl TypeConstructor {
value_parameters.push(r#type); value_parameters.push(r#type);
} }
let return_type = Box::new(return_type.construct(&context)?); let return_type = if let Some(constructor) = return_type {
Some(Box::new(constructor.construct(context)?))
} else {
None
};
Type::Function { Type::Function {
type_parameters, type_parameters,
@ -172,7 +175,6 @@ impl TypeConstructor {
RawTypeConstructor::Float => Type::Float, RawTypeConstructor::Float => Type::Float,
RawTypeConstructor::Integer => Type::Integer, RawTypeConstructor::Integer => Type::Integer,
RawTypeConstructor::Map => Type::Map, RawTypeConstructor::Map => Type::Map,
RawTypeConstructor::None => Type::Void,
RawTypeConstructor::Range => Type::Range, RawTypeConstructor::Range => Type::Range,
RawTypeConstructor::String => Type::String, RawTypeConstructor::String => Type::String,
}, },
@ -199,7 +201,7 @@ pub struct EnumTypeConstructor {
pub struct FunctionTypeConstructor { pub struct FunctionTypeConstructor {
pub type_parameters: Option<Vec<WithPosition<Identifier>>>, pub type_parameters: Option<Vec<WithPosition<Identifier>>>,
pub value_parameters: Vec<TypeConstructor>, pub value_parameters: Vec<TypeConstructor>,
pub return_type: Box<TypeConstructor>, pub return_type: Option<Box<TypeConstructor>>,
} }
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]

View File

@ -34,7 +34,7 @@ pub enum ValueNode {
Function { Function {
type_parameters: Option<Vec<Identifier>>, type_parameters: Option<Vec<Identifier>>,
value_parameters: Vec<(Identifier, TypeConstructor)>, value_parameters: Vec<(Identifier, TypeConstructor)>,
return_type: TypeConstructor, return_type: Option<TypeConstructor>,
body: WithPosition<Block>, body: WithPosition<Block>,
}, },
} }
@ -64,12 +64,7 @@ impl AbstractNode for ValueNode {
expression.define_types(_context)?; expression.define_types(_context)?;
} }
} }
ValueNode::Function { ValueNode::Function { body, .. } => {
type_parameters,
value_parameters,
return_type,
body,
} => {
body.node.define_types(_context)?; body.node.define_types(_context)?;
} }
_ => {} _ => {}
@ -156,20 +151,23 @@ impl AbstractNode for ValueNode {
body.node.validate(&mut function_context, _manage_memory)?; body.node.validate(&mut function_context, _manage_memory)?;
let (expected_return_type, expected_position) = if let Some(constructor) = return_type {
(constructor.construct(context)?, constructor.position())
} else {
return Err(ValidationError::ExpectedExpression(body.position));
};
let actual_return_type = if let Some(r#type) = body.node.expected_type(context)? { let actual_return_type = if let Some(r#type) = body.node.expected_type(context)? {
r#type r#type
} else { } else {
return Err(ValidationError::ExpectedExpression(body.position)); return Err(ValidationError::ExpectedExpression(body.position));
}; };
return_type expected_return_type
.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: Some(return_type.position()), expected_position: Some(expected_position),
})?; })?;
return Ok(()); return Ok(());
@ -316,7 +314,11 @@ impl AbstractNode for ValueNode {
} }
} }
let return_type = return_type.construct(&function_context)?; let return_type = if let Some(constructor) = return_type {
Some(constructor.construct(&function_context)?)
} else {
None
};
Value::function(type_parameters, value_parameters, return_type, body.node) Value::function(type_parameters, value_parameters, return_type, body.node)
} }
@ -398,12 +400,16 @@ impl AbstractNode for ValueNode {
.map(|identifier| identifier.clone()) .map(|identifier| identifier.clone())
.collect() .collect()
}); });
let return_type = return_type.clone().construct(&context)?; let return_type = if let Some(constructor) = return_type {
Some(Box::new(constructor.construct(context)?))
} else {
None
};
Type::Function { Type::Function {
type_parameters, type_parameters,
value_parameters: value_parameter_types, value_parameters: value_parameter_types,
return_type: Box::new(return_type), return_type,
} }
} }
ValueNode::Structure { ValueNode::Structure {

View File

@ -52,12 +52,12 @@ impl AbstractNode for While {
) -> Result<Option<Evaluation>, RuntimeError> { ) -> Result<Option<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 let evaluation = self
.expression .expression
.clone() .clone()
.evaluate(&mut _context.clone(), false)?; .evaluate(&mut _context.clone(), false)?;
if let Evaluation::Return(value) = action { if let Some(Evaluation::Return(value)) = evaluation {
Ok(value) Ok(value)
} else { } else {
Err(RuntimeError::ValidationFailure( Err(RuntimeError::ValidationFailure(
@ -68,7 +68,7 @@ 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 evaluation = statement.clone().run(&mut _context.clone(), false)?; let evaluation = statement.clone().evaluate(&mut _context.clone(), false)?;
if let Some(Evaluation::Break) = evaluation { if let Some(Evaluation::Break) = evaluation {
return Ok(evaluation); return Ok(evaluation);

View File

@ -455,7 +455,6 @@ impl InterpreterError {
} }
} }
ValidationError::EnumVariantNotFound { .. } => todo!(), ValidationError::EnumVariantNotFound { .. } => todo!(),
ValidationError::CannotIndexWithVoid(_) => todo!(),
} }
} }

View File

@ -84,7 +84,6 @@ pub fn parser<'src>(
just(Token::Keyword(Keyword::Float)).to(RawTypeConstructor::Float), just(Token::Keyword(Keyword::Float)).to(RawTypeConstructor::Float),
just(Token::Keyword(Keyword::Int)).to(RawTypeConstructor::Integer), just(Token::Keyword(Keyword::Int)).to(RawTypeConstructor::Integer),
just(Token::Keyword(Keyword::Map)).to(RawTypeConstructor::Map), just(Token::Keyword(Keyword::Map)).to(RawTypeConstructor::Map),
just(Token::Keyword(Keyword::None)).to(RawTypeConstructor::None),
just(Token::Keyword(Keyword::Range)).to(RawTypeConstructor::Range), just(Token::Keyword(Keyword::Range)).to(RawTypeConstructor::Range),
just(Token::Keyword(Keyword::Str)).to(RawTypeConstructor::String), just(Token::Keyword(Keyword::Str)).to(RawTypeConstructor::String),
)) ))
@ -115,15 +114,18 @@ pub fn parser<'src>(
just(Token::Symbol(Symbol::ParenClose)), just(Token::Symbol(Symbol::ParenClose)),
), ),
) )
.then_ignore(just(Token::Symbol(Symbol::SkinnyArrow))) .then(
.then(type_constructor.clone()) just(Token::Symbol(Symbol::SkinnyArrow))
.ignore_then(type_constructor.clone())
.or_not(),
)
.map_with( .map_with(
|((type_parameters, value_parameters), return_type), state| { |((type_parameters, value_parameters), return_type), state| {
TypeConstructor::Function( TypeConstructor::Function(
FunctionTypeConstructor { FunctionTypeConstructor {
type_parameters, type_parameters,
value_parameters, value_parameters,
return_type: Box::new(return_type), return_type: return_type.map(|r#type| Box::new(r#type)),
} }
.with_position(state.span()), .with_position(state.span()),
) )
@ -282,8 +284,11 @@ pub fn parser<'src>(
just(Token::Symbol(Symbol::ParenClose)), just(Token::Symbol(Symbol::ParenClose)),
), ),
) )
.then_ignore(just(Token::Symbol(Symbol::SkinnyArrow))) .then(
.then(type_constructor.clone()) just(Token::Symbol(Symbol::SkinnyArrow))
.ignore_then(type_constructor.clone())
.or_not(),
)
.then(block.clone()) .then(block.clone())
.map_with( .map_with(
|(((type_parameters, value_parameters), return_type), body), state| { |(((type_parameters, value_parameters), return_type), body), state| {

View File

@ -438,12 +438,12 @@ fn function_type() {
value_parameters: vec![TypeConstructor::Raw( value_parameters: vec![TypeConstructor::Raw(
RawTypeConstructor::Integer.with_position((19, 22)) RawTypeConstructor::Integer.with_position((19, 22))
)], )],
return_type: Box::new(TypeConstructor::Invokation( return_type: Some(Box::new(TypeConstructor::Invokation(
TypeInvokationConstructor { TypeInvokationConstructor {
identifier: Identifier::new("T").with_position((27, 28)), identifier: Identifier::new("T").with_position((27, 28)),
type_arguments: None type_arguments: None
} }
)) )))
} }
.with_position((11, 28)) .with_position((11, 28))
) )
@ -505,9 +505,9 @@ fn function() {
ValueNode::Function { ValueNode::Function {
type_parameters: None, type_parameters: None,
value_parameters: vec![], value_parameters: vec![],
return_type: TypeConstructor::Raw( return_type: Some(TypeConstructor::Raw(
RawTypeConstructor::Integer.with_position((9, 12)) RawTypeConstructor::Integer.with_position((9, 12))
), )),
body: Block::new(vec![Statement::Expression(Expression::Value( body: Block::new(vec![Statement::Expression(Expression::Value(
ValueNode::Integer(0).with_position((15, 16)) ValueNode::Integer(0).with_position((15, 16))
))]) ))])
@ -526,9 +526,9 @@ fn function() {
Identifier::new("x"), Identifier::new("x"),
TypeConstructor::Raw(RawTypeConstructor::Integer.with_position((7, 10))) TypeConstructor::Raw(RawTypeConstructor::Integer.with_position((7, 10)))
)], )],
return_type: TypeConstructor::Raw( return_type: Some(TypeConstructor::Raw(
RawTypeConstructor::Integer.with_position((15, 18)) RawTypeConstructor::Integer.with_position((15, 18))
), )),
body: Block::new(vec![Statement::Expression(Expression::Identifier( body: Block::new(vec![Statement::Expression(Expression::Identifier(
Identifier::new("x").with_position((21, 22)) Identifier::new("x").with_position((21, 22))
))]) ))])
@ -562,10 +562,10 @@ fn function_with_type_arguments() {
}) })
) )
], ],
return_type: TypeConstructor::Invokation(TypeInvokationConstructor { return_type: Some(TypeConstructor::Invokation(TypeInvokationConstructor {
identifier: Identifier::new("T").with_position((26, 27)), identifier: Identifier::new("T").with_position((26, 27)),
type_arguments: None, type_arguments: None,
}), })),
body: Block::new(vec![Statement::Expression(Expression::Identifier( body: Block::new(vec![Statement::Expression(Expression::Identifier(
Identifier::new("x").with_position((30, 31)) Identifier::new("x").with_position((30, 31))
))]) ))])

View File

@ -71,7 +71,7 @@ impl Value {
pub fn function( pub fn function(
type_parameters: Option<Vec<Identifier>>, type_parameters: Option<Vec<Identifier>>,
value_parameters: Vec<(Identifier, Type)>, value_parameters: Vec<(Identifier, Type)>,
return_type: Type, return_type: Option<Type>,
body: Block, body: Block,
) -> Self { ) -> Self {
Value(Arc::new(ValueInner::Function(Function { Value(Arc::new(ValueInner::Function(Function {
@ -188,7 +188,13 @@ impl Display for Value {
write!(f, "{identifier}: {}", r#type)?; write!(f, "{identifier}: {}", r#type)?;
} }
write!(f, "): {} {:?}", return_type, body) write!(f, ")")?;
if let Some(return_type) = return_type {
write!(f, "-> {return_type}")?
}
write!(f, " {{ {body:?} }}")
} }
ValueInner::Structure { name, fields } => { ValueInner::Structure { name, fields } => {
write!(f, "{}\n{{", name.node)?; write!(f, "{}\n{{", name.node)?;
@ -590,11 +596,12 @@ impl ValueInner {
.map(|(_, r#type)| r#type) .map(|(_, r#type)| r#type)
.cloned() .cloned()
.collect(); .collect();
let return_type = function.return_type.clone().map(|r#type| Box::new(r#type));
Type::Function { Type::Function {
type_parameters: function.type_parameters().clone(), type_parameters: function.type_parameters().clone(),
value_parameters, value_parameters,
return_type: Box::new(function.return_type.clone()), return_type,
} }
} }
ValueInner::Structure { name, .. } => { ValueInner::Structure { name, .. } => {
@ -704,7 +711,7 @@ impl Ord for ValueInner {
pub struct Function { pub struct Function {
type_parameters: Option<Vec<Identifier>>, type_parameters: Option<Vec<Identifier>>,
value_parameters: Vec<(Identifier, Type)>, value_parameters: Vec<(Identifier, Type)>,
return_type: Type, return_type: Option<Type>,
body: Block, body: Block,
} }

View File

@ -48,7 +48,7 @@ fn function_variable() {
Ok(Some(Value::function( Ok(Some(Value::function(
None, None,
vec![(Identifier::new("x"), Type::Integer)], vec![(Identifier::new("x"), Type::Integer)],
Type::Integer, Some(Type::Integer),
Block::new(vec![Statement::Expression(Expression::Identifier( Block::new(vec![Statement::Expression(Expression::Identifier(
Identifier::new("x").with_position((30, 31)) Identifier::new("x").with_position((30, 31))
))]) ))])

View File

@ -3,7 +3,7 @@ io = {
READ_LINE READ_LINE
} }
write_line = fn (output: any) -> none { write_line = fn (output: any) {
WRITE_LINE output WRITE_LINE output
} }
} }