from dataclasses import dataclass, field
from typing import List, Optional


@dataclass
class ASTNode:
    pass


@dataclass
class Module(ASTNode):
    name: str
    port_list: List['Port'] = field(default_factory=list)
    declarations: List['Declaration'] = field(default_factory=list)
    statements: List['Statement'] = field(default_factory=list)


@dataclass
class Port(ASTNode):
    name: str
    direction: str
    width: Optional[int] = None


@dataclass
class Declaration(ASTNode):
    pass


@dataclass
class WireDeclaration(Declaration):
    name: str
    width: Optional[int] = None


@dataclass
class RegDeclaration(Declaration):
    name: str
    width: Optional[int] = None


@dataclass
class Statement(ASTNode):
    pass


@dataclass
class Assign(Statement):
    left: 'Expression'
    right: 'Expression'


@dataclass
class Always(Statement):
    sensitivity_list: List[str]
    body: List[Statement]


@dataclass
class Expression(ASTNode):
    pass


@dataclass
class Identifier(Expression):
    name: str


@dataclass
class Number(Expression):
    value: str


@dataclass
class BinaryOp(Expression):
    left: Expression
    operator: str
    right: Expression


@dataclass
class UnaryOp(Expression):
    operator: str
    operand: Expression
