From 725e030374af6acac2c2a74f4cac2067db854ca9 Mon Sep 17 00:00:00 2001 From: LordBaryhobal Date: Wed, 8 Jul 2026 15:34:40 +0200 Subject: [PATCH] feat: remove complex and extension types --- gen/midas.py | 9 ------- midas/ast/midas.py | 23 ----------------- midas/ast/printer/midas.py | 13 ---------- midas/ast/printer/midas_ast.py | 15 ----------- midas/checker/midas.py | 15 ----------- midas/checker/registry.py | 24 ----------------- midas/checker/types.py | 45 -------------------------------- midas/cli/highlighter.py | 10 -------- midas/cli/hl_midas.css | 3 +-- midas/generator/generator.py | 4 --- midas/generator/stubs.py | 10 -------- midas/parser/midas.py | 47 ++-------------------------------- tests/serializer/midas.py | 15 ----------- 13 files changed, 3 insertions(+), 230 deletions(-) diff --git a/gen/midas.py b/gen/midas.py index fb90199..423d16b 100644 --- a/gen/midas.py +++ b/gen/midas.py @@ -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 diff --git a/midas/ast/midas.py b/midas/ast/midas.py index eae434a..2a822e5 100644 --- a/midas/ast/midas.py +++ b/midas/ast/midas.py @@ -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 diff --git a/midas/ast/printer/midas.py b/midas/ast/printer/midas.py index cbb62d7..56d7ce8 100644 --- a/midas/ast/printer/midas.py +++ b/midas/ast/printer/midas.py @@ -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)}" diff --git a/midas/ast/printer/midas_ast.py b/midas/ast/printer/midas_ast.py index 69a0b16..d2e5daf 100644 --- a/midas/ast/printer/midas_ast.py +++ b/midas/ast/printer/midas_ast.py @@ -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(): diff --git a/midas/checker/midas.py b/midas/checker/midas.py index e8cf791..02eb547 100644 --- a/midas/checker/midas.py +++ b/midas/checker/midas.py @@ -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), diff --git a/midas/checker/registry.py b/midas/checker/registry.py index c30c5e4..0c97074 100644 --- a/midas/checker/registry.py +++ b/midas/checker/registry.py @@ -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) diff --git a/midas/checker/types.py b/midas/checker/types.py index 5b043bc..ae56374 100644 --- a/midas/checker/types.py +++ b/midas/checker/types.py @@ -113,28 +113,6 @@ class OverloadedFunction: return "" -@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 diff --git a/midas/cli/highlighter.py b/midas/cli/highlighter.py index 15f3251..2db4637 100644 --- a/midas/cli/highlighter.py +++ b/midas/cli/highlighter.py @@ -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) diff --git a/midas/cli/hl_midas.css b/midas/cli/hl_midas.css index fabb84e..3580132 100644 --- a/midas/cli/hl_midas.css +++ b/midas/cli/hl_midas.css @@ -7,8 +7,7 @@ span { &.named-type, &.generic-type, - &.constraint-type, - &.complex-type { + &.constraint-type { --col: 150, 150, 150; } diff --git a/midas/generator/generator.py b/midas/generator/generator.py index 35634a5..18885a4 100644 --- a/midas/generator/generator.py +++ b/midas/generator/generator.py @@ -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() diff --git a/midas/generator/stubs.py b/midas/generator/stubs.py index f185f97..b228916 100644 --- a/midas/generator/stubs.py +++ b/midas/generator/stubs.py @@ -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) diff --git a/midas/parser/midas.py b/midas/parser/midas.py index 6678dbc..fef0e97 100644 --- a/midas/parser/midas.py +++ b/midas/parser/midas.py @@ -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 diff --git a/tests/serializer/midas.py b/tests/serializer/midas.py index 13fcbaa..599482b 100644 --- a/tests/serializer/midas.py +++ b/tests/serializer/midas.py @@ -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",