"""Classes for representing match statement patterns.""" from __future__ import annotations from typing import TypeVar from mypy_extensions import trait from mypy.nodes import Expression, NameExpr, Node, RefExpr from mypy.visitor import PatternVisitor T = TypeVar("T") @trait class Pattern(Node): """A pattern node.""" __slots__ = () def accept(self, visitor: PatternVisitor[T]) -> T: raise RuntimeError("Not implemented", type(self)) class AsPattern(Pattern): """The pattern as """ # The python ast, and therefore also our ast merges capture, wildcard and as patterns into one # for easier handling. # If pattern is None this is a capture pattern. If name and pattern are both none this is a # wildcard pattern. # Only name being None should not happen but also won't break anything. pattern: Pattern | None name: NameExpr | None def __init__(self, pattern: Pattern | None, name: NameExpr | None) -> None: super().__init__() self.pattern = pattern self.name = name def accept(self, visitor: PatternVisitor[T]) -> T: return visitor.visit_as_pattern(self) class OrPattern(Pattern): """The pattern | | ...""" patterns: list[Pattern] def __init__(self, patterns: list[Pattern]) -> None: super().__init__() self.patterns = patterns def accept(self, visitor: PatternVisitor[T]) -> T: return visitor.visit_or_pattern(self) class ValuePattern(Pattern): """The pattern x.y (or x.y.z, ...)""" expr: Expression def __init__(self, expr: Expression) -> None: super().__init__() self.expr = expr def accept(self, visitor: PatternVisitor[T]) -> T: return visitor.visit_value_pattern(self) class SingletonPattern(Pattern): # This can be exactly True, False or None value: bool | None def __init__(self, value: bool | None) -> None: super().__init__() self.value = value def accept(self, visitor: PatternVisitor[T]) -> T: return visitor.visit_singleton_pattern(self) class SequencePattern(Pattern): """The pattern [, ...]""" patterns: list[Pattern] def __init__(self, patterns: list[Pattern]) -> None: super().__init__() self.patterns = patterns def accept(self, visitor: PatternVisitor[T]) -> T: return visitor.visit_sequence_pattern(self) class StarredPattern(Pattern): # None corresponds to *_ in a list pattern. It will match multiple items but won't bind them to # a name. capture: NameExpr | None def __init__(self, capture: NameExpr | None) -> None: super().__init__() self.capture = capture def accept(self, visitor: PatternVisitor[T]) -> T: return visitor.visit_starred_pattern(self) class MappingPattern(Pattern): keys: list[Expression] values: list[Pattern] rest: NameExpr | None def __init__( self, keys: list[Expression], values: list[Pattern], rest: NameExpr | None ) -> None: super().__init__() assert len(keys) == len(values) self.keys = keys self.values = values self.rest = rest def accept(self, visitor: PatternVisitor[T]) -> T: return visitor.visit_mapping_pattern(self) class ClassPattern(Pattern): """The pattern Cls(...)""" class_ref: RefExpr positionals: list[Pattern] keyword_keys: list[str] keyword_values: list[Pattern] def __init__( self, class_ref: RefExpr, positionals: list[Pattern], keyword_keys: list[str], keyword_values: list[Pattern], ) -> None: super().__init__() assert len(keyword_keys) == len(keyword_values) self.class_ref = class_ref self.positionals = positionals self.keyword_keys = keyword_keys self.keyword_values = keyword_values def accept(self, visitor: PatternVisitor[T]) -> T: return visitor.visit_class_pattern(self)