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 {
fn define_types(&self, context: &Context) -> Result<(), ValidationError> {
fn define_types(&self, _: &Context) -> Result<(), ValidationError> {
Ok(())
}

View File

@ -8,8 +8,8 @@ use crate::{
};
use super::{
type_constructor::{RawTypeConstructor, TypeInvokationConstructor},
AbstractNode, Evaluation, Expression, Statement, Type, TypeConstructor, WithPosition,
type_constructor::TypeInvokationConstructor, AbstractNode, Evaluation, Expression, Statement,
Type, TypeConstructor, WithPosition,
};
#[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> {
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 statement_type = if let Some(r#type) = relevant_statement.expected_type(context)? {
r#type
@ -144,7 +136,7 @@ impl AbstractNode for Assignment {
..
}) = 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
.into_iter()
.find(|parameter| parameter == &identifier);

View File

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

View File

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

View File

@ -72,8 +72,16 @@ impl AbstractNode for Logic {
left.validate(context, _manage_memory)?;
right.validate(context, _manage_memory)?;
let left_type = left.expected_type(context)?;
let right_type = right.expected_type(context)?;
let left_type = if let Some(r#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()));
};
left_type
.check(&right_type)
@ -89,8 +97,16 @@ impl AbstractNode for Logic {
left.validate(context, _manage_memory)?;
right.validate(context, _manage_memory)?;
let left_type = left.expected_type(context)?;
let right_type = right.expected_type(context)?;
let left_type = if let Some(r#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::Boolean = left_type {
} else {
@ -113,7 +129,11 @@ impl AbstractNode for Logic {
Logic::Not(expression) => {
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 {
Ok(())
@ -134,8 +154,8 @@ impl AbstractNode for Logic {
) -> Result<Option<Evaluation>, RuntimeError> {
let run_and_expect_value = |expression: Expression| -> Result<Value, RuntimeError> {
let expression_position = expression.position();
let action = expression.evaluate(&mut context.clone(), _manage_memory)?;
let value = if let Evaluation::Return(value) = action {
let evaluation = expression.evaluate(&mut context.clone(), _manage_memory)?;
let value = if let Some(Evaluation::Return(value)) = evaluation {
value
} else {
return Err(RuntimeError::ValidationFailure(
@ -148,8 +168,8 @@ impl AbstractNode for Logic {
let run_and_expect_boolean = |expression: Expression| -> Result<bool, RuntimeError> {
let expression_position = expression.position();
let action = expression.evaluate(&mut context.clone(), _manage_memory)?;
let value = if let Evaluation::Return(value) = action {
let evaluation = expression.evaluate(&mut context.clone(), _manage_memory)?;
let value = if let Some(Evaluation::Return(value)) = evaluation {
value
} else {
return Err(RuntimeError::ValidationFailure(
@ -251,7 +271,7 @@ mod tests {
Expression::Value(ValueNode::Integer(42).with_position((0, 0)))
)
.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)))
)
.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)))
)
.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)))
)
.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)))
)
.evaluate(&mut Context::new(None), true),
Ok(Evaluation::Return(Value::boolean(true)))
Ok(Some(Evaluation::Return(Value::boolean(true))))
);
assert_eq!(
@ -308,7 +328,7 @@ mod tests {
Expression::Value(ValueNode::Integer(42).with_position((0, 0))),
)
.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))),
)
.evaluate(&mut Context::new(None), true),
Ok(Evaluation::Return(Value::boolean(true)))
Ok(Some(Evaluation::Return(Value::boolean(true))))
);
assert_eq!(
@ -329,7 +349,7 @@ mod tests {
Expression::Value(ValueNode::Integer(42).with_position((0, 0))),
)
.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))),
)
.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))),
)
.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))
))
.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> {
loop {
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 {
return Ok(run);

View File

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

View File

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

View File

@ -59,7 +59,7 @@ impl AbstractNode for Statement {
Statement::Block(block) => block.node.define_types(_context),
Statement::AsyncBlock(async_block) => async_block.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::StructureDefinition(struct_definition) => {
struct_definition.node.define_types(_context)

View File

@ -24,10 +24,10 @@ impl AbstractNode for StructureDefinition {
fn define_types(&self, context: &Context) -> Result<(), ValidationError> {
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)?;
fields.push((identifier, r#type));
fields.push((identifier.clone(), r#type));
}
let struct_type = Type::Structure {
@ -35,12 +35,12 @@ impl AbstractNode for StructureDefinition {
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(())
}
@ -67,7 +67,7 @@ impl AbstractNode for StructureDefinition {
Ok(None)
}
fn expected_type(&self, context: &Context) -> Result<Option<Type>, ValidationError> {
fn expected_type(&self, _: &Context) -> Result<Option<Type>, ValidationError> {
Ok(None)
}
}

View File

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

View File

@ -27,24 +27,20 @@ impl AbstractNode for TypeAlias {
fn define_types(&self, context: &Context) -> Result<(), ValidationError> {
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(())
}
fn validate(&self, context: &Context, manage_memory: bool) -> Result<(), ValidationError> {
fn validate(&self, _: &Context, _: bool) -> Result<(), ValidationError> {
Ok(())
}
fn evaluate(
self,
context: &Context,
manage_memory: bool,
) -> Result<Option<Evaluation>, RuntimeError> {
fn evaluate(self, _: &Context, _: bool) -> Result<Option<Evaluation>, RuntimeError> {
Ok(None)
}
fn expected_type(&self, context: &Context) -> Result<Option<Type>, ValidationError> {
fn expected_type(&self, _: &Context) -> Result<Option<Type>, ValidationError> {
Ok(None)
}
}

View File

@ -23,7 +23,6 @@ pub enum RawTypeConstructor {
Float,
Integer,
Map,
None,
Range,
String,
}
@ -144,7 +143,11 @@ impl TypeConstructor {
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_parameters,
@ -172,7 +175,6 @@ impl TypeConstructor {
RawTypeConstructor::Float => Type::Float,
RawTypeConstructor::Integer => Type::Integer,
RawTypeConstructor::Map => Type::Map,
RawTypeConstructor::None => Type::Void,
RawTypeConstructor::Range => Type::Range,
RawTypeConstructor::String => Type::String,
},
@ -199,7 +201,7 @@ pub struct EnumTypeConstructor {
pub struct FunctionTypeConstructor {
pub type_parameters: Option<Vec<WithPosition<Identifier>>>,
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)]

View File

@ -34,7 +34,7 @@ pub enum ValueNode {
Function {
type_parameters: Option<Vec<Identifier>>,
value_parameters: Vec<(Identifier, TypeConstructor)>,
return_type: TypeConstructor,
return_type: Option<TypeConstructor>,
body: WithPosition<Block>,
},
}
@ -64,12 +64,7 @@ impl AbstractNode for ValueNode {
expression.define_types(_context)?;
}
}
ValueNode::Function {
type_parameters,
value_parameters,
return_type,
body,
} => {
ValueNode::Function { body, .. } => {
body.node.define_types(_context)?;
}
_ => {}
@ -156,20 +151,23 @@ impl AbstractNode for ValueNode {
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)? {
r#type
} else {
return Err(ValidationError::ExpectedExpression(body.position));
};
return_type
.clone()
.construct(&function_context)?
expected_return_type
.check(&actual_return_type)
.map_err(|conflict| ValidationError::TypeCheck {
conflict,
actual_position: body.position,
expected_position: Some(return_type.position()),
expected_position: Some(expected_position),
})?;
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)
}
@ -398,12 +400,16 @@ impl AbstractNode for ValueNode {
.map(|identifier| identifier.clone())
.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_parameters,
value_parameters: value_parameter_types,
return_type: Box::new(return_type),
return_type,
}
}
ValueNode::Structure {

View File

@ -52,12 +52,12 @@ impl AbstractNode for While {
) -> Result<Option<Evaluation>, RuntimeError> {
let get_boolean = || -> Result<Value, RuntimeError> {
let expression_position = self.expression.position();
let action = self
let evaluation = self
.expression
.clone()
.evaluate(&mut _context.clone(), false)?;
if let Evaluation::Return(value) = action {
if let Some(Evaluation::Return(value)) = evaluation {
Ok(value)
} else {
Err(RuntimeError::ValidationFailure(
@ -68,7 +68,7 @@ impl AbstractNode for While {
while let ValueInner::Boolean(true) = get_boolean()?.inner().as_ref() {
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 {
return Ok(evaluation);

View File

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

View File

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

View File

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

View File

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

View File

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