feat(resolver): handle generic application
This commit is contained in:
@@ -12,6 +12,7 @@ from midas.checker.types import (
|
|||||||
Type,
|
Type,
|
||||||
TypeVar,
|
TypeVar,
|
||||||
UnknownType,
|
UnknownType,
|
||||||
|
substitute_typevars,
|
||||||
)
|
)
|
||||||
from midas.resolver.builtin import define_builtins
|
from midas.resolver.builtin import define_builtins
|
||||||
|
|
||||||
@@ -186,8 +187,36 @@ class MidasResolver(m.Stmt.Visitor[None], m.Expr.Visitor[None], m.Type.Visitor[T
|
|||||||
def visit_generic_type(self, type: m.GenericType) -> Type:
|
def visit_generic_type(self, type: m.GenericType) -> Type:
|
||||||
type_: Type = type.type.accept(self)
|
type_: Type = type.type.accept(self)
|
||||||
params: list[Type] = [param.accept(self) for param in type.params]
|
params: list[Type] = [param.accept(self) for param in type.params]
|
||||||
# TODO
|
return self.apply_generic(type_, params)
|
||||||
return UnknownType()
|
|
||||||
|
def apply_generic(self, type: Type, params: list[Type]) -> Type:
|
||||||
|
match type:
|
||||||
|
case AliasType(name=name, type=base):
|
||||||
|
return AliasType(name=name, type=self.apply_generic(base, params))
|
||||||
|
|
||||||
|
case GenericType(params=type_vars, body=body):
|
||||||
|
n_params: int = len(params)
|
||||||
|
n_type_vars: int = len(type_vars)
|
||||||
|
if n_params < n_type_vars:
|
||||||
|
raise ValueError(
|
||||||
|
f"Missing type parameters, expected {n_type_vars} but only {n_params} provided"
|
||||||
|
)
|
||||||
|
if n_params > n_type_vars:
|
||||||
|
raise ValueError(
|
||||||
|
f"Too many type parameters, expected {n_type_vars} but {n_params} provided"
|
||||||
|
)
|
||||||
|
substitutions: dict[str, Type] = {}
|
||||||
|
for param, type_var in zip(params, type_vars):
|
||||||
|
if type_var.bound is not None and not self.is_subtype(
|
||||||
|
param, type_var.bound
|
||||||
|
):
|
||||||
|
raise ValueError(
|
||||||
|
f"Type parameter {param} is not a subtype of {type_var.bound}"
|
||||||
|
)
|
||||||
|
substitutions[type_var.name] = param
|
||||||
|
return substitute_typevars(body, substitutions)
|
||||||
|
case _:
|
||||||
|
raise ValueError(f"{type} is not a generic type")
|
||||||
|
|
||||||
def visit_constraint_type(self, type: m.ConstraintType) -> Type:
|
def visit_constraint_type(self, type: m.ConstraintType) -> Type:
|
||||||
type_: Type = type.type.accept(self)
|
type_: Type = type.type.accept(self)
|
||||||
|
|||||||
Reference in New Issue
Block a user