from enum import Enum, auto from position import Node from typing import Optional, List from utils import escape_string class Type: def __str__(self) -> str: raise NotImplementedError() class TypeError(Type): def __init__(self, message: str) -> None: super().__init__() self.message = message class Pattern: def __str__(self) -> str: raise NotImplementedError() class PatternError(Pattern): def __init__(self, message: str) -> None: super().__init__() self.message = message class Parameter: def __init__(self, subject: Pattern, value_type: Type) -> None: self.subject = subject self.value_type = value_type def __str__(self) -> str: return f"Parameter {{ subject: {self.subject}, value_type: {self.value_type} }}" 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('{escape_string(self.value)}')" class String(Expr): def __init__(self, value: str) -> None: super().__init__() self.value = value def __str__(self) -> str: return f"String(\"{escape_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 Tuple(Expr): def __init__(self, values: List[Node[Expr]]) -> None: super().__init__() self.values = values def __str__(self) -> str: values = ", ".join(str(node) for node in self.values) return f"Tuple {{ values: [{values}] }}" 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(str(node) for node in self.statements) return f"Block {{ statements: [{statements}], value: {self.value} }}" class Lambda(Expr): def __init__(self, params: List[Node[Parameter]], body: Node[Expr]) -> None: super().__init__() self.params = params self.body = body def __str__(self) -> str: params = ", ".join(str(node) for node in self.params) return f"Lambda {{ params: [{params}], body: {self.body} }}" 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(str(node) 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} }}" class Let(Expr): def __init__(self, subject: Node[Pattern], value_type: Optional[Node[Type]], value: Node[Expr]) -> None: super().__init__() self.subject = subject self.value_type = value_type self.value = value def __str__(self) -> str: return f"Let {{ subject: {self.subject}, value_type: {self.value_type}, value: {self.value} }}" class Function(Expr): def __init__(self, subject_id: str, params: List[Node[Parameter]], body: Node[Expr]) -> None: super().__init__() self.subject_id = subject_id self.params = params self.body = body def __str__(self) -> str: params = ", ".join(str(node) for node in self.params) return f"Function {{ subject_id: {self.subject_id}, params: [{params}], body: {self.body} }}" class Return(Expr): def __init__(self, value: Optional[Node[Expr]]) -> None: super().__init__() self.value = value def __str__(self) -> str: return f"Return {{ value: {self.value} }}" class Break(Expr): def __init__(self, value: Optional[Node[Expr]]) -> None: super().__init__() self.value = value def __str__(self) -> str: return f"Break {{ value: {self.value} }}" class Continue(Expr): def __init__(self, value: Optional[Node[Expr]]) -> None: super().__init__() self.value = value def __str__(self) -> str: return f"Continue {{ value: {self.value} }}"