from enum import Enum, auto from position import Node from typing import Optional, List class Pattern: def __str__(self) -> str: raise NotImplementedError() class PatternError(Pattern): def __init__(self, message: str) -> None: super().__init__() self.message = message class Expr: def __str__(self) -> str: raise NotImplementedError() class ExprError(Expr): def __init__(self, message: str) -> None: super().__init__() self.message = message def __str__(self) -> str: return f"ErrorExpr({self.message})" class Id(Expr): def __init__(self, value: str) -> None: super().__init__() self.value = value def __str__(self) -> str: return f"Id({self.value})" class Int(Expr): def __init__(self, value: int) -> None: super().__init__() self.value = value def __str__(self) -> str: return f"Int({self.value})" class Char(Expr): def __init__(self, value: str) -> None: super().__init__() self.value = value def __str__(self) -> str: return f"Char('{self.value}')" class String(Expr): def __init__(self, value: str) -> None: super().__init__() self.value = value def __str__(self) -> str: return f"String(\"{self.value}\")" class Bool(Expr): def __init__(self, value: bool) -> None: super().__init__() self.value = value def __str__(self) -> str: value = "true" if self.value else "false" return f"Bool({value})" class Unit(Expr): def __init__(self) -> None: super().__init__() def __str__(self) -> str: return "Unit" class Block(Expr): def __init__(self, statements: List[Node[Expr]], value: Optional[Node[Expr]]) -> None: super().__init__() self.statements = statements self.value = value def __str__(self) -> str: statements = ", ".join(node.__str__() for node in self.statements) return f"Block {{ statements: [{statements}], value: {self.value} }}" class If(Expr): def __init__(self, condition: Node[Expr], truthy: Node[Expr], falsy: Optional[Node[Expr]]) -> None: super().__init__() self.condition = condition self.truthy = truthy self.falsy = falsy def __str__(self) -> str: return f"If {{ condition: {self.condition}, truthy: {self.truthy}, falsy: {self.falsy} }}" class MatchArm: def __init__(self, pattern: Node[Pattern], expr: Node[Expr]) -> None: self.pattern = pattern self.expr = expr class Match(Expr): def __init__(self, value: Node[Expr], arms: List[Node[MatchArm]]) -> None: super().__init__() self.value = value self.arms = arms class Loop(Expr): def __init__(self, body: Node[Expr]) -> None: super().__init__() self.body = body def __str__(self) -> str: return f"Loop {{ body: {self.body} }}" class While(Expr): def __init__(self, condition: Node[Expr], body: Node[Expr]) -> None: super().__init__() self.condition = condition self.body = body def __str__(self) -> str: return f"While {{ condition: {self.condition}, body: {self.body} }}" class For(Expr): def __init__(self, subject: Node[Pattern], value: Node[Expr], body: Node[Expr]) -> None: super().__init__() self.subject = subject self.value = value self.body = body def __str__(self) -> str: return f"For {{ subject: {self.subject}, value: {self.value}, body: {self.body} }}" class StructMember(Expr): def __init__(self, subject: Node[Expr], member_id: str) -> None: super().__init__() self.subject = subject self.member_id = member_id def __str__(self) -> str: return f"StructMember {{ subject: {self.subject}, member_id: {self.member_id} }}" class TupleMember(Expr): def __init__(self, subject: Node[Expr], member_index: int) -> None: super().__init__() self.subject = subject self.member_index = member_index def __str__(self) -> str: return f"StructMember {{ subject: {self.subject}, member_index: {self.member_index} }}" class Index(Expr): def __init__(self, subject: Node[Expr], value: Node[Expr]) -> None: super().__init__() self.subject = subject self.value = value def __str__(self) -> str: return f"Index {{ subject: {self.subject}, value: {self.value} }}" class Call(Expr): def __init__(self, subject: Node[Expr], arguments: List[Node[Expr]]) -> None: super().__init__() self.subject = subject self.arguments = arguments def __str__(self) -> str: arguments = ", ".join(node.__str__() for node in self.arguments) return f"Index {{ subject: {self.subject}, arguments: {arguments} }}" class UnaryType(Enum): Not = auto() Negate = auto() Reference = auto() ReferenceMut = auto() Dereference = auto() class Unary(Expr): def __init__(self, unary_type: UnaryType, subject: Node[Expr]) -> None: super().__init__() self.unary_type = unary_type self.subject = subject def __str__(self) -> str: return f"Unary {{ unary_type: {self.unary_type}, subject: {self.subject} }}" class BinaryType(Enum): And = auto() Or = auto() Add = auto() Subtract = auto() Multiply = auto() Divide = auto() Modulo = auto() Exponent = auto() Equal = auto() Inequal = auto() LT = auto() GT = auto() LTEqual = auto() GTEqual = auto() In = auto() class Binary(Expr): def __init__(self, binary_type: BinaryType, left: Node[Expr], right: Node[Expr]) -> None: super().__init__() self.binary_type = binary_type self.left = left self.right = right def __str__(self) -> str: return f"Binary {{ binary_type: {self.binary_type}, left: {self.left}, right: {self.right} }}" class AssignType(Enum): Assign = auto() Add = auto() Subtract = auto() Multiply = auto() Divide = auto() Modulo = auto() class Assign(Expr): def __init__(self, assign_type: AssignType, subject: Node[Expr], value: Node[Expr]) -> None: super().__init__() self.assign_type = assign_type self.subject = subject self.value = value def __str__(self) -> str: return f"Assign {{ assign_type: {self.assign_type}, subject: {self.subject}, value: {self.value} }}"