feat: remove complex and extension types

This commit is contained in:
2026-07-08 15:34:40 +02:00
parent db986d5242
commit 725e030374
13 changed files with 3 additions and 230 deletions

View File

@@ -136,15 +136,6 @@ class ConstraintType:
constraint: Expr
class ComplexType:
members: list[MemberStmt]
class ExtensionType:
base: Type
extension: ComplexType
class FunctionType:
params: ParamSpec
returns: Type

View File

@@ -256,12 +256,6 @@ class Type(ABC):
@abstractmethod
def visit_constraint_type(self, type: ConstraintType) -> T: ...
@abstractmethod
def visit_complex_type(self, type: ComplexType) -> T: ...
@abstractmethod
def visit_extension_type(self, type: ExtensionType) -> T: ...
@abstractmethod
def visit_function_type(self, type: FunctionType) -> T: ...
@@ -295,23 +289,6 @@ class ConstraintType(Type):
return visitor.visit_constraint_type(self)
@dataclass(frozen=True)
class ComplexType(Type):
members: list[MemberStmt]
def accept(self, visitor: Type.Visitor[T]) -> T:
return visitor.visit_complex_type(self)
@dataclass(frozen=True)
class ExtensionType(Type):
base: Type
extension: ComplexType
def accept(self, visitor: Type.Visitor[T]) -> T:
return visitor.visit_extension_type(self)
@dataclass(frozen=True)
class FunctionType(Type):
params: ParamSpec

View File

@@ -124,19 +124,6 @@ class MidasPrinter(
res += " where " + type.constraint.accept(self)
return res
def visit_complex_type(self, type: m.ComplexType) -> str:
res: str = "{\n"
self.level += 1
for member in type.members:
res += member.accept(self)
res += "\n"
self.level -= 1
res += self.indented("}")
return res
def visit_extension_type(self, type: m.ExtensionType) -> str:
return f"{type.base.accept(self)} & {type.extension.accept(self)}"
def visit_function_type(self, type: m.FunctionType) -> str:
spec: str = self._visit_param_spec(type.params)
return f"fn {spec} -> {type.returns.accept(self)}"

View File

@@ -177,21 +177,6 @@ class MidasAstPrinter(
with self._child_level(single=True):
type.constraint.accept(self)
def visit_complex_type(self, type: m.ComplexType) -> None:
self._write_line("ComplexType")
with self._child_level():
self._write_sequence("members", type.members, last=True)
def visit_extension_type(self, type: m.ExtensionType) -> None:
self._write_line("ExtensionType")
with self._child_level():
self._write_line("base")
with self._child_level(single=True):
type.base.accept(self)
self._write_line("extension", last=True)
with self._child_level(single=True):
type.extension.accept(self)
def visit_function_type(self, type: m.FunctionType) -> None:
self._write_line("FunctionType")
with self._child_level():

View File

@@ -13,11 +13,9 @@ from midas.checker.registry import TypesRegistry
from midas.checker.reporter import FileReporter, Reporter
from midas.checker.types import (
ColumnType,
ComplexType,
ConstraintType,
DataFrameType,
DerivedType,
ExtensionType,
Function,
GenericType,
ParamSpec,
@@ -422,19 +420,6 @@ class MidasTyper(m.Stmt.Visitor[None], m.Expr.Visitor[Type], m.Type.Visitor[Type
constraint=type.constraint,
)
def visit_complex_type(self, type: m.ComplexType) -> ComplexType:
return ComplexType(
members={
member.name.lexeme: member.type.accept(self) for member in type.members
}
)
def visit_extension_type(self, type: m.ExtensionType) -> Type:
return ExtensionType(
base=type.base.accept(self),
extension=self.visit_complex_type(type.extension),
)
def visit_function_type(self, type: m.FunctionType) -> Type:
return Function(
params=self._visit_param_spec(type.params),

View File

@@ -8,11 +8,9 @@ from midas.checker.types import (
AppliedType,
BaseType,
ColumnType,
ComplexType,
ConstraintType,
DataFrameType,
DerivedType,
ExtensionType,
Function,
GenericType,
OverloadedFunction,
@@ -202,14 +200,6 @@ class TypesRegistry:
case (BaseType(name=name1), BaseType(name=name2)):
return self.is_builtin_subtype(name1, name2)
case (ComplexType(properties=props1), ComplexType(properties=props2)):
for k, t in props2.items():
if k not in props1:
return False
if not self.is_subtype(props1[k], t):
return False
return True
case (DataFrameType(columns=columns1), DataFrameType(columns=columns2)):
# TODO: check order?
by_name1: dict[str, DataFrameType.Column] = {
@@ -506,20 +496,6 @@ class TypesRegistry:
member_type2 = substitute_typevars(member_type2, substitutions)
return member_type2
case ComplexType(members=members):
if member_name in members:
return members[member_name]
self.logger.debug(f"No member '{member_name}' in {type}")
return None
case ExtensionType(base=base, extension=ComplexType(members=members)):
if member_name in members:
return members[member_name]
self.logger.debug(
f"No member '{member_name}' on {type}, looking up in base"
)
return self.lookup_member(base, member_name)
case ConstraintType(type=base):
return self.lookup_member(base, member_name)

View File

@@ -113,28 +113,6 @@ class OverloadedFunction:
return "<overloaded function>"
@dataclass(frozen=True, kw_only=True)
class ComplexType:
"""A type with inline members"""
members: dict[str, Type]
def __str__(self) -> str:
props: list[str] = [f"{name}: {type}" for name, type in self.members.items()]
return f"{{{', '.join(props)}}}"
@dataclass(frozen=True, kw_only=True)
class ExtensionType:
"""An extension of a type, adding members through a `ComplexType`"""
base: Type
extension: ComplexType
def __str__(self) -> str:
return f"{self.base} & {self.extension}"
class Variance(StrEnum):
"""The variance of a :class:`TypeVar`"""
@@ -323,24 +301,6 @@ def substitute_typevars(type: Type, substitutions: dict[str, Type]) -> Type:
]
)
case ComplexType(members=members):
members2: dict[str, Type] = {
name: substitute_typevars(prop, substitutions)
for name, prop in members.items()
}
return ComplexType(members=members2)
case ExtensionType(base=base, extension=ComplexType(members=members)):
return ExtensionType(
base=substitute_typevars(base, substitutions),
extension=ComplexType(
members={
name: substitute_typevars(prop, substitutions)
for name, prop in members.items()
}
),
)
case AppliedType(name=name, args=args, body=body):
return AppliedType(
name=name,
@@ -468,9 +428,6 @@ def to_annotation(type: Type) -> str:
case OverloadedFunction():
return "Callable"
case ComplexType() | ExtensionType():
raise NotImplementedError
case TypeVar(name=name):
return name
@@ -519,8 +476,6 @@ Type = (
| UnitType
| Function
| OverloadedFunction
| ComplexType
| ExtensionType
| TypeVar
| GenericType
| AppliedType

View File

@@ -338,21 +338,11 @@ class MidasHighlighter(
type.type.accept(self)
type.constraint.accept(self)
def visit_complex_type(self, type: m.ComplexType) -> None:
self.wrap(type, "complex-type")
for member in type.members:
member.accept(self)
def visit_function_type(self, type: m.FunctionType) -> None:
self.wrap(type, "function")
self._visit_param_spec(type.params)
type.returns.accept(self)
def visit_extension_type(self, type: m.ExtensionType) -> None:
self.wrap(type, "extension")
type.base.accept(self)
type.extension.accept(self)
def _visit_param_spec(self, spec: m.ParamSpec) -> None:
for param in spec.pos + spec.mixed + spec.kw:
param.type.accept(self)

View File

@@ -7,8 +7,7 @@ span {
&.named-type,
&.generic-type,
&.constraint-type,
&.complex-type {
&.constraint-type {
--col: 150, 150, 150;
}

View File

@@ -16,11 +16,9 @@ from midas.checker.types import (
BaseType,
ColumnGroupBy,
ColumnType,
ComplexType,
ConstraintType,
DataFrameType,
DerivedType,
ExtensionType,
FrameGroupBy,
Function,
GenericType,
@@ -675,8 +673,6 @@ class Generator(p.Stmt.Visitor[ast.stmt], p.Expr.Visitor[ast.expr]):
case (
Function()
| OverloadedFunction()
| ComplexType()
| ExtensionType()
| GenericType()
| FrameGroupBy()
| ColumnGroupBy()

View File

@@ -8,11 +8,9 @@ from midas.checker.types import (
BaseType,
ColumnGroupBy,
ColumnType,
ComplexType,
ConstraintType,
DataFrameType,
DerivedType,
ExtensionType,
FrameGroupBy,
Function,
GenericType,
@@ -269,14 +267,6 @@ class StubsGenerator:
right=self.dump_type(overloads[-1]),
)
case ComplexType():
name: str = self.new_stub_name()
self.generate_stub(name, type)
return ast.Name(id=name)
case ExtensionType():
raise NotImplementedError
case TypeVar():
return ast.Name(id=type.name)

View File

@@ -5,11 +5,9 @@ from midas.ast.midas import (
AliasStmt,
BinaryExpr,
CallExpr,
ComplexType,
ConstraintType,
Expr,
ExtendStmt,
ExtensionType,
FrameType,
FunctionType,
GenericType,
@@ -187,19 +185,9 @@ class MidasParser(Parser[list[Stmt]]):
Returns:
TypeExpr: the parsed type expression
"""
base: Type
if self.match(TokenType.FUNC):
base = self.function()
else:
base = self.constraint_type()
if self.match(TokenType.AND):
extension: ComplexType = self.complex_type()
return ExtensionType(
location=Location.span(base.location, extension.location),
base=base,
extension=extension,
)
return base
return self.function()
return self.constraint_type()
def constraint_type(self) -> Type:
"""Parse a constraint type expression
@@ -235,9 +223,6 @@ class MidasParser(Parser[list[Stmt]]):
self.consume(TokenType.RIGHT_PAREN, "Unclosed parenthesis")
return type
if self.check(TokenType.LEFT_BRACE):
return self.complex_type()
return self.generic_type()
def generic_type(self) -> Type:
@@ -295,34 +280,6 @@ class MidasParser(Parser[list[Stmt]]):
name=name,
)
def complex_type(self) -> ComplexType:
"""Parse a complex type expression
A complex type consists of zero or more member statements enclosed in
curly braces
Returns:
ComplexType: the parsed complex type expression
"""
left: Token = self.consume(
TokenType.LEFT_BRACE, "Expected '{' to start type body"
)
members: list[MemberStmt] = []
# TODO: add keyword to differentiate properties and methods,
# and allow multiple methods with the same name but not properties
names: set[str] = set()
while not self.check(TokenType.RIGHT_BRACE) and not self.is_at_end():
member: MemberStmt = self.member_stmt()
# if member.name.lexeme in names:
# raise self.error(member.name, "Duplicate property")
# names.add(member.name.lexeme)
members.append(member)
right: Token = self.consume(TokenType.RIGHT_BRACE, "Unclosed type body")
return ComplexType(
location=left.location_to(right),
members=members,
)
def frame_type(self) -> FrameType:
"""Parse a frame type expression

View File

@@ -4,11 +4,9 @@ from midas.ast.midas import (
AliasStmt,
BinaryExpr,
CallExpr,
ComplexType,
ConstraintType,
Expr,
ExtendStmt,
ExtensionType,
FrameType,
FunctionType,
GenericType,
@@ -172,12 +170,6 @@ class MidasAstJsonSerializer(
"constraint": type.constraint.accept(self),
}
def visit_complex_type(self, type: ComplexType) -> dict:
return {
"_type": "ComplexType",
"members": self._serialize_list(type.members),
}
def visit_function_type(self, type: FunctionType) -> dict:
return {
"_type": "FunctionType",
@@ -200,13 +192,6 @@ class MidasAstJsonSerializer(
"required": param.required,
}
def visit_extension_type(self, type: ExtensionType) -> dict:
return {
"_type": "ExtensionType",
"base": type.base.accept(self),
"extension": type.extension.accept(self),
}
def visit_frame_type(self, type: FrameType) -> dict:
return {
"_type": "FrameType",