feat: remove complex and extension types
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)}"
|
||||
|
||||
@@ -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():
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -7,8 +7,7 @@ span {
|
||||
|
||||
&.named-type,
|
||||
&.generic-type,
|
||||
&.constraint-type,
|
||||
&.complex-type {
|
||||
&.constraint-type {
|
||||
--col: 150, 150, 150;
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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",
|
||||
|
||||
Reference in New Issue
Block a user