/* * common.h --- Common utilities. * * (c) Seq project. All rights reserved. * This file is subject to the terms and conditions defined in * file 'LICENSE', which is part of this source code package. */ #pragma once #include #include #include #include #include #include #include #include #include #include #include #include "util/common.h" using std::make_shared; using std::make_unique; using std::map; using std::pair; using std::set; using std::shared_ptr; using std::string; using std::unique_ptr; using std::unordered_map; using std::unordered_set; using std::vector; #include "compiler/util/fmt/format.h" #include "compiler/util/fmt/ostream.h" namespace seq { namespace exc { /** * Parser error exception. * Used for parsing, transformation and type-checking errors. */ class ParserException : public std::runtime_error { public: /// These vectors (stacks) store an error stack-trace. vector locations; vector messages; public: ParserException(const string &msg, const SrcInfo &info) noexcept : std::runtime_error(msg) { messages.push_back(msg); locations.push_back(info); } ParserException() noexcept : ParserException("", {}) {} explicit ParserException(const string &msg) noexcept : ParserException(msg, {}) {} ParserException(const ParserException &e) noexcept : std::runtime_error(e), locations(e.locations), messages(e.messages) {} /// Add an error message to the current stack trace void trackRealize(const string &msg, const SrcInfo &info) { locations.push_back(info); messages.push_back(fmt::format("while realizing {}", msg)); } /// Add an error message to the current stack trace void track(const string &msg, const SrcInfo &info) { locations.push_back(info); messages.push_back(msg); } }; } // namespace exc namespace ast { /// String and collection utilities /// Split a delimiter-separated string into a vector of strings. vector split(const string &str, char delim); /// Escape a C string (replace \n with \\n etc.). string escape(const string &str); /// Unescape a C string (replace \\n with \n etc.). string unescape(const string &str); /// Escape an F-string braces (replace { and } with {{ and }}). string escapeFStringBraces(const string &str, int start, int len); /// True if a string str starts with a prefix. bool startswith(const string &str, const string &prefix); /// True if a string str ends with a suffix. bool endswith(const string &str, const string &suffix); /// Trims whitespace at the beginning of the string. void ltrim(string &str); /// Trims whitespace at the end of the string. void rtrim(string &str); /// Removes leading stars in front of the string and returns the number of such stars. int trimStars(string &str); /// True if a string only contains digits. bool isdigit(const string &str); /// Combine items separated by a delimiter into a string. template string join(const T &items, const string &delim = " ", int start = 0, int end = -1) { string s; if (end == -1) end = items.size(); for (int i = start; i < end; i++) s += (i > start ? delim : "") + items[i]; return s; } /// Combine items separated by a delimiter into a string. template string combine(const vector &items, const string &delim = " ") { string s; for (int i = 0; i < items.size(); i++) if (items[i]) s += (i ? delim : "") + items[i]->toString(); return s; } /// @return True if an item is found in a vector vec. template bool in(const vector &vec, const U &item) { auto f = std::find(vec.begin(), vec.end(), item); return f != vec.end(); } /// @return True if an item is found in a set s. template bool in(const set &s, const U &item) { auto f = s.find(item); return f != s.end(); } /// @return True if an item is found in an unordered_set s. template bool in(const unordered_set &s, const U &item) { auto f = s.find(item); return f != s.end(); } /// @return True if an item is found in a map m. template bool in(const map &m, const U &item) { auto f = m.find(item); return f != m.end(); } /// @return True if an item is found in an unordered_map m. template bool in(const unordered_map &m, const U &item) { auto f = m.find(item); return f != m.end(); } /// @return vector c transformed by the function f. template auto vmap(const std::vector &c, F &&f) { std::vector::type> ret; std::transform(std::begin(c), std::end(c), std::inserter(ret, std::end(ret)), f); return ret; } /// AST utilities /// Raise a parsing error. void error(const char *format); /// Raise a parsing error at a source location p. void error(const SrcInfo &info, const char *format); /// Clones a pointer even if it is a nullptr. template auto clone(const shared_ptr &t) { return t ? t->clone() : nullptr; } /// Clones a vector of cloneable pointer objects. template vector clone(const vector &t) { vector v; for (auto &i : t) v.push_back(clone(i)); return v; } /// Clones a vector of cloneable objects. template vector clone_nop(const vector &t) { vector v; for (auto &i : t) v.push_back(i.clone()); return v; } /// Path utilities /// Detect a absolute path of the current executable (whose argv0 is known). /// @return Absolute executable path or argv0 if one cannot be found. string executable_path(const char *argv0); struct ImportFile { enum Status { STDLIB, PACKAGE }; Status status; /// Absolute path of an import. string path; /// Module name (e.g. foo.bar.baz). string module; }; /// Find an import file what given an executable path (argv0) either in the standard /// library or relative to a file relativeTo. Set forceStdlib for searching only the /// standard library. shared_ptr getImportFile(const string &argv0, const string &what, const string &relativeTo, bool forceStdlib = false, const string &module0 = ""); } // namespace ast } // namespace seq