Continue implementing type inference

This commit is contained in:
Jeff 2024-06-19 02:32:17 -04:00
parent b3dd610949
commit d37c618ead
4 changed files with 47 additions and 5 deletions

View File

@ -8,7 +8,8 @@ use crate::{
}; };
use super::{ use super::{
AbstractNode, Evaluation, ExpectedType, Statement, Type, TypeConstructor, WithPosition, AbstractNode, Evaluation, ExpectedType, Expression, Statement, Type, TypeConstructor,
WithPosition,
}; };
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
@ -52,7 +53,38 @@ impl AbstractNode for Assignment {
)); ));
} }
if let Some(constructor) = &self.constructor { if let (Some(constructor), Statement::Expression(Expression::FunctionCall(function_call))) =
(&self.constructor, self.statement.as_ref())
{
let declared_type = constructor.clone().construct(context)?;
let function_type = function_call.node.function().expected_type(context)?;
if let Type::Function {
return_type,
type_parameters: Some(type_parameters),
..
} = function_type
{
if let Type::Generic {
identifier,
concrete_type,
} = *return_type
{
let returned_parameter = type_parameters
.into_iter()
.find(|parameter| parameter == &identifier);
if let Some(parameter) = returned_parameter {
context.set_type(parameter, declared_type)?;
}
}
} else {
return Err(ValidationError::ExpectedFunction {
actual: function_type,
position: function_call.position,
});
}
} else if let Some(constructor) = &self.constructor {
let r#type = constructor.clone().construct(&context)?; let r#type = constructor.clone().construct(&context)?;
r#type r#type
@ -78,8 +110,8 @@ impl AbstractNode for Assignment {
context: &mut Context, context: &mut Context,
manage_memory: bool, manage_memory: bool,
) -> Result<Evaluation, RuntimeError> { ) -> Result<Evaluation, RuntimeError> {
let action = self.statement.evaluate(context, manage_memory)?; let evaluation = self.statement.evaluate(context, manage_memory)?;
let right = match action { let right = match evaluation {
Evaluation::Return(value) => value, Evaluation::Return(value) => value,
r#break => return Ok(r#break), r#break => return Ok(r#break),
}; };

View File

@ -27,6 +27,10 @@ impl FunctionCall {
value_arguments, value_arguments,
} }
} }
pub fn function(&self) -> &Box<Expression> {
&self.function
}
} }
impl AbstractNode for FunctionCall { impl AbstractNode for FunctionCall {
@ -148,7 +152,7 @@ impl ExpectedType 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 &return_identifier == identifier { if identifier == &return_identifier {
let concrete_type = constructor.clone().construct(&context)?; let concrete_type = constructor.clone().construct(&context)?;
return Ok(Type::Generic { return Ok(Type::Generic {

View File

@ -341,6 +341,10 @@ impl Function {
&self.value_parameters &self.value_parameters
} }
pub fn body(&self) -> &Block {
&self.body
}
pub fn call( pub fn call(
self, self,
arguments: Vec<Value>, arguments: Vec<Value>,

View File

@ -1,3 +1,5 @@
foo = fn |T| (x: T) -> T { x } foo = fn |T| (x: T) -> T { x }
bar: str = foo::(str)::("hi") bar: str = foo::(str)::("hi")
baz: str = foo("hi") baz: str = foo("hi")
x = json.parse::(int)::("1")
x: int = json.parse("1")