Implement type inferencing
This commit is contained in:
parent
ccdcc7c791
commit
aa79bea9a7
@ -128,10 +128,38 @@ impl AbstractNode for FunctionCall {
|
||||
}
|
||||
|
||||
impl ExpectedType for FunctionCall {
|
||||
fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> {
|
||||
let function_node_type = self.function.expected_type(_context)?;
|
||||
fn expected_type(&self, context: &mut Context) -> Result<Type, ValidationError> {
|
||||
let function_node_type = self.function.expected_type(context)?;
|
||||
|
||||
if let Type::Function {
|
||||
return_type,
|
||||
type_parameters,
|
||||
..
|
||||
} = function_node_type
|
||||
{
|
||||
for (constructor, identifier) in self
|
||||
.type_arguments
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.into_iter()
|
||||
.zip(type_parameters.unwrap().into_iter())
|
||||
{
|
||||
if let Type::Generic {
|
||||
identifier: return_identifier,
|
||||
..
|
||||
} = *return_type.clone()
|
||||
{
|
||||
if return_identifier == identifier {
|
||||
let concrete_type = constructor.clone().construct(&context)?;
|
||||
|
||||
return Ok(Type::Generic {
|
||||
identifier,
|
||||
concrete_type: Some(Box::new(concrete_type)),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Type::Function { return_type, .. } = function_node_type {
|
||||
Ok(*return_type)
|
||||
} else {
|
||||
Err(ValidationError::ExpectedFunction {
|
||||
|
@ -21,7 +21,10 @@ pub enum Type {
|
||||
value_parameters: Vec<Type>,
|
||||
return_type: Box<Type>,
|
||||
},
|
||||
Generic(Option<Box<Type>>),
|
||||
Generic {
|
||||
identifier: Identifier,
|
||||
concrete_type: Option<Box<Type>>,
|
||||
},
|
||||
Integer,
|
||||
List {
|
||||
length: usize,
|
||||
@ -50,7 +53,16 @@ impl Type {
|
||||
| (Type::None, Type::None)
|
||||
| (Type::Range, Type::Range)
|
||||
| (Type::String, Type::String) => return Ok(()),
|
||||
(Type::Generic(left), Type::Generic(right)) => match (left, right) {
|
||||
(
|
||||
Type::Generic {
|
||||
concrete_type: left,
|
||||
..
|
||||
},
|
||||
Type::Generic {
|
||||
concrete_type: right,
|
||||
..
|
||||
},
|
||||
) => match (left, right) {
|
||||
(Some(left), Some(right)) => {
|
||||
if left.check(&right).is_ok() {
|
||||
return Ok(());
|
||||
@ -61,6 +73,14 @@ impl Type {
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
(Type::Generic { concrete_type, .. }, other)
|
||||
| (other, Type::Generic { concrete_type, .. }) => {
|
||||
if let Some(concrete_type) = concrete_type {
|
||||
if other == concrete_type.as_ref() {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
}
|
||||
(Type::ListOf(left), Type::ListOf(right)) => {
|
||||
if left.check(&right).is_ok() {
|
||||
return Ok(());
|
||||
@ -207,11 +227,11 @@ impl Display for Type {
|
||||
Type::Any => write!(f, "any"),
|
||||
Type::Boolean => write!(f, "bool"),
|
||||
Type::Float => write!(f, "float"),
|
||||
Type::Generic(type_option) => {
|
||||
if let Some(concrete_type) = type_option {
|
||||
write!(f, "implied to be {concrete_type}")
|
||||
Type::Generic { concrete_type, .. } => {
|
||||
if let Some(r#type) = concrete_type {
|
||||
write!(f, "implied to be {}", r#type)
|
||||
} else {
|
||||
todo!()
|
||||
write!(f, "unknown")
|
||||
}
|
||||
}
|
||||
Type::Integer => write!(f, "int"),
|
||||
|
@ -82,9 +82,15 @@ impl TypeConstructor {
|
||||
node: identifier, ..
|
||||
}) => {
|
||||
if let Some(r#type) = context.get_type(&identifier)? {
|
||||
Type::Generic(Some(Box::new(r#type)))
|
||||
Type::Generic {
|
||||
identifier,
|
||||
concrete_type: Some(Box::new(r#type)),
|
||||
}
|
||||
} else {
|
||||
Type::Generic(None)
|
||||
Type::Generic {
|
||||
identifier,
|
||||
concrete_type: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
TypeConstructor::List(positioned_constructor) => {
|
||||
|
@ -68,7 +68,13 @@ impl AbstractNode for ValueNode {
|
||||
|
||||
if let Some(type_parameters) = type_parameters {
|
||||
for identifier in type_parameters {
|
||||
function_context.set_type(identifier.clone(), Type::Generic(None))?;
|
||||
function_context.set_type(
|
||||
identifier.clone(),
|
||||
Type::Generic {
|
||||
identifier: identifier.clone(),
|
||||
concrete_type: None,
|
||||
},
|
||||
)?;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,3 +18,4 @@ while count <= 15 {
|
||||
|
||||
count += 1
|
||||
}
|
||||
|
||||
|
2
examples/type_inference.ds
Normal file
2
examples/type_inference.ds
Normal file
@ -0,0 +1,2 @@
|
||||
foo = fn |T| (x: T) -> T { x }
|
||||
bar: str = foo::(str)::("hi")
|
Loading…
Reference in New Issue
Block a user