#ifndef error_hh #define error_hh #include "ansicolor.hh" #include #include #include #include #include "types.hh" namespace nix { typedef enum { elWarning, elError } ErrLevel; class ColumnRange { public: unsigned int start; unsigned int len; }; class ErrorInfo; class ErrLine { public: int lineNumber; std::optional columnRange; std::optional prevLineOfCode; string errLineOfCode; std::optional nextLineOfCode; }; class NixCode { public: std::optional nixFile; std::optional errLine; }; // ---------------------------------------------------------------- // format for hints. same as fmt, except templated values // are always in yellow. template class yellowify { public: yellowify(T &s) : value(s) {} T &value; }; template std::ostream& operator<<(std::ostream &out, const yellowify &y) { return out << ANSI_YELLOW << y.value << ANSI_NORMAL; } class hintformat { public: hintformat(string format) :fmt(format) { fmt.exceptions(boost::io::all_error_bits ^ boost::io::too_many_args_bit); } template hintformat& operator%(const T &value) { fmt % yellowify(value); return *this; } std::string str() const { return fmt.str(); } template friend class AddHint; private: format fmt; }; template inline hintformat hintfmt(const std::string & fs, const Args & ... args) { hintformat f(fs); formatHelper(f, args...); return f; } // ------------------------------------------------- // ErrorInfo. class ErrorInfo { public: ErrLevel level; string name; string description; std::optional nixCode; std::optional hint; static std::optional programName; static ErrorInfo ProgramError(const string &name, const string &description, const std::optional &hf); static ErrorInfo ProgramWarning(const string &name, const string &description, const std::optional &hf); template static ErrorInfo NixLangError(const string &name, const string &description, const P &pos, std::optional prevloc, string loc, std::optional nextloc, const std::optional &hf) { return NixLangEI(elError, name, description, pos, prevloc, loc, nextloc, hf); } template static ErrorInfo NixLangWarning(const string &name, const string &description, const P &pos, std::optional prevloc, string loc, std::optional nextloc, const std::optional &hf) { return NixLangEI(elWarning, name, description, pos, prevloc, loc, nextloc, hf); } private: template static ErrorInfo NixLangEI(ErrLevel level, const string &name, const string &description, const P &pos, std::optional prevloc, string loc, std::optional nextloc, const std::optional &hf) { ErrorInfo ei(level); ei.name = name; ei.description = description; if (hf.has_value()) ei.hint = std::optional(hf->str()); else ei.hint = std::nullopt; ErrLine errline; errline.lineNumber = pos.line; errline.columnRange = { .start = pos.column, .len = 1 }; errline.prevLineOfCode = prevloc; errline.errLineOfCode = loc; errline.nextLineOfCode = nextloc; NixCode nixcode; nixcode.nixFile = pos.file; nixcode.errLine = std::optional(errline); ei.nixCode = std::optional(nixcode); return ei; } static ErrorInfo ProgramEI(ErrLevel level, const string &name, const string &description, const std::optional &hf); // constructor is protected, so only the builder classes can create an ErrorInfo. ErrorInfo(ErrLevel level) { this->level = level; } }; // -------------------------------------------------------- // error printing // just to cout for now. void printErrorInfo(const ErrorInfo &einfo); } #endif