Continue refactoring
This commit is contained in:
parent
88906fb6d7
commit
4b89ea0e96
@ -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(())
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -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))))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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(),
|
||||
})
|
||||
}
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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) => {
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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() {
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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)]
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
@ -455,7 +455,6 @@ impl InterpreterError {
|
||||
}
|
||||
}
|
||||
ValidationError::EnumVariantNotFound { .. } => todo!(),
|
||||
ValidationError::CannotIndexWithVoid(_) => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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| {
|
||||
|
@ -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))
|
||||
))])
|
||||
|
@ -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,
|
||||
}
|
||||
|
||||
|
@ -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))
|
||||
))])
|
||||
|
Loading…
Reference in New Issue
Block a user