Rename to and remove cleanup the source tree for errors

This commit is contained in:
Sameer Rahmani 2022-03-10 19:48:33 +00:00
parent 4605e22e68
commit a215eb6cd9
7 changed files with 46 additions and 281 deletions

View File

@ -19,9 +19,11 @@
#ifndef SERENE_ERRORS_H
#define SERENE_ERRORS_H
#include "serene/errors/base.h"
#include "serene/errors/errc.h"
#include "serene/export.h"
#include "serene/reader/location.h"
#define GET_CLASS_DEFS
#include "serene/errors/errs.h.inc"
#include <llvm/Support/Casting.h>
#include <llvm/Support/Error.h>
@ -32,6 +34,33 @@ class SereneContext;
namespace serene::errors {
class SERENE_EXPORT SereneError : public llvm::ErrorInfo<SereneError> {
public:
static char ID;
ErrorType errorType;
SereneContext &ctx;
reader::LocationRange location;
std::string msg;
void log(llvm::raw_ostream &os) const override { os << msg; }
std::error_code convertToErrorCode() const override {
// TODO: Fix this by creating a mapping from ErrorType to standard
// errc or return the ErrorType number instead
return std::make_error_code(std::errc::io_error);
}
SereneError(SereneContext &ctx, ErrorType errtype, reader::LocationRange &loc)
: errorType(errtype), ctx(ctx), location(loc){};
SereneError(SereneContext &ctx, ErrorType errtype, reader::LocationRange &loc,
llvm::StringRef msg)
: errorType(errtype), ctx(ctx), location(loc), msg(msg.str()){};
reader::LocationRange &where() { return location; };
};
/// Create and return a Serene flavored `llvm::Error` by passing the parameters
/// directly to the constructor of type `E`.
///
@ -39,7 +68,8 @@ namespace serene::errors {
template <typename... Args>
SERENE_EXPORT llvm::Error makeError(SereneContext &ctx, ErrorType errtype,
Args &&...args) {
return llvm::make_error<Error>(ctx, errtype, std::forward<Args>(args)...);
return llvm::make_error<SereneError>(ctx, errtype,
std::forward<Args>(args)...);
};
/// Returns the messange that the given error \p e is holding. It doesn't cast

View File

@ -1,63 +0,0 @@
/* -*- C++ -*-
* Serene Programming Language
*
* Copyright (c) 2019-2022 Sameer Rahmani <lxsameer@gnu.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 2.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SERENE_ERRORS_BASE_H
#define SERENE_ERRORS_BASE_H
#include "serene/export.h"
#include "serene/reader/location.h"
#define GET_CLASS_DEFS
#include "serene/errors/errs.h.inc"
#include <system_error>
#include <llvm/Support/Error.h>
#include <llvm/Support/FormatVariadic.h>
namespace serene::errors {
class SERENE_EXPORT Error : public llvm::ErrorInfo<Error> {
public:
static char ID;
ErrorType errorType;
SereneContext &ctx;
reader::LocationRange location;
std::string msg;
void log(llvm::raw_ostream &os) const override { os << msg; }
std::error_code convertToErrorCode() const override {
// TODO: Fix this by creating a mapping from ErrorType to standard
// errc or return the ErrorType number instead
return std::make_error_code(std::errc::io_error);
}
Error(SereneContext &ctx, ErrorType errtype, reader::LocationRange &loc)
: errorType(errtype), ctx(ctx), location(loc){};
Error(SereneContext &ctx, ErrorType errtype, reader::LocationRange &loc,
llvm::StringRef msg)
: errorType(errtype), ctx(ctx), location(loc), msg(msg.str()){};
reader::LocationRange &where() { return location; };
};
}; // namespace serene::errors
#endif

View File

@ -1,124 +0,0 @@
/* -*- C++ -*-
* Serene Programming Language
*
* Copyright (c) 2019-2022 Sameer Rahmani <lxsameer@gnu.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 2.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SERENE_ERRORS_CONSTANTS_H
#define SERENE_ERRORS_CONSTANTS_H
#include <llvm/Support/FormatVariadic.h>
#include <map>
#include <string>
#include <utility>
namespace serene {
namespace errors {
/// This enum represent the expression type and **not** the value type.
enum class ErrType {
Syntax,
Semantic,
Compile,
};
enum ErrID {
E0000 = 0,
E0001,
E0002,
E0003,
E0004,
E0005,
E0006,
E0007,
E0008,
E0009,
E0010,
E0011,
E0012,
E0013,
E0014,
};
struct ErrorVariant {
ErrID id;
std::string description;
std::string longDescription;
ErrorVariant(ErrID id, std::string desc, std::string longDesc)
: id(id), description(std::move(desc)),
longDescription(std::move(longDesc)){};
std::string getErrId() { return llvm::formatv("E{0:d}", id); };
};
static ErrorVariant
UnknownError(E0000, "Can't find any description for this error.", "");
static ErrorVariant
DefExpectSymbol(E0001, "The first argument to 'def' has to be a Symbol.",
"");
static ErrorVariant DefWrongNumberOfArgs(
E0002, "Wrong number of arguments is passed to the 'def' form.", "");
static ErrorVariant FnNoArgsList(E0003, "'fn' form requires an argument list.",
"");
static ErrorVariant FnArgsMustBeList(E0004, "'fn' arguments should be a list.",
"");
static ErrorVariant CantResolveSymbol(E0005, "Can't resolve the given name.",
"");
static ErrorVariant
DontKnowHowToCallNode(E0006, "Don't know how to call the given expression.",
"");
static ErrorVariant PassFailureError(E0007, "Pass Failure.", "");
static ErrorVariant NSLoadError(E0008, "Faild to find a namespace.", "");
static ErrorVariant
NSAddToSMError(E0009, "Faild to add the namespace to the source manager.",
"");
static ErrorVariant
EOFWhileScaningAList(E0010, "EOF reached before closing of list", "");
static ErrorVariant InvalidDigitForNumber(E0011, "Invalid digit for a number.",
"");
static ErrorVariant
TwoFloatPoints(E0012, "Two or more float point characters in a number", "");
static ErrorVariant
InvalidCharacterForSymbol(E0013, "Invalid character for a symbol", "");
static ErrorVariant CompilationError(E0014, "Compilation error!", "");
static std::map<ErrID, ErrorVariant *> ErrDesc = {
{E0000, &UnknownError}, {E0001, &DefExpectSymbol},
{E0002, &DefWrongNumberOfArgs}, {E0003, &FnNoArgsList},
{E0004, &FnArgsMustBeList}, {E0005, &CantResolveSymbol},
{E0006, &DontKnowHowToCallNode}, {E0007, &PassFailureError},
{E0008, &NSLoadError}, {E0009, &NSAddToSMError},
{E0010, &EOFWhileScaningAList}, {E0011, &InvalidDigitForNumber},
{E0012, &TwoFloatPoints}, {E0013, &InvalidCharacterForSymbol},
{E0014, &CompilationError}};
} // namespace errors
} // namespace serene
#endif

View File

@ -1,77 +0,0 @@
/* -*- C++ -*-
* Serene Programming Language
*
* Copyright (c) 2019-2022 Sameer Rahmani <lxsameer@gnu.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 2.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SERENE_ERRORS_ERRC_H
#define SERENE_ERRORS_ERRC_H
#include <llvm/Support/Errc.h>
namespace serene {
/// A collection of common error codes in Serene
enum class errc {
argument_list_too_long = int(std::errc::argument_list_too_long),
argument_out_of_domain = int(std::errc::argument_out_of_domain),
bad_address = int(std::errc::bad_address),
bad_file_descriptor = int(std::errc::bad_file_descriptor),
broken_pipe = int(std::errc::broken_pipe),
device_or_resource_busy = int(std::errc::device_or_resource_busy),
directory_not_empty = int(std::errc::directory_not_empty),
executable_format_error = int(std::errc::executable_format_error),
file_exists = int(std::errc::file_exists),
file_too_large = int(std::errc::file_too_large),
filename_too_long = int(std::errc::filename_too_long),
function_not_supported = int(std::errc::function_not_supported),
illegal_byte_sequence = int(std::errc::illegal_byte_sequence),
inappropriate_io_control_operation =
int(std::errc::inappropriate_io_control_operation),
interrupted = int(std::errc::interrupted),
invalid_argument = int(std::errc::invalid_argument),
invalid_seek = int(std::errc::invalid_seek),
io_error = int(std::errc::io_error),
is_a_directory = int(std::errc::is_a_directory),
no_child_process = int(std::errc::no_child_process),
no_lock_available = int(std::errc::no_lock_available),
no_space_on_device = int(std::errc::no_space_on_device),
no_such_device_or_address = int(std::errc::no_such_device_or_address),
no_such_device = int(std::errc::no_such_device),
no_such_file_or_directory = int(std::errc::no_such_file_or_directory),
no_such_process = int(std::errc::no_such_process),
not_a_directory = int(std::errc::not_a_directory),
not_enough_memory = int(std::errc::not_enough_memory),
not_supported = int(std::errc::not_supported),
operation_not_permitted = int(std::errc::operation_not_permitted),
permission_denied = int(std::errc::permission_denied),
read_only_file_system = int(std::errc::read_only_file_system),
resource_deadlock_would_occur = int(std::errc::resource_deadlock_would_occur),
resource_unavailable_try_again =
int(std::errc::resource_unavailable_try_again),
result_out_of_range = int(std::errc::result_out_of_range),
too_many_files_open_in_system = int(std::errc::too_many_files_open_in_system),
too_many_files_open = int(std::errc::too_many_files_open),
too_many_links = int(std::errc::too_many_links)
};
/// The **official way** to create `std::error_code` in context of Serene.
inline std::error_code make_error_code(errc E) {
return std::error_code(static_cast<int>(E), std::generic_category());
};
}; // namespace serene
#endif

View File

@ -18,15 +18,13 @@
#include "serene/errors.h"
#include "serene/errors/base.h"
#include <llvm/Support/Casting.h>
#include <llvm/Support/Error.h>
namespace serene::errors {
// We need this to make Error class a llvm::Error friendy implementation
char Error::ID;
char SereneError::ID;
std::string getMessage(const llvm::Error &e) {
std::string msg;

View File

@ -38,14 +38,15 @@ TEST_CASE("Serene Error construction", "[errors]") {
auto ctx = makeSereneContext();
llvm::Error err = makeError(*ctx, PassFailureError, *range, "test error");
auto unhandled = llvm::handleErrors(std::move(err), [&](const Error &e) {
REQUIRE(e.message() == "test error");
const auto *v = getVariant(e.errorType);
REQUIRE(v != nullptr);
CHECK(v->title == "PassFailureError");
CHECK(v->desc == "Pass Failure.");
CHECK(v->help.empty());
});
auto unhandled =
llvm::handleErrors(std::move(err), [&](const SereneError &e) {
REQUIRE(e.message() == "test error");
const auto *v = getVariant(e.errorType);
REQUIRE(v != nullptr);
CHECK(v->title == "PassFailureError");
CHECK(v->desc == "Pass Failure.");
CHECK(v->help.empty());
});
CHECK(!unhandled);
}

View File

@ -30,9 +30,9 @@
// `llvm::Error`s has to be checked in the same scope. This macro makes
// the check easy while were testing the other aspects of the error.
// `t` is the concrete error type and `e` is the error instance.
#define CHECK_ERR(t, e) \
auto unhandled = \
llvm::handleErrors(e, [&](const Error &x) { CHECK(x.errorType == t); }); \
#define CHECK_ERR(t, e) \
auto unhandled = llvm::handleErrors( \
e, [&](const SereneError &x) { CHECK(x.errorType == t); }); \
CHECK(!unhandled);
namespace serene {