feat: add polyfill for llvm libcxx to make it possible to compile
This commit is contained in:
@@ -67,6 +67,8 @@ FILES
|
|||||||
yycc/patch/fopen.hpp
|
yycc/patch/fopen.hpp
|
||||||
yycc/patch/stream.hpp
|
yycc/patch/stream.hpp
|
||||||
yycc/patch/format.hpp
|
yycc/patch/format.hpp
|
||||||
|
yycc/patch/libcxx/enumerate.hpp
|
||||||
|
yycc/patch/libcxx/stacktrace.hpp
|
||||||
yycc/num/parse.hpp
|
yycc/num/parse.hpp
|
||||||
yycc/num/stringify.hpp
|
yycc/num/stringify.hpp
|
||||||
yycc/num/safe_cast.hpp
|
yycc/num/safe_cast.hpp
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#include "../termcolor.hpp"
|
#include "../termcolor.hpp"
|
||||||
#include "../../patch/stream.hpp"
|
#include "../../patch/stream.hpp"
|
||||||
#include "../../patch/format.hpp"
|
#include "../../patch/format.hpp"
|
||||||
|
#include "../../patch/libcxx/stacktrace.hpp"
|
||||||
#include "../../string/op.hpp"
|
#include "../../string/op.hpp"
|
||||||
#include "../../env.hpp"
|
#include "../../env.hpp"
|
||||||
#include <ranges>
|
#include <ranges>
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#include "wcwidth.hpp"
|
#include "wcwidth.hpp"
|
||||||
#include "../num/safe_op.hpp"
|
#include "../num/safe_op.hpp"
|
||||||
#include "../patch/stream.hpp"
|
#include "../patch/stream.hpp"
|
||||||
|
#include "../patch/libcxx/stacktrace.hpp"
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <ranges>
|
#include <ranges>
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "panic.hpp"
|
#include "panic.hpp"
|
||||||
#include "carton/termcolor.hpp"
|
#include "carton/termcolor.hpp"
|
||||||
#include "patch/stream.hpp"
|
#include "patch/stream.hpp"
|
||||||
|
#include "patch/libcxx/stacktrace.hpp"
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|||||||
251
src/yycc/patch/libcxx/enumerate.hpp
Normal file
251
src/yycc/patch/libcxx/enumerate.hpp
Normal file
@@ -0,0 +1,251 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "../../macro/stl_detector.hpp"
|
||||||
|
|
||||||
|
#if defined(YYCC_STL_CLANGSTL)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @file This is the polyfill for LLVM libcxx std::enumerate.
|
||||||
|
* This should be removed once libcxx provide it.
|
||||||
|
* This polyfill is generated by AI.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ranges>
|
||||||
|
#include <utility>
|
||||||
|
#include <tuple>
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
namespace std {
|
||||||
|
|
||||||
|
namespace ranges {
|
||||||
|
namespace views {
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
concept can_reference = requires { typename T&; };
|
||||||
|
|
||||||
|
template<typename V, typename I>
|
||||||
|
concept enumerable =
|
||||||
|
ranges::input_range<V> &&
|
||||||
|
integral<I> &&
|
||||||
|
ranges::view<V>;
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
// enumerate_view实现
|
||||||
|
template<ranges::view V, typename I = size_t>
|
||||||
|
requires detail::enumerable<V, I>
|
||||||
|
class enumerate_view : public ranges::view_interface<enumerate_view<V, I>> {
|
||||||
|
private:
|
||||||
|
V _base;
|
||||||
|
I _start;
|
||||||
|
|
||||||
|
// 迭代器实现
|
||||||
|
template<bool Const>
|
||||||
|
class iterator {
|
||||||
|
private:
|
||||||
|
using Base = conditional_t<Const, const V, V>;
|
||||||
|
using Parent = conditional_t<Const, const enumerate_view, enumerate_view>;
|
||||||
|
|
||||||
|
Parent* _parent = nullptr;
|
||||||
|
ranges::iterator_t<Base> _current;
|
||||||
|
I _index;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using iterator_category = typename iterator_traits<ranges::iterator_t<Base>>::iterator_category;
|
||||||
|
using iterator_concept = iterator_category;
|
||||||
|
using value_type = tuple<I, ranges::range_reference_t<Base>>;
|
||||||
|
using difference_type = ranges::range_difference_t<Base>;
|
||||||
|
|
||||||
|
iterator() = default;
|
||||||
|
|
||||||
|
constexpr iterator(Parent* parent, ranges::iterator_t<Base> current, I index)
|
||||||
|
: _parent(parent), _current(current), _index(index) {}
|
||||||
|
|
||||||
|
constexpr iterator(iterator<!Const> other) requires Const &&
|
||||||
|
convertible_to<ranges::iterator_t<V>, ranges::iterator_t<Base>>
|
||||||
|
: _parent(other._parent), _current(other._current), _index(other._index) {}
|
||||||
|
|
||||||
|
constexpr ranges::iterator_t<Base> base() const {
|
||||||
|
return _current;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr auto operator*() const {
|
||||||
|
return tuple<I, ranges::range_reference_t<Base>>(_index, *_current);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr iterator& operator++() {
|
||||||
|
++_current;
|
||||||
|
++_index;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr iterator operator++(int) {
|
||||||
|
auto tmp = *this;
|
||||||
|
++*this;
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr iterator& operator--() requires ranges::bidirectional_range<Base> {
|
||||||
|
--_current;
|
||||||
|
--_index;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr iterator operator--(int) requires ranges::bidirectional_range<Base> {
|
||||||
|
auto tmp = *this;
|
||||||
|
--*this;
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr iterator& operator+=(difference_type n)
|
||||||
|
requires ranges::random_access_range<Base> {
|
||||||
|
_current += n;
|
||||||
|
_index += static_cast<I>(n);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr iterator& operator-=(difference_type n)
|
||||||
|
requires ranges::random_access_range<Base> {
|
||||||
|
_current -= n;
|
||||||
|
_index -= static_cast<I>(n);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr auto operator[](difference_type n) const
|
||||||
|
requires ranges::random_access_range<Base> {
|
||||||
|
return tuple<I, ranges::range_reference_t<Base>>(
|
||||||
|
_index + static_cast<I>(n), _current[n]);
|
||||||
|
}
|
||||||
|
|
||||||
|
friend constexpr bool operator==(const iterator& x, const iterator& y) {
|
||||||
|
return x._current == y._current;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend constexpr bool operator<(const iterator& x, const iterator& y)
|
||||||
|
requires ranges::random_access_range<Base> {
|
||||||
|
return x._current < y._current;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend constexpr bool operator>(const iterator& x, const iterator& y)
|
||||||
|
requires ranges::random_access_range<Base> {
|
||||||
|
return x._current > y._current;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend constexpr bool operator<=(const iterator& x, const iterator& y)
|
||||||
|
requires ranges::random_access_range<Base> {
|
||||||
|
return x._current <= y._current;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend constexpr bool operator>=(const iterator& x, const iterator& y)
|
||||||
|
requires ranges::random_access_range<Base> {
|
||||||
|
return x._current >= y._current;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend constexpr iterator operator+(const iterator& i, difference_type n)
|
||||||
|
requires ranges::random_access_range<Base> {
|
||||||
|
auto r = i;
|
||||||
|
r += n;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend constexpr iterator operator+(difference_type n, const iterator& i)
|
||||||
|
requires ranges::random_access_range<Base> {
|
||||||
|
return i + n;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend constexpr iterator operator-(const iterator& i, difference_type n)
|
||||||
|
requires ranges::random_access_range<Base> {
|
||||||
|
auto r = i;
|
||||||
|
r -= n;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend constexpr difference_type operator-(const iterator& x, const iterator& y)
|
||||||
|
requires ranges::random_access_range<Base> {
|
||||||
|
return x._current - y._current;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
enumerate_view() = default;
|
||||||
|
|
||||||
|
constexpr enumerate_view(V base, I start = 0)
|
||||||
|
: _base(std::move(base)), _start(start) {}
|
||||||
|
|
||||||
|
constexpr V base() const & requires copy_constructible<V> {
|
||||||
|
return _base;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr V base() && {
|
||||||
|
return std::move(_base);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr I start() const {
|
||||||
|
return _start;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr auto begin() requires (!ranges::simple_view<V>) {
|
||||||
|
return iterator<false>(this, ranges::begin(_base), _start);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr auto begin() const requires ranges::range<const V> {
|
||||||
|
return iterator<true>(this, ranges::begin(_base), _start);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr auto end() requires (!ranges::simple_view<V>) {
|
||||||
|
return iterator<false>(this, ranges::end(_base),
|
||||||
|
_start + static_cast<I>(ranges::distance(_base)));
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr auto end() const requires ranges::range<const V> {
|
||||||
|
return iterator<true>(this, ranges::end(_base),
|
||||||
|
_start + static_cast<I>(ranges::distance(_base)));
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr auto size() requires ranges::sized_range<V> {
|
||||||
|
return ranges::size(_base);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr auto size() const requires ranges::sized_range<const V> {
|
||||||
|
return ranges::size(_base);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 推导指引
|
||||||
|
template<class R, class I>
|
||||||
|
enumerate_view(R&&, I) -> enumerate_view<views::all_t<R>, I>;
|
||||||
|
|
||||||
|
template<class R>
|
||||||
|
enumerate_view(R&&) -> enumerate_view<views::all_t<R>, size_t>;
|
||||||
|
|
||||||
|
// enumerate适配器对象
|
||||||
|
struct enumerate_fn {
|
||||||
|
template<ranges::viewable_range R, typename I = size_t>
|
||||||
|
requires detail::enumerable<views::all_t<R>, I>
|
||||||
|
constexpr auto operator()(R&& r, I start = 0) const {
|
||||||
|
return enumerate_view(views::all(forward<R>(r)), start);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename I = size_t>
|
||||||
|
constexpr auto operator()(I start = 0) const {
|
||||||
|
return ranges::views::__adaptor_invoke(*this, start);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 适配器对象实例
|
||||||
|
inline constexpr enumerate_fn enumerate;
|
||||||
|
|
||||||
|
} // namespace views
|
||||||
|
|
||||||
|
// 使enumerate_view成为view
|
||||||
|
template<typename V, typename I>
|
||||||
|
inline constexpr bool enable_borrowed_range<views::enumerate_view<V, I>> =
|
||||||
|
ranges::enable_borrowed_range<V>;
|
||||||
|
|
||||||
|
} // namespace ranges
|
||||||
|
|
||||||
|
} // namespace std
|
||||||
|
|
||||||
|
#endif
|
||||||
146
src/yycc/patch/libcxx/stacktrace.hpp
Normal file
146
src/yycc/patch/libcxx/stacktrace.hpp
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "../../macro/stl_detector.hpp"
|
||||||
|
|
||||||
|
#if defined(YYCC_STL_CLANGSTL)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @file This is the polyfill for LLVM libcxx std::stacktrace.
|
||||||
|
* This should be removed once libcxx provide it.
|
||||||
|
* This polyfill is generated by AI.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <sstream>
|
||||||
|
#include <vector>
|
||||||
|
#include <memory>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace std {
|
||||||
|
|
||||||
|
// 空实现的stacktrace_entry
|
||||||
|
class stacktrace_entry {
|
||||||
|
public:
|
||||||
|
constexpr stacktrace_entry() noexcept = default;
|
||||||
|
constexpr stacktrace_entry(const stacktrace_entry&) noexcept = default;
|
||||||
|
stacktrace_entry& operator=(const stacktrace_entry&) noexcept = default;
|
||||||
|
|
||||||
|
constexpr explicit operator bool() const noexcept { return false; }
|
||||||
|
|
||||||
|
string description() const { return ""; }
|
||||||
|
|
||||||
|
constexpr void* native_handle() const noexcept { return nullptr; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
// 使用void*作为占位符
|
||||||
|
void* _handle = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 比较运算符
|
||||||
|
constexpr bool operator==(const stacktrace_entry&, const stacktrace_entry&) noexcept {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool operator!=(const stacktrace_entry&, const stacktrace_entry&) noexcept {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool operator<(const stacktrace_entry&, const stacktrace_entry&) noexcept {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool operator<=(const stacktrace_entry&, const stacktrace_entry&) noexcept {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool operator>(const stacktrace_entry&, const stacktrace_entry&) noexcept {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool operator>=(const stacktrace_entry&, const stacktrace_entry&) noexcept {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 流输出运算符
|
||||||
|
template<class charT, class traits>
|
||||||
|
basic_ostream<charT, traits>& operator<<(
|
||||||
|
basic_ostream<charT, traits>& os, const stacktrace_entry&) {
|
||||||
|
return os << basic_string<charT, traits>("<stacktrace not supported>");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 空实现的stacktrace类
|
||||||
|
class stacktrace {
|
||||||
|
public:
|
||||||
|
using value_type = stacktrace_entry;
|
||||||
|
using const_iterator = const stacktrace_entry*;
|
||||||
|
using iterator = const_iterator;
|
||||||
|
using reference = const stacktrace_entry&;
|
||||||
|
using const_reference = const stacktrace_entry&;
|
||||||
|
using difference_type = ptrdiff_t;
|
||||||
|
using size_type = size_t;
|
||||||
|
|
||||||
|
// 构造和析构
|
||||||
|
constexpr stacktrace() noexcept = default;
|
||||||
|
stacktrace(const stacktrace&) = default;
|
||||||
|
stacktrace& operator=(const stacktrace&) = default;
|
||||||
|
~stacktrace() = default;
|
||||||
|
|
||||||
|
// 始终返回空的stacktrace
|
||||||
|
static stacktrace current(size_t = 0) noexcept {
|
||||||
|
return stacktrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 容量
|
||||||
|
constexpr size_type size() const noexcept { return 0; }
|
||||||
|
constexpr size_type max_size() const noexcept { return 0; }
|
||||||
|
constexpr bool empty() const noexcept { return true; }
|
||||||
|
|
||||||
|
// 元素访问
|
||||||
|
const_reference operator[](size_type) const noexcept {
|
||||||
|
static stacktrace_entry entry;
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
const_reference at(size_type) const {
|
||||||
|
throw out_of_range("stacktrace is empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 迭代器
|
||||||
|
constexpr const_iterator begin() const noexcept { return nullptr; }
|
||||||
|
constexpr const_iterator end() const noexcept { return nullptr; }
|
||||||
|
constexpr const_iterator cbegin() const noexcept { return nullptr; }
|
||||||
|
constexpr const_iterator cend() const noexcept { return nullptr; }
|
||||||
|
|
||||||
|
// 比较
|
||||||
|
friend bool operator==(const stacktrace&, const stacktrace&) noexcept {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend bool operator!=(const stacktrace&, const stacktrace&) noexcept {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// 无数据成员
|
||||||
|
};
|
||||||
|
|
||||||
|
// stacktrace的流输出
|
||||||
|
template<class charT, class traits>
|
||||||
|
basic_ostream<charT, traits>& operator<<(
|
||||||
|
basic_ostream<charT, traits>& os, const stacktrace&) {
|
||||||
|
return os << basic_string<charT, traits>("Stacktrace is not supported in this implementation");
|
||||||
|
}
|
||||||
|
|
||||||
|
// to_string函数
|
||||||
|
inline string to_string(const stacktrace_entry&) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
inline string to_string(const stacktrace&) {
|
||||||
|
return "stacktrace not supported";
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace std
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user