"""µFrame error types with source location tracking."""

from __future__ import annotations


class UFrameError(Exception):
    """Base error for all µFrame operations."""

    def __init__(self, message: str, line: int | None = None, col: int | None = None):
        self.line = line
        self.col = col
        loc = ""
        if line is not None:
            loc = f" (line {line}"
            if col is not None:
                loc += f", col {col}"
            loc += ")"
        super().__init__(f"{message}{loc}")


class ParseError(UFrameError):
    """Raised when .uf source cannot be parsed."""
    pass


class LayoutError(UFrameError):
    """Raised when layout constraints cannot be satisfied."""
    pass


class CompileWarning:
    """Non-fatal issue discovered during compilation."""

    __slots__ = ("message", "line", "col")

    def __init__(self, message: str, line: int | None = None, col: int | None = None):
        self.message = message
        self.line = line
        self.col = col

    def __repr__(self) -> str:
        loc = ""
        if self.line is not None:
            loc = f" line={self.line}"
        return f"CompileWarning({self.message!r}{loc})"
