diff --git a/.ignore b/.ignore index 6912fef..32801c9 100644 --- a/.ignore +++ b/.ignore @@ -1 +1 @@ -deps/ +deps/tree-sitter-lang diff --git a/deps/termcolor/.gitignore b/deps/termcolor/.gitignore new file mode 100644 index 0000000..f0b7474 --- /dev/null +++ b/deps/termcolor/.gitignore @@ -0,0 +1,2 @@ +.xmake +compile_commands.json diff --git a/deps/termcolor/LICENSE b/deps/termcolor/LICENSE new file mode 100644 index 0000000..e2a9f53 --- /dev/null +++ b/deps/termcolor/LICENSE @@ -0,0 +1,31 @@ +Copyright (c) 2013, Ihor Kalnytskyi. +All rights reserved. + +Redistribution and use in source and binary forms of the software as well +as documentation, with or without modification, are permitted provided +that the following conditions are met: + +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + +* The names of the contributors may not be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY THE COPYRIGHT HOLDERS AND +CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT +NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE AND DOCUMENTATION, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. diff --git a/deps/termcolor/termcolor.hpp b/deps/termcolor/termcolor.hpp new file mode 100644 index 0000000..d94e991 --- /dev/null +++ b/deps/termcolor/termcolor.hpp @@ -0,0 +1,939 @@ +//! +//! termcolor +//! ~~~~~~~~~ +//! +//! termcolor is a header-only c++ library for printing colored messages +//! to the terminal. Written just for fun with a help of the Force. +//! +//! :copyright: (c) 2013 by Ihor Kalnytskyi +//! :license: BSD, see LICENSE for details +//! + +#ifndef TERMCOLOR_HPP_ +#define TERMCOLOR_HPP_ + +#include + +// Detect target's platform and set some macros in order to wrap platform +// specific code this library depends on. +#if defined(_WIN32) || defined(_WIN64) +# define TERMCOLOR_TARGET_WINDOWS +#elif defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)) +# define TERMCOLOR_TARGET_POSIX +#endif + +// If implementation has not been explicitly set, try to choose one based on +// target platform. +#if !defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) && !defined(TERMCOLOR_USE_WINDOWS_API) && !defined(TERMCOLOR_USE_NOOP) +# if defined(TERMCOLOR_TARGET_POSIX) +# define TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES +# define TERMCOLOR_AUTODETECTED_IMPLEMENTATION +# elif defined(TERMCOLOR_TARGET_WINDOWS) +# define TERMCOLOR_USE_WINDOWS_API +# define TERMCOLOR_AUTODETECTED_IMPLEMENTATION +# endif +#endif + +// These headers provide isatty()/fileno() functions, which are used for +// testing whether a standard stream refers to the terminal. +#if defined(TERMCOLOR_TARGET_POSIX) +# include +#elif defined(TERMCOLOR_TARGET_WINDOWS) +# include +# include +#endif + + +namespace termcolor +{ + // Forward declaration of the `_internal` namespace. + // All comments are below. + namespace _internal + { + inline int colorize_index(); + inline FILE* get_standard_stream(const std::ostream& stream); + inline FILE* get_standard_stream(const std::wostream& stream); + template + bool is_colorized(std::basic_ostream& stream); + template + bool is_atty(const std::basic_ostream& stream); + + #if defined(TERMCOLOR_TARGET_WINDOWS) + template + void win_change_attributes(std::basic_ostream& stream, int foreground, int background = -1); + #endif + } + + template + std::basic_ostream& colorize(std::basic_ostream& stream) + { + stream.iword(_internal::colorize_index()) = 1L; + return stream; + } + + template + std::basic_ostream& nocolorize(std::basic_ostream& stream) + { + stream.iword(_internal::colorize_index()) = 0L; + return stream; + } + + template + std::basic_ostream& reset(std::basic_ostream& stream) + { + if (_internal::is_colorized(stream)) + { + #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[00m"; + #elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, -1, -1); + #endif + } + return stream; + } + + template + std::basic_ostream& bold(std::basic_ostream& stream) + { + if (_internal::is_colorized(stream)) + { + #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[1m"; + #elif defined(TERMCOLOR_USE_WINDOWS_API) + #endif + } + return stream; + } + + template + std::basic_ostream& dark(std::basic_ostream& stream) + { + if (_internal::is_colorized(stream)) + { + #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[2m"; + #elif defined(TERMCOLOR_USE_WINDOWS_API) + #endif + } + return stream; + } + + template + std::basic_ostream& italic(std::basic_ostream& stream) + { + if (_internal::is_colorized(stream)) + { + #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[3m"; + #elif defined(TERMCOLOR_USE_WINDOWS_API) + #endif + } + return stream; + } + + template + std::basic_ostream& underline(std::basic_ostream& stream) + { + if (_internal::is_colorized(stream)) + { + #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[4m"; + #elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, -1, COMMON_LVB_UNDERSCORE); + #endif + } + return stream; + } + + template + std::basic_ostream& blink(std::basic_ostream& stream) + { + if (_internal::is_colorized(stream)) + { + #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[5m"; + #elif defined(TERMCOLOR_USE_WINDOWS_API) + #endif + } + return stream; + } + + template + std::basic_ostream& reverse(std::basic_ostream& stream) + { + if (_internal::is_colorized(stream)) + { + #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[7m"; + #elif defined(TERMCOLOR_USE_WINDOWS_API) + #endif + } + return stream; + } + + template + std::basic_ostream& concealed(std::basic_ostream& stream) + { + if (_internal::is_colorized(stream)) + { + #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[8m"; + #elif defined(TERMCOLOR_USE_WINDOWS_API) + #endif + } + return stream; + } + + template + std::basic_ostream& crossed(std::basic_ostream& stream) + { + if (_internal::is_colorized(stream)) + { + #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[9m"; + #elif defined(TERMCOLOR_USE_WINDOWS_API) + #endif + } + return stream; + } + + template + std::basic_ostream& color(std::basic_ostream& stream) + { + if (_internal::is_colorized(stream)) + { + #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[38;5;" << +code << "m"; + #elif defined(TERMCOLOR_USE_WINDOWS_API) + #endif + } + return stream; + } + + template + std::basic_ostream& on_color(std::basic_ostream& stream) + { + if (_internal::is_colorized(stream)) + { + #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[48;5;" << +code << "m"; + #elif defined(TERMCOLOR_USE_WINDOWS_API) + #endif + } + return stream; + } + + template + std::basic_ostream& color(std::basic_ostream& stream) + { + if (_internal::is_colorized(stream)) + { + #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[38;2;" << +r << ";" << +g << ";" << +b << "m"; + #elif defined(TERMCOLOR_USE_WINDOWS_API) + #endif + } + return stream; + } + + template + std::basic_ostream& on_color(std::basic_ostream& stream) + { + if (_internal::is_colorized(stream)) + { + #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[48;2;" << +r << ";" << +g << ";" << +b << "m"; + #elif defined(TERMCOLOR_USE_WINDOWS_API) + #endif + } + return stream; + } + + template + std::basic_ostream& grey(std::basic_ostream& stream) + { + if (_internal::is_colorized(stream)) + { + #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[30m"; + #elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, + 0 // grey (black) + ); + #endif + } + return stream; + } + + template + std::basic_ostream& red(std::basic_ostream& stream) + { + if (_internal::is_colorized(stream)) + { + #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[31m"; + #elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, + FOREGROUND_RED + ); + #endif + } + return stream; + } + + template + std::basic_ostream& green(std::basic_ostream& stream) + { + if (_internal::is_colorized(stream)) + { + #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[32m"; + #elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, + FOREGROUND_GREEN + ); + #endif + } + return stream; + } + + template + std::basic_ostream& yellow(std::basic_ostream& stream) + { + if (_internal::is_colorized(stream)) + { + #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[33m"; + #elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, + FOREGROUND_GREEN | FOREGROUND_RED + ); + #endif + } + return stream; + } + + template + std::basic_ostream& blue(std::basic_ostream& stream) + { + if (_internal::is_colorized(stream)) + { + #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[34m"; + #elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, + FOREGROUND_BLUE + ); + #endif + } + return stream; + } + + template + std::basic_ostream& magenta(std::basic_ostream& stream) + { + if (_internal::is_colorized(stream)) + { + #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[35m"; + #elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, + FOREGROUND_BLUE | FOREGROUND_RED + ); + #endif + } + return stream; + } + + template + std::basic_ostream& cyan(std::basic_ostream& stream) + { + if (_internal::is_colorized(stream)) + { + #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[36m"; + #elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, + FOREGROUND_BLUE | FOREGROUND_GREEN + ); + #endif + } + return stream; + } + + template + std::basic_ostream& white(std::basic_ostream& stream) + { + if (_internal::is_colorized(stream)) + { + #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[37m"; + #elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, + FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED + ); + #endif + } + return stream; + } + + + template + std::basic_ostream& bright_grey(std::basic_ostream& stream) + { + if (_internal::is_colorized(stream)) + { + #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[90m"; + #elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, + 0 | FOREGROUND_INTENSITY // grey (black) + ); + #endif + } + return stream; + } + + template + std::basic_ostream& bright_red(std::basic_ostream& stream) + { + if (_internal::is_colorized(stream)) + { + #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[91m"; + #elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, + FOREGROUND_RED | FOREGROUND_INTENSITY + ); + #endif + } + return stream; + } + + template + std::basic_ostream& bright_green(std::basic_ostream& stream) + { + if (_internal::is_colorized(stream)) + { + #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[92m"; + #elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, + FOREGROUND_GREEN | FOREGROUND_INTENSITY + ); + #endif + } + return stream; + } + + template + std::basic_ostream& bright_yellow(std::basic_ostream& stream) + { + if (_internal::is_colorized(stream)) + { + #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[93m"; + #elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, + FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY + ); + #endif + } + return stream; + } + + template + std::basic_ostream& bright_blue(std::basic_ostream& stream) + { + if (_internal::is_colorized(stream)) + { + #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[94m"; + #elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, + FOREGROUND_BLUE | FOREGROUND_INTENSITY + ); + #endif + } + return stream; + } + + template + std::basic_ostream& bright_magenta(std::basic_ostream& stream) + { + if (_internal::is_colorized(stream)) + { + #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[95m"; + #elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, + FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY + ); + #endif + } + return stream; + } + + template + std::basic_ostream& bright_cyan(std::basic_ostream& stream) + { + if (_internal::is_colorized(stream)) + { + #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[96m"; + #elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, + FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY + ); + #endif + } + return stream; + } + + template + std::basic_ostream& bright_white(std::basic_ostream& stream) + { + if (_internal::is_colorized(stream)) + { + #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[97m"; + #elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, + FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY + ); + #endif + } + return stream; + } + + + template + std::basic_ostream& on_grey(std::basic_ostream& stream) + { + if (_internal::is_colorized(stream)) + { + #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[40m"; + #elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, -1, + 0 // grey (black) + ); + #endif + } + return stream; + } + + template + std::basic_ostream& on_red(std::basic_ostream& stream) + { + if (_internal::is_colorized(stream)) + { + #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[41m"; + #elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, -1, + BACKGROUND_RED + ); + #endif + } + return stream; + } + + template + std::basic_ostream& on_green(std::basic_ostream& stream) + { + if (_internal::is_colorized(stream)) + { + #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[42m"; + #elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, -1, + BACKGROUND_GREEN + ); + #endif + } + return stream; + } + + template + std::basic_ostream& on_yellow(std::basic_ostream& stream) + { + if (_internal::is_colorized(stream)) + { + #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[43m"; + #elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, -1, + BACKGROUND_GREEN | BACKGROUND_RED + ); + #endif + } + return stream; + } + + template + std::basic_ostream& on_blue(std::basic_ostream& stream) + { + if (_internal::is_colorized(stream)) + { + #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[44m"; + #elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, -1, + BACKGROUND_BLUE + ); + #endif + } + return stream; + } + + template + std::basic_ostream& on_magenta(std::basic_ostream& stream) + { + if (_internal::is_colorized(stream)) + { + #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[45m"; + #elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, -1, + BACKGROUND_BLUE | BACKGROUND_RED + ); + #endif + } + return stream; + } + + template + std::basic_ostream& on_cyan(std::basic_ostream& stream) + { + if (_internal::is_colorized(stream)) + { + #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[46m"; + #elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, -1, + BACKGROUND_GREEN | BACKGROUND_BLUE + ); + #endif + } + return stream; + } + + template + std::basic_ostream& on_white(std::basic_ostream& stream) + { + if (_internal::is_colorized(stream)) + { + #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[47m"; + #elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, -1, + BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_RED + ); + #endif + } + + return stream; + } + + + template + std::basic_ostream& on_bright_grey(std::basic_ostream& stream) + { + if (_internal::is_colorized(stream)) + { + #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[100m"; + #elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, -1, + 0 | BACKGROUND_INTENSITY // grey (black) + ); + #endif + } + return stream; + } + + template + std::basic_ostream& on_bright_red(std::basic_ostream& stream) + { + if (_internal::is_colorized(stream)) + { + #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[101m"; + #elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, -1, + BACKGROUND_RED | BACKGROUND_INTENSITY + ); + #endif + } + return stream; + } + + template + std::basic_ostream& on_bright_green(std::basic_ostream& stream) + { + if (_internal::is_colorized(stream)) + { + #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[102m"; + #elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, -1, + BACKGROUND_GREEN | BACKGROUND_INTENSITY + ); + #endif + } + return stream; + } + + template + std::basic_ostream& on_bright_yellow(std::basic_ostream& stream) + { + if (_internal::is_colorized(stream)) + { + #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[103m"; + #elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, -1, + BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY + ); + #endif + } + return stream; + } + + template + std::basic_ostream& on_bright_blue(std::basic_ostream& stream) + { + if (_internal::is_colorized(stream)) + { + #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[104m"; + #elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, -1, + BACKGROUND_BLUE | BACKGROUND_INTENSITY + ); + #endif + } + return stream; + } + + template + std::basic_ostream& on_bright_magenta(std::basic_ostream& stream) + { + if (_internal::is_colorized(stream)) + { + #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[105m"; + #elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, -1, + BACKGROUND_BLUE | BACKGROUND_RED | BACKGROUND_INTENSITY + ); + #endif + } + return stream; + } + + template + std::basic_ostream& on_bright_cyan(std::basic_ostream& stream) + { + if (_internal::is_colorized(stream)) + { + #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[106m"; + #elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, -1, + BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_INTENSITY + ); + #endif + } + return stream; + } + + template + std::basic_ostream& on_bright_white(std::basic_ostream& stream) + { + if (_internal::is_colorized(stream)) + { + #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) + stream << "\033[107m"; + #elif defined(TERMCOLOR_USE_WINDOWS_API) + _internal::win_change_attributes(stream, -1, + BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_RED | BACKGROUND_INTENSITY + ); + #endif + } + + return stream; + } + + + + //! Since C++ hasn't a way to hide something in the header from + //! the outer access, I have to introduce this namespace which + //! is used for internal purpose and should't be access from + //! the user code. + namespace _internal + { + // An index to be used to access a private storage of I/O streams. See + // colorize / nocolorize I/O manipulators for details. Due to the fact + // that static variables ain't shared between translation units, inline + // function with local static variable is used to do the trick and share + // the variable value between translation units. + inline int colorize_index() + { + static int colorize_index = std::ios_base::xalloc(); + return colorize_index; + } + + //! Since C++ hasn't a true way to extract stream handler + //! from the a given `std::ostream` object, I have to write + //! this kind of hack. + inline + FILE* get_standard_stream(const std::ostream& stream) + { + if (&stream == &std::cout) + return stdout; + else if (&stream == &std::cerr || &stream == &std::clog) + return stderr; + + return nullptr; + } + + //! Since C++ hasn't a true way to extract stream handler + //! from the a given `std::wostream` object, I have to write + //! this kind of hack. + inline + FILE* get_standard_stream(const std::wostream& stream) + { + if (&stream == &std::wcout) + return stdout; + else if (&stream == &std::wcerr || &stream == &std::wclog) + return stderr; + + return nullptr; + } + + // Say whether a given stream should be colorized or not. It's always + // true for ATTY streams and may be true for streams marked with + // colorize flag. + template + bool is_colorized(std::basic_ostream& stream) + { + return is_atty(stream) || static_cast(stream.iword(colorize_index())); + } + + //! Test whether a given `std::ostream` object refers to + //! a terminal. + template + bool is_atty(const std::basic_ostream& stream) + { + FILE* std_stream = get_standard_stream(stream); + + // Unfortunately, fileno() ends with segmentation fault + // if invalid file descriptor is passed. So we need to + // handle this case gracefully and assume it's not a tty + // if standard stream is not detected, and 0 is returned. + if (!std_stream) + return false; + + #if defined(TERMCOLOR_TARGET_POSIX) + return ::isatty(fileno(std_stream)); + #elif defined(TERMCOLOR_TARGET_WINDOWS) + return ::_isatty(_fileno(std_stream)); + #else + return false; + #endif + } + + #if defined(TERMCOLOR_TARGET_WINDOWS) + + //! same hack as used in get_standard_stream function, but for Windows with `std::ostream` + inline HANDLE get_terminal_handle(std::ostream& stream) + { + if (&stream == &std::cout) + return GetStdHandle(STD_OUTPUT_HANDLE); + else if (&stream == &std::cerr || &stream == &std::clog) + return GetStdHandle(STD_ERROR_HANDLE); + return nullptr; + } + + //! same hack as used in get_standard_stream function, but for Windows with `std::wostream` + inline HANDLE get_terminal_handle(std::wostream& stream) + { + if (&stream == &std::wcout) + return GetStdHandle(STD_OUTPUT_HANDLE); + else if (&stream == &std::wcerr || &stream == &std::wclog) + return GetStdHandle(STD_ERROR_HANDLE); + return nullptr; + } + + //! Change Windows Terminal colors attribute. If some + //! parameter is `-1` then attribute won't changed. + template + void win_change_attributes(std::basic_ostream& stream, int foreground, int background) + { + // yeah, i know.. it's ugly, it's windows. + static WORD defaultAttributes = 0; + + // Windows doesn't have ANSI escape sequences and so we use special + // API to change Terminal output color. That means we can't + // manipulate colors by means of "std::stringstream" and hence + // should do nothing in this case. + if (!_internal::is_atty(stream)) + return; + + // get terminal handle + HANDLE hTerminal = INVALID_HANDLE_VALUE; + hTerminal = get_terminal_handle(stream); + + // save default terminal attributes if it unsaved + if (!defaultAttributes) + { + CONSOLE_SCREEN_BUFFER_INFO info; + if (!GetConsoleScreenBufferInfo(hTerminal, &info)) + return; + defaultAttributes = info.wAttributes; + } + + // restore all default settings + if (foreground == -1 && background == -1) + { + SetConsoleTextAttribute(hTerminal, defaultAttributes); + return; + } + + // get current settings + CONSOLE_SCREEN_BUFFER_INFO info; + if (!GetConsoleScreenBufferInfo(hTerminal, &info)) + return; + + if (foreground != -1) + { + info.wAttributes &= ~(info.wAttributes & 0x0F); + info.wAttributes |= static_cast(foreground); + } + + if (background != -1) + { + info.wAttributes &= ~(info.wAttributes & 0xF0); + info.wAttributes |= static_cast(background); + } + + SetConsoleTextAttribute(hTerminal, info.wAttributes); + } + #endif // TERMCOLOR_TARGET_WINDOWS + + } // namespace _internal + +} // namespace termcolor + + +#undef TERMCOLOR_TARGET_POSIX +#undef TERMCOLOR_TARGET_WINDOWS + +#if defined(TERMCOLOR_AUTODETECTED_IMPLEMENTATION) +# undef TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES +# undef TERMCOLOR_USE_WINDOWS_API +#endif + +#endif // TERMCOLOR_HPP_ diff --git a/deps/termcolor/xmake.lua b/deps/termcolor/xmake.lua new file mode 100644 index 0000000..7e8083e --- /dev/null +++ b/deps/termcolor/xmake.lua @@ -0,0 +1,7 @@ +set_languages("c++20") + +target("termcolor") + set_kind("headeronly") + add_headerfiles("termcolor.hpp") + set_warnings("all", "error") + set_rundir("$(projectdir)") diff --git a/lang/app/main.cpp b/lang/app/main.cpp index 30355ef..9bfc041 100644 --- a/lang/app/main.cpp +++ b/lang/app/main.cpp @@ -11,8 +11,8 @@ int main(int argc, char **argv) { // - SourcesManager sources_manager; + SourcesManager sources_manager(Log({}, {})); - sources_manager.add_file(filename); - sources_manager.print(std::cout); + sources_manager.AddFile(filename); + sources_manager.Print(std::cout); } diff --git a/lang/app/sources_manager.hpp b/lang/app/sources_manager.hpp index 77cdc1a..4e3db4a 100644 --- a/lang/app/sources_manager.hpp +++ b/lang/app/sources_manager.hpp @@ -2,8 +2,8 @@ #include "basic_printers.hpp" #include "error_handling.hpp" -#include "error_log.hpp" #include "expression_nodes.hpp" +#include "log.hpp" #include "name_tree.hpp" #include "statement_builders.hpp" #include "statement_nodes.hpp" @@ -17,7 +17,11 @@ class SourcesManager { public: - void add_file(const std::string &filename) { + SourcesManager(Log &&log) : log_(std::move(log)) {} + + void AddFile(const std::string &filename) { + Log::Context logc(log_, utils::Log::Area::kParse); + std::ifstream in; in.open(filename); @@ -32,8 +36,8 @@ public: parser::ParseTree parse_tree(source); if (!parse_tree.is_properly_parsed()) { - error_handling::handle_parsing_error( - "There are some parsing errors in file", parse_tree.get_root()); + logc.Fatal( + {{"There are some parsing errors in file"}} /*,parse_tree.get_root()*/); } auto new_statements = builders::build_source_file( @@ -47,36 +51,36 @@ public: new_statements.clear(); } - void print(std::ostream &out) { + void Print(std::ostream &out) { printers::Printer printer(out, 2, 80, true); printers::print(statements_, printer); } // - nodes::ExpressionStorage *expressions() { return &expression_storage_; } + nodes::ExpressionStorage &expressions() { return expression_storage_; } - const nodes::ExpressionStorage *expressions() const { - return &expression_storage_; + const nodes::ExpressionStorage &expressions() const { + return expression_storage_; } // - nodes::TypeStorage *types() { return &type_storage_; } + nodes::TypeStorage &types() { return type_storage_; } - const nodes::TypeStorage *types() const { return &type_storage_; } + const nodes::TypeStorage &types() const { return type_storage_; } // - names::NameTree *names() { return &name_tree_; } + names::NameTree &names() { return name_tree_; } - const names::NameTree *names() const { return &name_tree_; } + const names::NameTree &names() const { return name_tree_; } // - error_handling::ErrorLog *errors() { return &error_log_; } + utils::Log &log() { return log_; } - const error_handling::ErrorLog *errors() const { return &error_log_; } + const utils::Log &log() const { return log_; } // @@ -89,9 +93,9 @@ public: } private: - nodes::ExpressionStorage expression_storage_; - nodes::TypeStorage type_storage_; - names::NameTree name_tree_; - error_handling::ErrorLog error_log_; - std::vector statements_; + Log log_; + nodes::ExpressionStorage expression_storage_ = {}; + nodes::TypeStorage type_storage_ = {}; + names::NameTree name_tree_ = {}; + std::vector statements_ = {}; }; diff --git a/lang/type_check/src/expression_type_check.cpp b/lang/type_check/src/expression_type_check.cpp index fea52a4..aab879f 100644 --- a/lang/type_check/src/expression_type_check.cpp +++ b/lang/type_check/src/expression_type_check.cpp @@ -2,7 +2,6 @@ #include "basic_nodes.hpp" #include "basic_type_check.hpp" #include "builtin_types.hpp" -#include "error_log.hpp" #include "sources_manager.hpp" #include "type_nodes.hpp" #include "utils.hpp" diff --git a/lang/utils/include/error_log.hpp b/lang/utils/include/error_log.hpp index 129c237..2ac0c4e 100644 --- a/lang/utils/include/error_log.hpp +++ b/lang/utils/include/error_log.hpp @@ -3,6 +3,7 @@ #include "basic_nodes.hpp" #include "basic_printers.hpp" +#include #include namespace error_handling { diff --git a/lang/utils/include/executor.hpp b/lang/utils/include/executor.hpp new file mode 100644 index 0000000..d9fbc5c --- /dev/null +++ b/lang/utils/include/executor.hpp @@ -0,0 +1,79 @@ +#pragma once + +#include +#include + +#include "log.hpp" + +namespace utils { + +template class Task; + +template class ExecutorState { +public: + struct Tag {}; + + ExecutorState(State &&state) : state_(std::move(state)) {} + + // + + State &state(Tag) { return state; } + const State &state(Tag) const { return state; } + +protected: + State state_; +}; + +template class Executor : public ExecutorState... { + friend class Task; + +public: + Executor(Log &&log, States &&...states) + : ExecutorState(std::move(states))..., log_(std::move(log)) {} + + // + + template T New(Args... args) { + return T(*this, args...); + } + + // + + Log &log() { return log_; } + const Log &log() const { return log_; } + +private: + Log log_; +}; + +template class Task { +public: + Task(Executor &executor) : executor(executor) {} + + virtual ~Task() {} + + // + + virtual void operator()() = 0; + + template T New(Args... args) { + return executor.template New(std::move(args)...); + } + + // + + template T &state() { + return executor.state(ExecutorState::Tag); + } + template const T &state() const { + return executor.state(ExecutorState::Tag); + } + + Log &log() { return executor.log_; } + const Log &log() const { return executor.log_; } + +public: + Executor &executor; +}; + +} // namespace utils diff --git a/lang/utils/include/log.hpp b/lang/utils/include/log.hpp new file mode 100644 index 0000000..8e3ef2d --- /dev/null +++ b/lang/utils/include/log.hpp @@ -0,0 +1,304 @@ +#include +#include +#include +#include +#include +#include +#include + +// Expect + +#define EXPECT_EQ(context, left, right) \ + (context).Expect((left) == (right), "#left == #right"); + +#define EXPECT_NE(context, left, right) \ + (context).Expect((left) != (right), "#left != #right"); + +#define EXPECT_LE(context, left, right) \ + (context).Expect((left) <= (right), "#left <= #right"); + +#define EXPECT_GE(context, left, right) \ + (context).Expect((left) >= (right), "#left >= #right"); + +#define EXPECT_LT(context, left, right) \ + (context).Expect((left) < (right), "#left < #right"); + +#define EXPECT_GT(context, left, right) \ + (context).Expect((left) > (right), "#left > #right"); + +// Require + +#define REQUIRE_EQ(context, left, right) \ + (context).Require((left) == (right), "#left == #right"); + +#define REQUIRE_NE(context, left, right) \ + (context).Require((left) != (right), "#left != #right"); + +#define REQUIRE_LE(context, left, right) \ + (context).Require((left) <= (right), "#left <= #right"); + +#define REQUIRE_GE(context, left, right) \ + (context).Require((left) >= (right), "#left >= #right"); + +#define REQUIRE_LT(context, left, right) \ + (context).Require((left) < (right), "#left < #right"); + +#define REQUIRE_GT(context, left, right) \ + (context).Require((left) > (right), "#left > #right"); + +// + +namespace utils { + +std::string to_string(const std::source_location &source_location); + +struct Pos { +public: + struct Point { + size_t line; + size_t position; + }; + +public: + Point start; + Point end; +}; + +class Log { + friend class Context; + +public: + enum Kind { + kSys, + kProc, + }; + + enum class Level : uint32_t { // NOTE: change to_string(Log::Level level) on + // change + kDebug = 1, + kInfo = 3, + kImportant = 5, + kWarning = 7, + kError = 9, + kFatal = 11, + }; + + enum class Area { + kDefault, + kParse, + kIntepret, + // ... + }; + struct Fragment { + // Fragment(std::string fragment) : fragment(fragment), color(kNone) {} + + enum Color { + kNone, + kDebug, + kInfo, + kImportant, + kWarning, + kError, + kFatal, + }; + + std::string fragment; + Color color = kNone; + + explicit operator std::string() { + return fragment; // TODO: +color + } + }; + using Fragments = std::vector; + + struct Message { + Fragments message; + Level level; + Area area = Area::kDefault; + std::optional pos = {}; + std::source_location source_location = std::source_location::current(); + }; + + class Context { + public: + Context( + Log &log, Area area, Level default_level = Level::kInfo, + std::source_location source_location = std::source_location::current()) + : log_(log), area_(area), default_level_(default_level), + function_(to_string(source_location)) { + log_.PushLog({ + .message = {{"Enter ", Fragment::kInfo}, {function_}}, + .level = default_level_, + }); + } + + ~Context() { + log_.PushLog({ + .message = {{"Leave ", Fragment::kInfo}, {function_}}, + .level = default_level_, + }); + } + + Context(const Context &log) = delete; + Context(Context &&log) = delete; + + // + + template + void LogWithLevel(Fragments message, Level level, + std::optional pos = {}, + std::source_location source_location = + std::source_location::current()) { + log_.PushLog({ + .message = std::move(message), + .level = level, + .area = area_, + .pos = pos, + .source_location = source_location, + }); + } + + template + void Default(Fragments message, std::optional pos = {}, + std::source_location source_location = + std::source_location::current()) { + LogWithLevel(std::move(message), default_level_, pos, source_location); + } + + template + void Debug(Fragments message, std::optional pos = {}, + std::source_location source_location = + std::source_location::current()) { + LogWithLevel(std::move(message), Level::kDebug, pos, source_location); + } + + template + void Info(Fragments message, std::optional pos = {}, + std::source_location source_location = + std::source_location::current()) { + LogWithLevel(std::move(message), Level::kInfo, pos, source_location); + } + + template + void Important(Fragments message, std::optional pos = {}, + std::source_location source_location = + std::source_location::current()) { + LogWithLevel(std::move(message), Level::kImportant, pos, + source_location); + } + + template + void Warning(Fragments message, std::optional pos = {}, + std::source_location source_location = + std::source_location::current()) { + LogWithLevel(std::move(message), Level::kWarning, pos, + source_location); + } + + template + void Error(Fragments message, std::optional pos = {}, + std::source_location source_location = + std::source_location::current()) { + LogWithLevel(std::move(message), Level::kError, pos, source_location); + } + + template + void Fatal(Fragments message, std::optional pos = {}, + std::source_location source_location = + std::source_location::current()) { + auto entity = Message{ + .message = std::move(message), + .level = Level::kFatal, + .area = area_, + .pos = pos, + .source_location = source_location, + }; + + log_.PushLog(entity); + throw entity; + } + + // + + template + bool Expect(bool condition, Fragments message, std::optional pos = {}, + std::source_location source_location = + std::source_location::current()) { + message.insert(message.begin(), + {.fragment = "Expected: ", .color = Fragment::kError}); + if (condition) { + Error(std::move(message), pos, source_location); + } + return condition; + } + + template + bool Require(bool condition, Fragments message, std::optional pos = {}, + std::source_location source_location = + std::source_location::current()) { + message.insert(message.begin(), + {.fragment = "Required: ", .color = Fragment::kError}); + if (condition) { + Error(std::move(message), pos, source_location); + } + return condition; + } + + private: + Log &log_; + Area area_; + Level default_level_; + std::string function_; + }; + +public: + Log(std::function sys_hook, + std::function proc_hook) + : sys{}, proc{}, sys_hook_(sys_hook), proc_hook_(proc_hook) {} + + // TODO: proc logs + +private: + template void PushLog(Message message) { + static_assert(K == kSys or K == kProc); + switch (K) { + case kSys: + sys_hook_(message); + sys.push_back(std::move(message)); + break; + case kProc: + proc_hook_(message); + proc.push_back(std::move(message)); + break; + } + } + +private: + std::vector sys; // logs for runing code + std::vector + proc; // logs for code parsing / type check / interpretation / ... + std::function sys_hook_; + std::function proc_hook_; +}; + +// + +std::string to_string(const std::source_location &source_location); + +std::string to_string(Pos::Point point); + +std::string to_string(Pos pos); + +std::string to_string(Log::Fragments fragments); + +std::string to_string(Log::Level level); + +std::string to_string(Log::Message message); + +// + +Log BuildPrintLog(std::ostream &out, Log::Level min_level = Log::Level::kInfo); + +} // namespace utils + +using utils::Log; diff --git a/lang/utils/src/executor.cpp b/lang/utils/src/executor.cpp new file mode 100644 index 0000000..e4390e4 --- /dev/null +++ b/lang/utils/src/executor.cpp @@ -0,0 +1 @@ +#include "executor.hpp" diff --git a/lang/utils/src/log.cpp b/lang/utils/src/log.cpp new file mode 100644 index 0000000..6189aaf --- /dev/null +++ b/lang/utils/src/log.cpp @@ -0,0 +1,54 @@ +#include "log.hpp" + +#include "magic_enum.hpp" + +#include + +namespace utils { + +std::string to_string(const std::source_location &source_location) { + return std::format("{}:{} {}", source_location.file_name(), + source_location.line(), source_location.function_name()); +} + +std::string to_string(Pos::Point point) { + return std::format("{},{}", point.line, point.position); +} + +std::string to_string(Pos pos) { + return std::format("{} - {}", to_string(pos.start), to_string(pos.end)); +} + +std::string to_string(Log::Fragments fragments) { + return std::accumulate( // + std::move_iterator(fragments.begin()), + std::move_iterator(fragments.end()), std::string{}, + [](auto &&acc, Log::Fragment &&fragment) { + acc += static_cast(fragment); + return acc; + }); +} + +std::string to_string(Log::Level level) { + return std::string{magic_enum::enum_name(level).substr(1)}; // k... -> ... +} + +std::string to_string(Log::Message message) { + return std::format( + "{}: {}{} ({})", to_string(message.level), to_string(message.message), + message.pos ? (" at " + to_string(*message.pos)) : std::string{}, + to_string(message.source_location)); +} + +// + +inline Log BuildPrintLog(std::ostream &out, Log::Level min_level) { + auto const print = [&out, min_level](const Log::Message &message) { + if (message.level >= min_level) { + out << to_string(message); + } + }; + return Log(print, print); +} + +} // namespace utils diff --git a/lang/utils/xmake.lua b/lang/utils/xmake.lua index 15a7127..8850e50 100644 --- a/lang/utils/xmake.lua +++ b/lang/utils/xmake.lua @@ -1,8 +1,15 @@ set_languages("c++20") +add_requires("magic_enum") + +-- TODO: +-- includes("../../deps/termcolor") + target("lang.utils") set_kind("static") add_includedirs("include", {public = true}) add_files("src/**.cpp") + add_packages("magic_enum") + -- add_deps("termcolor") set_warnings("allextra", "error") set_rundir("$(projectdir)")