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