summaryrefslogtreecommitdiff
path: root/src/errors.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/errors.cc')
-rw-r--r--src/errors.cc116
1 files changed, 116 insertions, 0 deletions
diff --git a/src/errors.cc b/src/errors.cc
new file mode 100644
index 0000000..7122a9a
--- /dev/null
+++ b/src/errors.cc
@@ -0,0 +1,116 @@
+#include "errors.hh"
+
+#include "location.hh"
+
+#include <cstdint>
+#include <format>
+#include <iostream>
+#include <memory>
+#include <ostream>
+#include <string>
+#include <string_view>
+#include <utility>
+
+namespace src {
+
+namespace {
+
+class FileErrors : public Errors {
+ public:
+ FileErrors(std::string filename, std::shared_ptr<ErrorsOutput> output)
+ : filename_(std::move(filename)), output_(std::move(output)) {}
+
+ void err(Location loc, std::string_view msg) override {
+ ++errors_;
+ output_->println(std::format("{}:{}:{}: Error: {}", filename_, loc.line,
+ loc.column, msg));
+ }
+
+ void warn(Location loc, std::string_view msg) override {
+ ++warnings_;
+ output_->println(std::format("{}:{}:{}: Warning: {}", filename_, loc.line,
+ loc.column, msg));
+ }
+
+#if !defined(NDEBUG)
+ void dbg(Location loc, std::string_view msg) override {
+ output_->println(std::format("{}:{}:{}: Debug: {}", filename_, loc.line,
+ loc.column, msg));
+ }
+#endif
+
+ [[nodiscard]]
+ uint64_t errors() const override {
+ return errors_;
+ }
+
+ [[nodiscard]]
+ uint64_t warnings() const override {
+ return warnings_;
+ }
+
+ private:
+ std::string const filename_;
+ std::shared_ptr<ErrorsOutput> output_;
+ uint64_t errors_{0};
+ uint64_t warnings_{0};
+};
+
+class IgnoreErrors : public Errors {
+ public:
+ IgnoreErrors() = default;
+
+ void err(Location /* loc */, std::string_view /* msg */) override {}
+ void warn(Location /* loc */, std::string_view /* msg */) override {}
+
+#if !defined(NDEBUG)
+ void dbg(Location /* loc */, std::string_view /* msg */) override {}
+#endif
+
+ [[nodiscard]]
+ uint64_t errors() const override {
+ return 0;
+ }
+
+ [[nodiscard]]
+ uint64_t warnings() const override {
+ return 0;
+ }
+};
+
+class OutputStreamErrorsOutput : public ErrorsOutput {
+ public:
+ explicit OutputStreamErrorsOutput(std::ostream& out) : out_(out) {}
+
+ void println(std::string_view line) override { out_ << line << '\n'; }
+
+ private:
+ std::ostream& out_;
+};
+
+} // namespace
+
+[[nodiscard]]
+std::unique_ptr<Errors> file_errors(std::string filename,
+ std::shared_ptr<ErrorsOutput> output) {
+ if (!output) {
+ static std::shared_ptr<ErrorsOutput> g_stderr_output;
+ // TODO: Make thread-safe when needed
+ if (!g_stderr_output)
+ g_stderr_output = std::make_shared<OutputStreamErrorsOutput>(std::cerr);
+ output = g_stderr_output;
+ }
+ return std::make_unique<FileErrors>(std::move(filename), std::move(output));
+}
+
+[[nodiscard]]
+std::unique_ptr<Errors> ignore_errors() {
+ return std::make_unique<IgnoreErrors>();
+}
+
+[[nodiscard]]
+std::unique_ptr<ErrorsOutput> errors_output_ios(std::ostream& out) {
+ return std::make_unique<OutputStreamErrorsOutput>(out);
+}
+
+} // namespace src