diff --git a/libserene/include/serene/errors.h b/libserene/include/serene/errors.h index 94f1f2e..d5403db 100644 --- a/libserene/include/serene/errors.h +++ b/libserene/include/serene/errors.h @@ -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 #include @@ -32,6 +34,33 @@ class SereneContext; namespace serene::errors { +class SERENE_EXPORT SereneError : public llvm::ErrorInfo { +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 SERENE_EXPORT llvm::Error makeError(SereneContext &ctx, ErrorType errtype, Args &&...args) { - return llvm::make_error(ctx, errtype, std::forward(args)...); + return llvm::make_error(ctx, errtype, + std::forward(args)...); }; /// Returns the messange that the given error \p e is holding. It doesn't cast diff --git a/libserene/include/serene/errors/base.h b/libserene/include/serene/errors/base.h deleted file mode 100644 index 99fafad..0000000 --- a/libserene/include/serene/errors/base.h +++ /dev/null @@ -1,63 +0,0 @@ -/* -*- C++ -*- - * Serene Programming Language - * - * Copyright (c) 2019-2022 Sameer Rahmani - * - * 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 . - */ - -#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 - -#include -#include - -namespace serene::errors { - -class SERENE_EXPORT Error : public llvm::ErrorInfo { -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 diff --git a/libserene/include/serene/errors/constants.h b/libserene/include/serene/errors/constants.h deleted file mode 100644 index 75627a8..0000000 --- a/libserene/include/serene/errors/constants.h +++ /dev/null @@ -1,124 +0,0 @@ -/* -*- C++ -*- - * Serene Programming Language - * - * Copyright (c) 2019-2022 Sameer Rahmani - * - * 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 . - */ - -#ifndef SERENE_ERRORS_CONSTANTS_H -#define SERENE_ERRORS_CONSTANTS_H - -#include - -#include -#include -#include - -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 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 diff --git a/libserene/include/serene/errors/errc.h b/libserene/include/serene/errors/errc.h deleted file mode 100644 index b6f081e..0000000 --- a/libserene/include/serene/errors/errc.h +++ /dev/null @@ -1,77 +0,0 @@ -/* -*- C++ -*- - * Serene Programming Language - * - * Copyright (c) 2019-2022 Sameer Rahmani - * - * 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 . - */ - -#ifndef SERENE_ERRORS_ERRC_H -#define SERENE_ERRORS_ERRC_H - -#include - -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(E), std::generic_category()); -}; - -}; // namespace serene - -#endif diff --git a/libserene/lib/errors.cpp b/libserene/lib/errors.cpp index 5c83de7..5ef7792 100644 --- a/libserene/lib/errors.cpp +++ b/libserene/lib/errors.cpp @@ -18,15 +18,13 @@ #include "serene/errors.h" -#include "serene/errors/base.h" - #include #include 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; diff --git a/libserene/tests/errors/error_tests.cpp.inc b/libserene/tests/errors/error_tests.cpp.inc index 49efbb5..2ce1b4a 100644 --- a/libserene/tests/errors/error_tests.cpp.inc +++ b/libserene/tests/errors/error_tests.cpp.inc @@ -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); } diff --git a/libserene/tests/test_helpers.cpp.inc b/libserene/tests/test_helpers.cpp.inc index e321069..63ed325 100644 --- a/libserene/tests/test_helpers.cpp.inc +++ b/libserene/tests/test_helpers.cpp.inc @@ -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 {