#include "pac_exception.h"

#include "pac_expr.h"
#include "pac_id.h"
#include "pac_utils.h"

Exception::Exception(const Object* o, string msg) {
    if ( o ) {
        msg_ = o->Location();
        msg_ += ": error : ";
    }

    msg_ += msg;

    if ( FLAGS_pac_debug ) {
        DEBUG_MSG("Exception: %s\n", msg_.c_str());
        abort();
    }
}

ExceptionIDNotFound::ExceptionIDNotFound(const ID* id) : Exception(id), id_(id) {
    append(strfmt("`%s' undeclared", id_->Name()));
}

ExceptionIDRedefinition::ExceptionIDRedefinition(const ID* id) : Exception(id), id_(id) {
    append(strfmt("`%s' redefined", id_->Name()));
}

ExceptionIDNotEvaluated::ExceptionIDNotEvaluated(const ID* id) : Exception(id), id_(id) {
    append(strfmt("ID `%s' not evaluated before used", id->Name()));
}

ExceptionIDNotField::ExceptionIDNotField(const ID* id) : Exception(id), id_(id) {
    append(strfmt("ID `%s' is not a field", id_->Name()));
}

ExceptionMemberNotFound::ExceptionMemberNotFound(const ID* type_id, const ID* member_id)
    : Exception(member_id), type_id_(type_id), member_id_(member_id) {
    append(strfmt("type %s does not have member `%s'", type_id_->Name(), member_id_->Name()));
}

ExceptionCyclicDependence::ExceptionCyclicDependence(const ID* id) : Exception(id), id_(id) {
    append(strfmt("cyclic dependence through `%s'", id_->Name()));
}

ExceptionPaddingError::ExceptionPaddingError(const Object* o, string msg) : Exception(o) { append(msg.c_str()); }

ExceptionNonConstExpr::ExceptionNonConstExpr(const Expr* expr) : Exception(expr), expr(expr) {
    append(strfmt("Expression `%s' is not constant", expr->orig()));
}

ExceptionInvalidCaseSizeExpr::ExceptionInvalidCaseSizeExpr(const Expr* expr) : Exception(expr), expr(expr) {
    append(strfmt("Expression `%s' is greater than the 32-bit limit for use as a case index", expr->orig()));
}

ExceptionInvalidCaseLimitExpr::ExceptionInvalidCaseLimitExpr(const Expr* expr) : Exception(expr), expr(expr) {
    append(
        strfmt("Expression `%s' as a case index is outside the numeric limit of the type used "
               "for the switch expression",
               expr->orig()));
}
