Fix type generic bug
This commit is contained in:
parent
97268c272e
commit
7dc7f7a351
@ -1,3 +1,5 @@
|
|||||||
|
use std::cmp::Ordering;
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -6,13 +8,19 @@ use crate::{
|
|||||||
value::ValueInner,
|
value::ValueInner,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{AbstractNode, Evaluation, Expression, Type, TypeConstructor, ValueNode, WithPosition};
|
use super::{
|
||||||
|
expression, AbstractNode, Evaluation, Expression, Type, TypeConstructor, ValueNode,
|
||||||
|
WithPosition,
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct FunctionCall {
|
pub struct FunctionCall {
|
||||||
function_expression: Box<Expression>,
|
function_expression: Box<Expression>,
|
||||||
type_arguments: Option<Vec<TypeConstructor>>,
|
type_arguments: Option<Vec<TypeConstructor>>,
|
||||||
value_arguments: Option<Vec<Expression>>,
|
value_arguments: Option<Vec<Expression>>,
|
||||||
|
|
||||||
|
#[serde(skip)]
|
||||||
|
context: Context,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FunctionCall {
|
impl FunctionCall {
|
||||||
@ -25,6 +33,7 @@ impl FunctionCall {
|
|||||||
function_expression: Box::new(function_expression),
|
function_expression: Box::new(function_expression),
|
||||||
type_arguments,
|
type_arguments,
|
||||||
value_arguments,
|
value_arguments,
|
||||||
|
context: Context::new(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,6 +52,8 @@ impl AbstractNode for FunctionCall {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.context.set_parent(context.clone())?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,20 +81,35 @@ impl AbstractNode for FunctionCall {
|
|||||||
return_type: _,
|
return_type: _,
|
||||||
} = function_node_type
|
} = function_node_type
|
||||||
{
|
{
|
||||||
match (type_parameters, &self.type_arguments) {
|
if let (Some(parameters), Some(arguments)) = (type_parameters, &self.type_arguments) {
|
||||||
(Some(parameters), Some(type_arguments)) => {
|
if parameters.len() != arguments.len() {
|
||||||
if parameters.len() != type_arguments.len() {
|
return Err(ValidationError::WrongTypeArguments {
|
||||||
return Err(ValidationError::WrongTypeArguments {
|
arguments: arguments.clone(),
|
||||||
arguments: type_arguments.clone(),
|
parameters: parameters.clone(),
|
||||||
parameters: parameters.clone(),
|
});
|
||||||
});
|
}
|
||||||
}
|
|
||||||
|
for (identifier, constructor) in parameters.into_iter().zip(arguments.into_iter()) {
|
||||||
|
let r#type = constructor.construct(context)?;
|
||||||
|
|
||||||
|
self.context.set_type(identifier, r#type)?;
|
||||||
}
|
}
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
match (value_parameters, &self.value_arguments) {
|
match (value_parameters, &self.value_arguments) {
|
||||||
(Some(parameters), Some(arguments)) => {
|
(Some(parameters), Some(arguments)) => {
|
||||||
|
for ((identifier, _), expression) in
|
||||||
|
parameters.iter().zip(arguments.into_iter())
|
||||||
|
{
|
||||||
|
let r#type = if let Some(r#type) = expression.expected_type(context)? {
|
||||||
|
r#type
|
||||||
|
} else {
|
||||||
|
return Err(ValidationError::ExpectedExpression(expression.position()));
|
||||||
|
};
|
||||||
|
|
||||||
|
self.context.set_type(identifier.clone(), r#type)?;
|
||||||
|
}
|
||||||
|
|
||||||
if parameters.len() != arguments.len() {
|
if parameters.len() != arguments.len() {
|
||||||
return Err(ValidationError::WrongValueArguments {
|
return Err(ValidationError::WrongValueArguments {
|
||||||
parameters,
|
parameters,
|
||||||
@ -150,8 +176,6 @@ impl AbstractNode for FunctionCall {
|
|||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
let function_context = Context::new(Some(context.clone()));
|
|
||||||
|
|
||||||
if let (Some(type_parameters), Some(type_arguments)) =
|
if let (Some(type_parameters), Some(type_arguments)) =
|
||||||
(function.type_parameters(), self.type_arguments)
|
(function.type_parameters(), self.type_arguments)
|
||||||
{
|
{
|
||||||
@ -160,7 +184,7 @@ impl AbstractNode for FunctionCall {
|
|||||||
{
|
{
|
||||||
let r#type = constructor.construct(context)?;
|
let r#type = constructor.construct(context)?;
|
||||||
|
|
||||||
function_context.set_type(identifier.clone(), r#type)?;
|
self.context.set_type(identifier.clone(), r#type)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,31 +202,71 @@ impl AbstractNode for FunctionCall {
|
|||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
function_context.set_value(identifier.clone(), value)?;
|
self.context.set_value(identifier.clone(), value)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function.call(&function_context, manage_memory)
|
function.call(&self.context, manage_memory)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expected_type(&self, context: &Context) -> Result<Option<Type>, ValidationError> {
|
fn expected_type(&self, context: &Context) -> Result<Option<Type>, ValidationError> {
|
||||||
let return_type = if let Some(r#type) = self.function_expression.expected_type(context)? {
|
let expression_type = self.function_expression.expected_type(context)?.ok_or(
|
||||||
if let Type::Function { return_type, .. } = r#type {
|
ValidationError::ExpectedExpression(self.function_expression.position()),
|
||||||
return_type
|
)?;
|
||||||
} else {
|
|
||||||
return Err(ValidationError::ExpectedFunction {
|
let (type_parameters, value_parameters, return_type) = if let Type::Function {
|
||||||
actual: r#type,
|
type_parameters,
|
||||||
position: self.function_expression.position(),
|
value_parameters,
|
||||||
});
|
return_type,
|
||||||
}
|
} = expression_type
|
||||||
|
{
|
||||||
|
(type_parameters, value_parameters, return_type)
|
||||||
} else {
|
} else {
|
||||||
return Err(ValidationError::ExpectedExpression(
|
return Err(ValidationError::ExpectedFunction {
|
||||||
self.function_expression.position(),
|
actual: expression_type,
|
||||||
));
|
position: self.function_expression.position(),
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
let return_type = return_type.map(|r#box| *r#box);
|
if let Some(Type::Generic {
|
||||||
|
identifier: return_identifier,
|
||||||
|
concrete_type: None,
|
||||||
|
}) = return_type.clone().map(|r#box| *r#box)
|
||||||
|
{
|
||||||
|
if let (Some(parameters), Some(arguments)) = (type_parameters, &self.type_arguments) {
|
||||||
|
for (identifier, constructor) in parameters.into_iter().zip(arguments.into_iter()) {
|
||||||
|
if identifier == return_identifier {
|
||||||
|
let r#type = constructor.construct(context)?;
|
||||||
|
|
||||||
Ok(return_type)
|
return Ok(Some(Type::Generic {
|
||||||
|
identifier,
|
||||||
|
concrete_type: Some(Box::new(r#type)),
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(return_type.map(|r#box| *r#box))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Eq for FunctionCall {}
|
||||||
|
|
||||||
|
impl PartialEq for FunctionCall {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialOrd for FunctionCall {
|
||||||
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||||
|
Some(self.cmp(other))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ord for FunctionCall {
|
||||||
|
fn cmp(&self, other: &Self) -> Ordering {
|
||||||
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -142,7 +142,15 @@ impl Display for Value {
|
|||||||
write!(f, "{type_name}::{variant}")
|
write!(f, "{type_name}::{variant}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ValueInner::Float(float) => write!(f, "{float}"),
|
ValueInner::Float(float) => {
|
||||||
|
write!(f, "{float}")?;
|
||||||
|
|
||||||
|
if &float.floor() == float {
|
||||||
|
write!(f, ".0")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
ValueInner::Integer(integer) => write!(f, "{integer}"),
|
ValueInner::Integer(integer) => write!(f, "{integer}"),
|
||||||
ValueInner::List(list) => {
|
ValueInner::List(list) => {
|
||||||
write!(f, "[")?;
|
write!(f, "[")?;
|
||||||
|
Loading…
Reference in New Issue
Block a user