class AxelError(Exception):
    pass

class AxelUserError(Exception):
    pass

class InternalError(AxelError):
    def __init__(self, msg):
        self.message = "Internal error: " + msg

# ___________________________________________________________________________
# Runtime errors

class AxelRuntimeError(AxelUserError):
    pass

class ApplicationToNonFunction(AxelRuntimeError):
    def __init__(self, loc, w_value, w_args):
        self.message = "The value '%s' is not a function, but it was invoked with arguments '%s'" % (w_value, w_args)
        self.loc = loc
        self.w_value = w_value
        self.w_args = w_args

class NoMatchingFunction(AxelRuntimeError):
    def __init__(self, loc, w_values):
        self.message = "No function applicable to %s found" % (w_values,)
        self.loc = loc
        self.w_values = w_values

class TooManyArguments(AxelRuntimeError):
    def __init__(self, loc, expected, actual):
        self.message = "%d arguments supplied, but a max of %d expected" % (
            actual, expected)
        self.loc = loc
        self.expected = expected
        self.actual = actual

class AmbiguousApplication(AxelRuntimeError):
    def __init__(self, loc, amb_funcs, w_values):
        self.loc = loc
        self.message = (
            "Ambiguous application, cannot distinguish between "
            "%s when applied to (%s)" %
            (
            " and ".join([str(a) for a in amb_funcs]),
            ", ".join([str(w_value) for w_value in w_values]),
            ))
        self.amb_funcs = amb_funcs

class CannotWrap(AxelRuntimeError):
    def __init__(self, pyval):
        self.message = "Cannot wrap %r (%s)" % (pyval, type(pyval))
        self.pyval = pyval

class InvalidPatternReturnValue(AxelRuntimeError):
    def __init__(self, loc, w_value):
        self.message = "Pattern function must return boolean or tuple, not '%s'"
        self.message = self.message % (w_value,)
        self.loc = loc
        self.w_value = w_value

# ___________________________________________________________________________
# Parse errors

class LexError(AxelUserError):
    def __init__(self, loc):
        self.loc = loc
        
class NoTabsError(LexError):
    pass

class InvalidIndentationError(LexError):
    pass

# ___________________________________________________________________________
# Semantic errors

class AxelSemanticError(AxelUserError):
    pass

class CircularOpenEndedImport(AxelSemanticError):
    def __init__(self, locs):
        pass

class ImportNotFound(AxelSemanticError):
    def __init__(self, loc, nm):
        self.message = "No module matching '%s' found" % nm
        self.loc = loc

class CanNotImportDirectory(AxelSemanticError):
    def __init__(self, loc, nm):
        pass
    
class UnknownIdentifier(AxelSemanticError):
    def __init__(self, loc, nm):
        self.message = "Unknown identifier '%s'" % nm
        self.loc = loc
        self.nm = nm

class UnitSuperTypeRedefined(AxelSemanticError):
    def __init__(self, loc):
        pass

class UnitVarNotAllowedHere(AxelSemanticError):
    def __init__(self, loc):
        self.message = "Unit var not allowed here"
        self.loc = loc

class UnitRaiseInfNotAllowedHere(AxelSemanticError):
    def __init__(self, loc):
        self.message = "Units cannot be raised infinitely here"
        self.loc = loc

class ComplexUnitsCannotBeRaisedInfinitly(AxelSemanticError):
    def __init__(self, loc):
        self.message = "Only Unit Atoms can be raised indefinitely"
        self.loc = loc
    
class UnitRaisedToNonInt(AxelSemanticError):
    def __init__(self, loc, w_value):
        self.message = "Units should be raised to integers, not %s"
        self.loc = loc
        self.w_value = w_value

class ExpectedUnit(AxelSemanticError):
    def __init__(self, loc):
        self.message = "Expected a unit here"
        self.loc = loc
    
class ExpectedUnitAtom(AxelSemanticError):
    def __init__(self, loc, unit):
        self.message = "Expected atomic unit but found %s" % (unit,)
        self.loc = loc
        self.unit = unit
    
class ExpectedValue(AxelSemanticError):
    def __init__(self, loc):
        self.message = "Expected a value but found a unit"
        self.loc = loc

class ExpectedFuncValue(AxelSemanticError):
    def __init__(self, loc):
        self.message = "Expected function value"
        self.loc = loc
    
class NestedFuncsMustBeUnqualified(AxelSemanticError):
    def __init__(self, loc):
        self.message = "Nested function names must be unqualified"
        self.loc = loc
    
class UnknownType(AxelSemanticError):
    def __init__(self, loc, id):
        pass

class DuplicateVariable(AxelSemanticError):
    def __init__(self, loc, name):
        pass

class NotUnit(AxelSemanticError):
    def __init__(self, loc, ident):
        pass

class NoMainFunction(AxelSemanticError):
    def __init__(self):
        pass

class CannotMerge(AxelSemanticError):
    def __init__(self, loc, loc2, name):
        self.message = ("Cannot merge this definition "
                        "for '%s' with the one at %s") % (
            name, loc2)
        self.loc = loc
        self.loc2 = loc2
        self.name = name


