feat(types): add TupleType
This commit is contained in:
@@ -27,6 +27,7 @@ from midas.checker.types import (
|
|||||||
Function,
|
Function,
|
||||||
GenericType,
|
GenericType,
|
||||||
OverloadedFunction,
|
OverloadedFunction,
|
||||||
|
TupleType,
|
||||||
Type,
|
Type,
|
||||||
TypeVar,
|
TypeVar,
|
||||||
UnitType,
|
UnitType,
|
||||||
@@ -642,6 +643,11 @@ class PythonTyper(
|
|||||||
|
|
||||||
def visit_subscript_expr(self, expr: p.SubscriptExpr) -> Type:
|
def visit_subscript_expr(self, expr: p.SubscriptExpr) -> Type:
|
||||||
object: Type = self.type_of(expr.object)
|
object: Type = self.type_of(expr.object)
|
||||||
|
unfolded: Type = unfold_type(object)
|
||||||
|
match unfolded:
|
||||||
|
case TupleType():
|
||||||
|
return self._visit_tuple_subscript(unfolded, expr)
|
||||||
|
|
||||||
operation: Optional[Type] = self.types.lookup_member(object, "__getitem__")
|
operation: Optional[Type] = self.types.lookup_member(object, "__getitem__")
|
||||||
if operation is None:
|
if operation is None:
|
||||||
self.reporter.error(
|
self.reporter.error(
|
||||||
@@ -1231,3 +1237,18 @@ class PythonTyper(
|
|||||||
expr.location, f"Cannot evaluate cast to {target_type} statically"
|
expr.location, f"Cannot evaluate cast to {target_type} statically"
|
||||||
)
|
)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def _visit_tuple_subscript(self, tup: TupleType, expr: p.SubscriptExpr) -> Type:
|
||||||
|
match expr.index:
|
||||||
|
case p.LiteralExpr(value=int() as index):
|
||||||
|
if index < 0 or index >= len(tup.items):
|
||||||
|
self.reporter.error(
|
||||||
|
expr.location, f"Index {index} out of range for tuple {tup}"
|
||||||
|
)
|
||||||
|
return UnknownType()
|
||||||
|
return tup.items[index]
|
||||||
|
case _:
|
||||||
|
self.reporter.error(
|
||||||
|
expr.location, f"Invalid index type {expr.index} on {tup}"
|
||||||
|
)
|
||||||
|
return UnknownType()
|
||||||
|
|||||||
@@ -156,6 +156,14 @@ class ConstraintType:
|
|||||||
return f"{self.type} where {printer.print(self.constraint)}"
|
return f"{self.type} where {printer.print(self.constraint)}"
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True, kw_only=True)
|
||||||
|
class TupleType:
|
||||||
|
items: tuple[Type, ...]
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
return f"({', '.join(map(str, self.items))})"
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True, kw_only=True)
|
@dataclass(frozen=True, kw_only=True)
|
||||||
class ColumnType:
|
class ColumnType:
|
||||||
type: Type
|
type: Type
|
||||||
@@ -282,6 +290,11 @@ def substitute_typevars(type: Type, substitutions: dict[str, Type]) -> Type:
|
|||||||
body=substitute_typevars(body, substitutions),
|
body=substitute_typevars(body, substitutions),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
case TupleType(items=items):
|
||||||
|
return TupleType(
|
||||||
|
items=tuple(substitute_typevars(item, substitutions) for item in items),
|
||||||
|
)
|
||||||
|
|
||||||
case ColumnType(type=items_type):
|
case ColumnType(type=items_type):
|
||||||
return ColumnType(
|
return ColumnType(
|
||||||
type=substitute_typevars(items_type, substitutions),
|
type=substitute_typevars(items_type, substitutions),
|
||||||
@@ -360,6 +373,9 @@ def to_annotation(type: Type) -> str:
|
|||||||
case ConstraintType():
|
case ConstraintType():
|
||||||
return str(type)
|
return str(type)
|
||||||
|
|
||||||
|
case TupleType(items=items):
|
||||||
|
return f"Tuple[{', '.join(map(to_annotation, items))}]"
|
||||||
|
|
||||||
case ColumnType():
|
case ColumnType():
|
||||||
return "pd.Series"
|
return "pd.Series"
|
||||||
|
|
||||||
@@ -391,6 +407,7 @@ Type = (
|
|||||||
| GenericType
|
| GenericType
|
||||||
| AppliedType
|
| AppliedType
|
||||||
| ConstraintType
|
| ConstraintType
|
||||||
|
| TupleType
|
||||||
| ColumnType
|
| ColumnType
|
||||||
| DataFrameType
|
| DataFrameType
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user