Continue implementing type inference
This commit is contained in:
parent
b3dd610949
commit
d37c618ead
@ -8,7 +8,8 @@ use crate::{
|
||||
};
|
||||
|
||||
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)]
|
||||
@ -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)?;
|
||||
|
||||
r#type
|
||||
@ -78,8 +110,8 @@ impl AbstractNode for Assignment {
|
||||
context: &mut Context,
|
||||
manage_memory: bool,
|
||||
) -> Result<Evaluation, RuntimeError> {
|
||||
let action = self.statement.evaluate(context, manage_memory)?;
|
||||
let right = match action {
|
||||
let evaluation = self.statement.evaluate(context, manage_memory)?;
|
||||
let right = match evaluation {
|
||||
Evaluation::Return(value) => value,
|
||||
r#break => return Ok(r#break),
|
||||
};
|
||||
|
@ -27,6 +27,10 @@ impl FunctionCall {
|
||||
value_arguments,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn function(&self) -> &Box<Expression> {
|
||||
&self.function
|
||||
}
|
||||
}
|
||||
|
||||
impl AbstractNode for FunctionCall {
|
||||
@ -148,7 +152,7 @@ impl ExpectedType for FunctionCall {
|
||||
for (constructor, identifier) in
|
||||
type_arguments.into_iter().zip(type_parameters.into_iter())
|
||||
{
|
||||
if &return_identifier == identifier {
|
||||
if identifier == &return_identifier {
|
||||
let concrete_type = constructor.clone().construct(&context)?;
|
||||
|
||||
return Ok(Type::Generic {
|
||||
|
@ -341,6 +341,10 @@ impl Function {
|
||||
&self.value_parameters
|
||||
}
|
||||
|
||||
pub fn body(&self) -> &Block {
|
||||
&self.body
|
||||
}
|
||||
|
||||
pub fn call(
|
||||
self,
|
||||
arguments: Vec<Value>,
|
||||
|
@ -1,3 +1,5 @@
|
||||
foo = fn |T| (x: T) -> T { x }
|
||||
bar: str = foo::(str)::("hi")
|
||||
baz: str = foo("hi")
|
||||
x = json.parse::(int)::("1")
|
||||
x: int = json.parse("1")
|
||||
|
Loading…
Reference in New Issue
Block a user