166 lines
3.7 KiB
Python
166 lines
3.7 KiB
Python
from __future__ import annotations
|
|
|
|
from abc import ABC, abstractmethod
|
|
from dataclasses import dataclass
|
|
from typing import TypeVar, Generic, Optional
|
|
|
|
from src.ast.expr import Expr
|
|
from src.token import Token
|
|
|
|
T = TypeVar("T")
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class Stmt(ABC):
|
|
@abstractmethod
|
|
def accept(self, visitor: Visitor[T]) -> T:
|
|
...
|
|
|
|
class Visitor(ABC, Generic[T]):
|
|
@abstractmethod
|
|
def visit_block_stmt(self, stmt: BlockStmt) -> T:
|
|
...
|
|
|
|
@abstractmethod
|
|
def visit_class_stmt(self, stmt: ClassStmt) -> T:
|
|
...
|
|
|
|
@abstractmethod
|
|
def visit_expression_stmt(self, stmt: ExpressionStmt) -> T:
|
|
...
|
|
|
|
@abstractmethod
|
|
def visit_function_stmt(self, stmt: FunctionStmt) -> T:
|
|
...
|
|
|
|
@abstractmethod
|
|
def visit_if_stmt(self, stmt: IfStmt) -> T:
|
|
...
|
|
|
|
@abstractmethod
|
|
def visit_return_stmt(self, stmt: ReturnStmt) -> T:
|
|
...
|
|
|
|
@abstractmethod
|
|
def visit_let_stmt(self, stmt: LetStmt) -> T:
|
|
...
|
|
|
|
@abstractmethod
|
|
def visit_while_stmt(self, stmt: WhileStmt) -> T:
|
|
...
|
|
|
|
@abstractmethod
|
|
def visit_for_stmt(self, stmt: ForStmt) -> T:
|
|
...
|
|
|
|
@abstractmethod
|
|
def visit_break_stmt(self, stmt: BreakStmt) -> T:
|
|
...
|
|
|
|
@abstractmethod
|
|
def visit_continue_stmt(self, stmt: ContinueStmt) -> T:
|
|
...
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class BlockStmt(Stmt):
|
|
statements: list[Stmt]
|
|
|
|
def accept(self, visitor: Stmt.Visitor[T]) -> T:
|
|
return visitor.visit_block_stmt(self)
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class ClassStmt(Stmt):
|
|
name: Token
|
|
methods: list[FunctionStmt]
|
|
|
|
def accept(self, visitor: Stmt.Visitor[T]) -> T:
|
|
return visitor.visit_class_stmt(self)
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class ExpressionStmt(Stmt):
|
|
expression: Expr
|
|
|
|
def accept(self, visitor: Stmt.Visitor[T]) -> T:
|
|
return visitor.visit_expression_stmt(self)
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class FunctionStmt(Stmt):
|
|
name: Token
|
|
params: list[Token]
|
|
body: list[Stmt]
|
|
|
|
def accept(self, visitor: Stmt.Visitor[T]) -> T:
|
|
return visitor.visit_function_stmt(self)
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class IfStmt(Stmt):
|
|
condition: Expr
|
|
then_branch: Stmt
|
|
else_branch: Optional[Stmt]
|
|
|
|
def accept(self, visitor: Stmt.Visitor[T]) -> T:
|
|
return visitor.visit_if_stmt(self)
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class ReturnStmt(Stmt):
|
|
keyword: Token
|
|
value: Optional[Expr]
|
|
|
|
def accept(self, visitor: Stmt.Visitor[T]) -> T:
|
|
return visitor.visit_return_stmt(self)
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class LetStmt(Stmt):
|
|
name: Token
|
|
initializer: Optional[Expr]
|
|
|
|
def accept(self, visitor: Stmt.Visitor[T]) -> T:
|
|
return visitor.visit_let_stmt(self)
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class WhileStmt(Stmt):
|
|
condition: Expr
|
|
body: Stmt
|
|
|
|
def accept(self, visitor: Stmt.Visitor[T]) -> T:
|
|
return visitor.visit_while_stmt(self)
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class ForStmt(Stmt):
|
|
variable: Token
|
|
start_token: Optional[Token]
|
|
start: Optional[Expr]
|
|
end_token: Optional[Token]
|
|
end: Optional[Expr]
|
|
step_token: Optional[Token]
|
|
step: Optional[Expr]
|
|
body: Stmt
|
|
|
|
def accept(self, visitor: Stmt.Visitor[T]) -> T:
|
|
return visitor.visit_for_stmt(self)
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class BreakStmt(Stmt):
|
|
keyword: Token
|
|
|
|
def accept(self, visitor: Stmt.Visitor[T]) -> T:
|
|
return visitor.visit_break_stmt(self)
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class ContinueStmt(Stmt):
|
|
keyword: Token
|
|
|
|
def accept(self, visitor: Stmt.Visitor[T]) -> T:
|
|
return visitor.visit_continue_stmt(self)
|