#pragma once #include "basic_nodes.hpp" #include "basic_printers.hpp" #include namespace error_handling { enum class ErrorType { GENERAL, TYPE_CHECK, }; inline std::string to_string(ErrorType error_type) { switch (error_type) { case ErrorType::GENERAL: return "general error"; case ErrorType::TYPE_CHECK: return "type check error"; } } class ErrorLog { public: struct ErrorMessage { public: ErrorMessage(nodes::Node node, const std::string &message, ErrorType error_type = ErrorType::GENERAL) : node_(node), message_(message), error_type_(error_type) {} void print(printers::Printer &printer) { printer.print("Error at "); print_position(printer, node_.get_start_position(), node_.get_start_position()); printer.print(" : "); printer.print(message_); printer.print(" (" + to_string(error_type_) + ")."); } private: inline void print_position(printers::Printer &printer, std::pair start_position, std::pair end_position) { printer.print("[" + std::to_string(start_position.first + 1) + ", " + std::to_string(start_position.second + 1) + "] - [" + std::to_string(end_position.first + 1) + ", " + std::to_string(end_position.second + 1) + "]"); } public: nodes::Node node_; std::string message_; ErrorType error_type_ = ErrorType::GENERAL; }; void add_error(ErrorMessage &&error) { messages_.push_back(std::move(error)); } void add_error(const ErrorMessage &error) { messages_.push_back(error); } void print_all_errors(printers::Printer &printer) { for (auto &message : messages_) { message.print(printer); printer.new_indent_line(); } } private: std::vector messages_; }; } // namespace error_handling