# Copyright (C) 2022-2023 Exaloop Inc. <https://exaloop.io>

# Warning(!): This type must be consistent with the exception
# header type defined in runtime/exc.cpp.
class BaseException:
    typename: str
    message: str
    func: str
    file: str
    line: int
    col: int

    def __init__(self, typename: str, message: str = ""):
        self.typename = typename
        self.message = message
        self.func = ""
        self.file = ""
        self.line = 0
        self.col = 0

    def __str__(self):
        return self.message

    def __repr__(self):
        return f'{self.typename}({self.message.__repr__()})'

class Exception(Static[BaseException]):
    def __init__(self, typename: str, msg: str = ""):
        super().__init__(typename, msg)

class NameError(Static[Exception]):
    def __init__(self, message: str = ""):
        super().__init__("NameError", message)

class OSError(Static[Exception]):
    def __init__(self, message: str = ""):
        super().__init__("OSError", message)

class IOError(Static[Exception]):
    def __init__(self, message: str = ""):
        super().__init__("IOError", message)

class ValueError(Static[Exception]):
    def __init__(self, message: str = ""):
        super().__init__("ValueError", message)

class IndexError(Static[Exception]):
    def __init__(self, message: str = ""):
        super().__init__("IndexError", message)

class KeyError(Static[Exception]):
    def __init__(self, message: str = ""):
        super().__init__("KeyError", message)

class OverflowError(Static[Exception]):
    def __init__(self, message: str = ""):
        super().__init__("OverflowError", message)

class CError(Static[Exception]):
    def __init__(self, message: str = ""):
        super().__init__("CError", message)

class PyError(Static[Exception]):
    pytype: pyobj

    def __init__(self, message: str, pytype: pyobj):
        super().__init__("PyError", message)
        self.pytype = pytype

class TypeError(Static[Exception]):
    def __init__(self, message: str = ""):
        super().__init__("TypeError", message)

class ZeroDivisionError(Static[Exception]):
    def __init__(self, message: str = ""):
        super().__init__("ZeroDivisionError", message)

class AttributeError(Static[Exception]):
    def __init__(self, message: str = ""):
        super().__init__("AttributeError", message)

class NotImplementedError(Static[Exception]):
    def __init__(self, message: str = ""):
        super().__init__("NotImplementedError", message)

class StopIteration(Static[Exception]):
    def __init__(self, message: str = ""):
        super().__init__("StopIteration", message)

class AssertionError(Static[Exception]):
    def __init__(self, message: str = ""):
        super().__init__("AssertionError", message)

class SystemExit(Static[BaseException]):
    _status: int

    def __init__(self, message: str = "", status: int = 0):
        super().__init__("SystemExit", message)
        self._status = status

    def __init__(self, status: int):
        self.__init__("", status)

    @property
    def status(self):
        return self._status
