diff options
Diffstat (limited to 'include/openvic-dataloader/DiagnosticLogger.hpp')
-rw-r--r-- | include/openvic-dataloader/DiagnosticLogger.hpp | 395 |
1 files changed, 0 insertions, 395 deletions
diff --git a/include/openvic-dataloader/DiagnosticLogger.hpp b/include/openvic-dataloader/DiagnosticLogger.hpp deleted file mode 100644 index bd8f9cc..0000000 --- a/include/openvic-dataloader/DiagnosticLogger.hpp +++ /dev/null @@ -1,395 +0,0 @@ -#pragma once - -#include <concepts> -#include <cstdarg> -#include <cstdio> -#include <ostream> -#include <string> -#include <utility> - -#include <openvic-dataloader/AbstractSyntaxTree.hpp> -#include <openvic-dataloader/Error.hpp> -#include <openvic-dataloader/File.hpp> -#include <openvic-dataloader/NodeLocation.hpp> -#include <openvic-dataloader/detail/CallbackOStream.hpp> -#include <openvic-dataloader/detail/LexyReportError.hpp> -#include <openvic-dataloader/detail/OStreamOutputIterator.hpp> -#include <openvic-dataloader/detail/SymbolIntern.hpp> -#include <openvic-dataloader/detail/utility/ErrorRange.hpp> -#include <openvic-dataloader/detail/utility/Utility.hpp> - -#include <lexy/error.hpp> -#include <lexy/input/base.hpp> -#include <lexy/input/buffer.hpp> -#include <lexy/visualize.hpp> - -#include <dryad/_detail/config.hpp> -#include <dryad/abstract_node.hpp> -#include <dryad/arena.hpp> -#include <dryad/node.hpp> -#include <dryad/tree.hpp> - -#include <fmt/core.h> - -#include <lexy_ext/report_error.hpp> - -namespace ovdl { - struct DiagnosticLogger : SymbolIntern { - using AnnotationKind = lexy_ext::annotation_kind; - using DiagnosticKind = lexy_ext::diagnostic_kind; - - using error_range = detail::error_range<error::Root>; - - explicit operator bool() const; - bool errored() const; - bool warned() const; - - NodeLocation location_of(const error::Error* error) const; - - template<std::derived_from<DiagnosticLogger> Logger> - struct ErrorCallback { - ErrorCallback(Logger& logger) : _logger(&logger) {} - - struct sink_t { - using return_type = std::size_t; - - template<typename Input, typename Tag> - void operator()(lexy::error_context<Input> const& context, lexy::error_for<Input, Tag> const& error) { - using Reader = lexy::input_reader<Input>; - error::Error* result; - - std::string production_name = context.production(); - auto left_strip = production_name.find_first_of('<'); - if (left_strip != std::string::npos) { - auto right_strip = production_name.find_first_of('>', left_strip); - if (right_strip != std::string::npos) { - production_name.erase(left_strip, right_strip - left_strip + 1); - } - } - - auto production = _logger.intern_cstr(production_name); - if constexpr (std::is_same_v<Tag, lexy::expected_literal>) { - auto string = lexy::_detail::make_literal_lexeme<typename Reader::encoding>(error.string(), error.length()); - NodeLocation loc = NodeLocation::make_from(context.position(), error.position() - 1); - auto message = _logger.intern_cstr(fmt::format("expected '{}'", string.data())); - result = _logger.template create<error::ExpectedLiteral>(loc, message, production); - } else if constexpr (std::is_same_v<Tag, lexy::expected_keyword>) { - auto string = lexy::_detail::make_literal_lexeme<typename Reader::encoding>(error.string(), error.length()); - NodeLocation loc = NodeLocation::make_from(context.position(), error.position() - 1); - auto message = _logger.intern_cstr(fmt::format("expected keyword '{}'", string.data())); - result = _logger.template create<error::ExpectedKeyword>(loc, message, production); - } else if constexpr (std::is_same_v<Tag, lexy::expected_char_class>) { - auto message = _logger.intern_cstr(fmt::format("expected {}", error.name())); - result = _logger.template create<error::ExpectedCharClass>(error.position(), message, production); - } else { - NodeLocation loc = NodeLocation::make_from(error.begin(), error.end()); - auto message = _logger.intern_cstr(error.message()); - result = _logger.template create<error::GenericParseError>(loc, message, production); - } - - _logger.insert(result); - - _count++; - } - - std::size_t finish() && { - return _count; - } - - Logger& _logger; - std::size_t _count; - }; - - constexpr auto sink() const { - return sink_t { *_logger, 0 }; - } - - mutable Logger* _logger; - }; - - template<typename T, typename... Args> - T* create(NodeLocation loc, Args&&... args) { - using node_creator = dryad::node_creator<decltype(DRYAD_DECLVAL(T).kind()), void>; - T* result = _tree.create<T>(DRYAD_FWD(args)...); - _map.insert(result, loc); - return result; - } - - template<typename T> - T* create() { - using node_creator = dryad::node_creator<decltype(DRYAD_DECLVAL(T).kind()), void>; - T* result = _tree.create<T>(); - return result; - } - - protected: - bool _errored = false; - bool _warned = false; - dryad::node_map<const error::Error, NodeLocation> _map; - dryad::tree<error::Root> _tree; - - symbol_interner_type _symbol_interner; - - void insert(error::Error* root) { - _tree.root()->insert_back(root); - } - - public: - symbol_type intern(const char* str, std::size_t length) { - return _symbol_interner.intern(str, length); - } - symbol_type intern(std::string_view str) { - return intern(str.data(), str.size()); - } - const char* intern_cstr(const char* str, std::size_t length) { - return intern(str, length).c_str(_symbol_interner); - } - const char* intern_cstr(std::string_view str) { - return intern_cstr(str.data(), str.size()); - } - symbol_interner_type& symbol_interner() { - return _symbol_interner; - } - const symbol_interner_type& symbol_interner() const { - return _symbol_interner; - } - }; - - template<IsFile FileT> - struct BasicDiagnosticLogger : DiagnosticLogger { - using file_type = FileT; - - template<typename... Args> - using format_str = fmt::basic_format_string<char, fmt::type_identity_t<Args>...>; - - explicit BasicDiagnosticLogger(const file_type& file) - : _file(&file) { - _tree.set_root(_tree.create<error::Root>()); - } - - struct Writer; - - template<typename... Args> - Writer error(format_str<Args...> fmt, Args&&... args) { - return log(DiagnosticKind::error, fmt, std::forward<Args>(args)...); - } - - template<typename... Args> - Writer warning(format_str<Args...> fmt, Args&&... args) { - return log(DiagnosticKind::warning, fmt, std::forward<Args>(args)...); - } - - template<typename... Args> - Writer note(format_str<Args...> fmt, Args&&... args) { - return log(DiagnosticKind::note, fmt, std::forward<Args>(args)...); - } - - template<typename... Args> - Writer info(format_str<Args...> fmt, Args&&... args) { - return log(DiagnosticKind::info, fmt, std::forward<Args>(args)...); - } - - template<typename... Args> - Writer debug(format_str<Args...> fmt, Args&&... args) { - return log(DiagnosticKind::debug, fmt, std::forward<Args>(args)...); - } - - template<typename... Args> - Writer fixit(format_str<Args...> fmt, Args&&... args) { - return log(DiagnosticKind::fixit, fmt, std::forward<Args>(args)...); - } - - template<typename... Args> - Writer help(format_str<Args...> fmt, Args&&... args) { - return log(DiagnosticKind::help, fmt, std::forward<Args>(args)...); - } - - Writer error(std::string_view sv) { - return log(DiagnosticKind::error, fmt::runtime(sv)); - } - - Writer warning(std::string_view sv) { - return log(DiagnosticKind::warning, fmt::runtime(sv)); - } - - Writer note(std::string_view sv) { - return log(DiagnosticKind::note, fmt::runtime(sv)); - } - - Writer info(std::string_view sv) { - return log(DiagnosticKind::info, fmt::runtime(sv)); - } - - Writer debug(std::string_view sv) { - return log(DiagnosticKind::debug, fmt::runtime(sv)); - } - - Writer fixit(std::string_view sv) { - return log(DiagnosticKind::fixit, fmt::runtime(sv)); - } - - Writer help(std::string_view sv) { - return log(DiagnosticKind::help, fmt::runtime(sv)); - } - - auto error_callback() { - return ErrorCallback(*this); - } - - template<typename CharT> - static void _write_to_buffer(const CharT* s, std::streamsize n, void* output_str) { - auto* output = reinterpret_cast<std::basic_string<CharT>*>(output_str); - output->append(s, n); - } - - template<typename CharT> - auto make_callback_stream(std::basic_string<CharT>& output) { - return detail::make_callback_stream<CharT>(&_write_to_buffer<CharT>, reinterpret_cast<void*>(&output)); - } - - template<typename CharT> - detail::OStreamOutputIterator make_ostream_iterator(std::basic_ostream<CharT>& stream) { - return detail::OStreamOutputIterator { stream }; - } - - struct Writer { - template<typename... Args> - [[nodiscard]] Writer& primary(NodeLocation loc, format_str<Args...> fmt, Args&&... args) { - return annotation(AnnotationKind::primary, loc, fmt, std::forward<Args>(args)...); - } - - template<typename... Args> - [[nodiscard]] Writer& secondary(NodeLocation loc, format_str<Args...> fmt, Args&&... args) { - return annotation(AnnotationKind::secondary, loc, fmt, std::forward<Args>(args)...); - } - - [[nodiscard]] Writer& primary(NodeLocation loc, std::string_view sv) { - return annotation(AnnotationKind::primary, loc, fmt::runtime(sv)); - } - - [[nodiscard]] Writer& secondary(NodeLocation loc, std::string_view sv) { - return annotation(AnnotationKind::secondary, loc, fmt::runtime(sv)); - } - - void finish() {} - - template<typename... Args> - [[nodiscard]] Writer& annotation(AnnotationKind kind, NodeLocation loc, format_str<Args...> fmt, Args&&... args) { - auto begin_loc = lexy::get_input_location(_file->buffer(), loc.begin()); - - std::basic_string<typename decltype(fmt.get())::value_type> output; - auto stream = _logger.make_callback_stream(output); - auto iter = _logger.make_ostream_iterator(stream); - - _impl.write_empty_annotation(iter); - _impl.write_annotation(iter, kind, begin_loc, loc.end(), - [&](auto out, lexy::visualization_options) { - return lexy::_detail::write_str(out, fmt::format(fmt, std::forward<Args>(args)...).c_str()); - }); - - error::Annotation* annotation; - auto message = _logger.intern_cstr(output); - switch (kind) { - case AnnotationKind::primary: - annotation = _logger.create<error::PrimaryAnnotation>(loc, message); - break; - case AnnotationKind::secondary: - annotation = _logger.create<error::SecondaryAnnotation>(loc, message); - break; - default: detail::unreachable(); - } - _semantic->push_back(annotation); - return *this; - } - - private: - Writer(BasicDiagnosticLogger& logger, const file_type* file, error::Semantic* semantic) - : _file(file), - _impl(file->buffer(), { lexy::visualize_fancy }), - _logger(logger), - _semantic(semantic) {} - - const file_type* _file; - lexy_ext::diagnostic_writer<lexy::buffer<typename file_type::encoding_type>> _impl; - BasicDiagnosticLogger& _logger; - error::Semantic* _semantic; - - friend BasicDiagnosticLogger; - }; - - using diagnostic_writer = lexy_ext::diagnostic_writer<lexy::buffer<typename file_type::encoding_type>>; - - template<std::derived_from<error::Error> T, typename... Args> - void log_with_impl(diagnostic_writer& impl, T* error, DiagnosticKind kind, format_str<Args...> fmt, Args&&... args) { - std::basic_string<typename decltype(fmt.get())::value_type> output; - auto stream = make_callback_stream(output); - auto iter = make_ostream_iterator(stream); - - impl.write_message(iter, kind, - [&](auto out, lexy::visualization_options) { - return lexy::_detail::write_str(out, fmt::format(fmt, std::forward<Args>(args)...).c_str()); - }); - impl.write_path(iter, _file->path()); - - auto message = intern_cstr(output); - error->_set_message(message); - insert(error); - } - - template<std::derived_from<error::Error> T, typename... Args> - void log_with_error(T* error, DiagnosticKind kind, format_str<Args...> fmt, Args&&... args) { - auto impl = diagnostic_writer { _file->buffer() }; - log_with_impl(impl, error, kind, fmt, std::forward<Args>(args)...); - } - - template<std::derived_from<error::Error> T, typename... Args> - void create_log(DiagnosticKind kind, format_str<Args...> fmt, Args&&... args) { - log_with_error(create<T>(), kind, fmt, std::forward<Args>(args)...); - } - - template<typename... Args> - Writer log(DiagnosticKind kind, format_str<Args...> fmt, Args&&... args) { - error::Semantic* semantic; - - switch (kind) { - case DiagnosticKind::error: - semantic = create<error::SemanticError>(); - break; - case DiagnosticKind::warning: - semantic = create<error::SemanticWarning>(); - break; - case DiagnosticKind::info: - semantic = create<error::SemanticInfo>(); - break; - case DiagnosticKind::debug: - semantic = create<error::SemanticDebug>(); - break; - case DiagnosticKind::fixit: - semantic = create<error::SemanticFixit>(); - break; - case DiagnosticKind::help: - semantic = create<error::SemanticHelp>(); - break; - default: detail::unreachable(); - } - - Writer result(*this, _file, semantic); - - log_with_impl(result._impl, semantic, kind, fmt, std::forward<Args>(args)...); - - if (kind == DiagnosticKind::error) - _errored = true; - if (kind == DiagnosticKind::warning) - _warned = true; - - return result; - } - - error_range get_errors() const { - return _tree.root()->errors(); - } - - private: - const file_type* _file; - }; -}
\ No newline at end of file |