Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial, experimental modules support #106

Merged
merged 5 commits into from
Jul 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions include/flux/core/assert.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

namespace flux {

FLUX_EXPORT
struct unrecoverable_error : std::logic_error {
explicit unrecoverable_error(char const* msg) : std::logic_error(msg) {}
};
Expand Down Expand Up @@ -44,7 +45,7 @@ struct runtime_error_fn {

}

inline constexpr auto runtime_error = detail::runtime_error_fn{};
FLUX_EXPORT inline constexpr auto runtime_error = detail::runtime_error_fn{};

namespace detail {

Expand All @@ -71,8 +72,8 @@ struct bounds_check_fn {

} // namespace detail

inline constexpr auto assert_ = detail::assert_fn{};
inline constexpr auto bounds_check = detail::bounds_check_fn{};
FLUX_EXPORT inline constexpr auto assert_ = detail::assert_fn{};
FLUX_EXPORT inline constexpr auto bounds_check = detail::bounds_check_fn{};

#define FLUX_ASSERT(cond) (::flux::assert_(cond, "assertion '" #cond "' failed"))

Expand Down
23 changes: 23 additions & 0 deletions include/flux/core/concepts.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,15 @@ namespace flux {
/*
* Cursor concepts
*/
FLUX_EXPORT
template <typename Cur>
concept cursor = std::movable<Cur>;

FLUX_EXPORT
template <typename Cur>
concept regular_cursor = cursor<Cur> && std::regular<Cur>;

FLUX_EXPORT
template <typename Cur>
concept ordered_cursor =
regular_cursor<Cur> &&
Expand All @@ -40,6 +43,7 @@ concept ordered_cursor =
* Sequence concepts and associated types
*/

FLUX_EXPORT
template <typename T>
struct sequence_traits;

Expand All @@ -50,9 +54,11 @@ using traits_t = sequence_traits<std::remove_cvref_t<T>>;

} // namespace detail

FLUX_EXPORT
template <typename Seq>
using cursor_t = decltype(detail::traits_t<Seq>::first(FLUX_DECLVAL(Seq&)));

FLUX_EXPORT
template <typename Seq>
using element_t = decltype(detail::traits_t<Seq>::read_at(FLUX_DECLVAL(Seq&), FLUX_DECLVAL(cursor_t<Seq> const&)));

Expand Down Expand Up @@ -93,19 +99,25 @@ struct rvalue_element_type<T> {

} // namespace detail

FLUX_EXPORT
template <typename Seq>
using value_t = typename detail::value_type<Seq>::type;

FLUX_EXPORT
using distance_t = flux::config::int_type;

FLUX_EXPORT
using index_t = flux::config::int_type;

FLUX_EXPORT
template <typename Seq>
using rvalue_element_t = typename detail::rvalue_element_type<Seq>::type;

FLUX_EXPORT
template <typename Seq>
using common_element_t = std::common_reference_t<element_t<Seq>, value_t<Seq>&>;

FLUX_EXPORT
template <typename Seq>
using const_element_t = std::common_reference_t<value_t<Seq> const&&, element_t<Seq>>;

Expand Down Expand Up @@ -144,6 +156,7 @@ concept sequence_concept =

} // namespace detail

FLUX_EXPORT
template <typename Seq>
concept sequence = detail::sequence_concept<Seq>;

Expand All @@ -159,6 +172,7 @@ inline constexpr bool disable_multipass<T> = T::disable_multipass;

} // namespace detail

FLUX_EXPORT
template <typename Seq>
concept multipass_sequence =
sequence<Seq> && regular_cursor<cursor_t<Seq>> &&
Expand All @@ -175,6 +189,7 @@ concept bidirectional_sequence_concept =

} // namespace detail

FLUX_EXPORT
template <typename Seq>
concept bidirectional_sequence = detail::bidirectional_sequence_concept<Seq>;

Expand All @@ -192,6 +207,7 @@ concept random_access_sequence_concept =

} // namespace detail

FLUX_EXPORT
template <typename Seq>
concept random_access_sequence = detail::random_access_sequence_concept<Seq>;

Expand All @@ -208,6 +224,7 @@ concept contiguous_sequence_concept =

} // namespace detail

FLUX_EXPORT
template <typename Seq>
concept contiguous_sequence = detail::contiguous_sequence_concept<Seq>;

Expand All @@ -222,6 +239,7 @@ concept bounded_sequence_concept =

} // namespace detail

FLUX_EXPORT
template <typename Seq>
concept bounded_sequence = detail::bounded_sequence_concept<Seq>;

Expand All @@ -238,9 +256,11 @@ concept sized_sequence_concept =

} // namespace detail

FLUX_EXPORT
template <typename Seq>
concept sized_sequence = detail::sized_sequence_concept<Seq>;

FLUX_EXPORT
template <typename Seq, typename T>
concept writable_sequence_of =
sequence<Seq> &&
Expand All @@ -260,11 +280,13 @@ inline constexpr bool is_infinite_seq<T> = T::is_infinite;

}

FLUX_EXPORT
template <typename Seq>
concept infinite_sequence =
sequence<Seq> &&
detail::is_infinite_seq<detail::traits_t<Seq>>;

FLUX_EXPORT
template <typename Seq>
concept read_only_sequence =
sequence<Seq> &&
Expand Down Expand Up @@ -292,6 +314,7 @@ concept trivially_copyable_sequence =

}

FLUX_EXPORT
template <typename Seq>
concept adaptable_sequence =
(detail::rvalue_sequence<Seq>
Expand Down
9 changes: 9 additions & 0 deletions include/flux/core/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#ifndef FLUX_CORE_CONFIG_HPP_INCLUDED
#define FLUX_CORE_CONFIG_HPP_INCLUDED

#include <flux/core/macros.hpp>

#include <concepts>
#include <cstddef>
#include <type_traits>
Expand Down Expand Up @@ -71,11 +73,13 @@

namespace flux {

FLUX_EXPORT
enum class error_policy {
terminate = FLUX_ERROR_POLICY_TERMINATE,
unwind = FLUX_ERROR_POLICY_UNWIND
};

FLUX_EXPORT
enum class overflow_policy {
ignore = FLUX_OVERFLOW_POLICY_IGNORE,
wrap = FLUX_OVERFLOW_POLICY_WRAP,
Expand All @@ -84,16 +88,21 @@ enum class overflow_policy {

namespace config {

FLUX_EXPORT
using int_type = FLUX_INT_TYPE;
static_assert(std::signed_integral<int_type> && (sizeof(int_type) >= sizeof(std::ptrdiff_t)),
"Custom FLUX_INT_TYPE must be a signed integer type at least as large as ptrdiff_t");

FLUX_EXPORT
inline constexpr error_policy on_error = static_cast<error_policy>(FLUX_ERROR_POLICY);

FLUX_EXPORT
inline constexpr overflow_policy on_overflow = static_cast<overflow_policy>(FLUX_OVERFLOW_POLICY);

FLUX_EXPORT
inline constexpr bool print_error_on_terminate = FLUX_PRINT_ERROR_ON_TERMINATE;

FLUX_EXPORT
inline constexpr bool enable_debug_asserts = FLUX_ENABLE_DEBUG_ASSERTS;

} // namespace config
Expand Down
42 changes: 22 additions & 20 deletions include/flux/core/functional.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

namespace flux {

FLUX_EXPORT
template <typename Fn, typename Proj = std::identity>
struct proj {
Fn fn;
Expand All @@ -38,6 +39,7 @@ struct proj {
template <typename F, typename P = std::identity>
proj(F, P = {}) -> proj<F, P>;

FLUX_EXPORT
template <typename Fn, typename Lhs = std::identity, typename Rhs = std::identity>
struct proj2 {
Fn fn;
Expand Down Expand Up @@ -120,7 +122,7 @@ struct unpack_fn {

} // namespace detail

inline constexpr auto unpack = detail::unpack_fn{};
FLUX_EXPORT inline constexpr auto unpack = detail::unpack_fn{};

namespace pred {

Expand All @@ -142,7 +144,7 @@ inline constexpr auto cmp = [](auto&& val) {
} // namespace detail

/// Given a predicate, returns a new predicate with the condition reversed
inline constexpr auto not_ = [](auto&& pred) {
FLUX_EXPORT inline constexpr auto not_ = [](auto&& pred) {
return detail::predicate([p = FLUX_FWD(pred)] (auto const&... args) {
return !std::invoke(p, FLUX_FWD(args)...);
});
Expand All @@ -153,7 +155,7 @@ inline constexpr auto not_ = [](auto&& pred) {
///
/// The returned predicate is short-circuiting: if the first predicate returns
/// `false`, the second will not be evaluated.
inline constexpr auto both = [](auto&& p, auto&& and_) {
FLUX_EXPORT inline constexpr auto both = [](auto&& p, auto&& and_) {
return detail::predicate{[p1 = FLUX_FWD(p), p2 = FLUX_FWD(and_)] (auto const&... args) {
return std::invoke(p1, args...) && std::invoke(p2, args...);
}};
Expand All @@ -164,7 +166,7 @@ inline constexpr auto both = [](auto&& p, auto&& and_) {
///
/// The returned predicate is short-circuiting: if the first predicate returns
/// `true`, the second will not be evaluated
inline constexpr auto either = [](auto&& p, auto&& or_) {
FLUX_EXPORT inline constexpr auto either = [](auto&& p, auto&& or_) {
return detail::predicate{[p1 = FLUX_FWD(p), p2 = FLUX_FWD(or_)] (auto const&... args) {
return std::invoke(p1, args...) || std::invoke(p2, args...);
}};
Expand Down Expand Up @@ -197,55 +199,55 @@ constexpr auto operator||(detail::predicate<L> lhs, detail::predicate<R> rhs)
///
/// The returned predicate is short-circuiting: if the first predicate returns
/// `true`, the second will not be evaluated.
inline constexpr auto neither = [](auto&& p1, auto&& nor) {
FLUX_EXPORT inline constexpr auto neither = [](auto&& p1, auto&& nor) {
return not_(either(FLUX_FWD(p1), FLUX_FWD(nor)));
};

inline constexpr auto eq = detail::cmp<std::ranges::equal_to>;
inline constexpr auto neq = detail::cmp<std::ranges::not_equal_to>;
inline constexpr auto lt = detail::cmp<std::ranges::less>;
inline constexpr auto gt = detail::cmp<std::ranges::greater>;
inline constexpr auto leq = detail::cmp<std::ranges::less_equal>;
inline constexpr auto geq = detail::cmp<std::ranges::greater_equal>;
FLUX_EXPORT inline constexpr auto eq = detail::cmp<std::ranges::equal_to>;
FLUX_EXPORT inline constexpr auto neq = detail::cmp<std::ranges::not_equal_to>;
FLUX_EXPORT inline constexpr auto lt = detail::cmp<std::ranges::less>;
FLUX_EXPORT inline constexpr auto gt = detail::cmp<std::ranges::greater>;
FLUX_EXPORT inline constexpr auto leq = detail::cmp<std::ranges::less_equal>;
FLUX_EXPORT inline constexpr auto geq = detail::cmp<std::ranges::greater_equal>;

/// A predicate which always returns true
inline constexpr auto true_ = detail::predicate{[](auto const&...) -> bool { return true; }};
FLUX_EXPORT inline constexpr auto true_ = detail::predicate{[](auto const&...) -> bool { return true; }};

/// A predicate which always returns false
inline constexpr auto false_ = detail::predicate{[](auto const&...) -> bool { return false; }};
FLUX_EXPORT inline constexpr auto false_ = detail::predicate{[](auto const&...) -> bool { return false; }};

/// Identity predicate, returns the boolean value given to it
inline constexpr auto id = detail::predicate{[](bool b) -> bool { return b; }};
FLUX_EXPORT inline constexpr auto id = detail::predicate{[](bool b) -> bool { return b; }};

/// Returns true if the given value is greater than a zero of the same type.
inline constexpr auto positive = detail::predicate{[](auto const& val) -> bool {
FLUX_EXPORT inline constexpr auto positive = detail::predicate{[](auto const& val) -> bool {
return val > decltype(val){0};
}};

/// Returns true if the given value is less than a zero of the same type.
inline constexpr auto negative = detail::predicate{[](auto const& val) -> bool {
FLUX_EXPORT inline constexpr auto negative = detail::predicate{[](auto const& val) -> bool {
return val < decltype(val){0};
}};

/// Returns true if the given value is not equal to a zero of the same type.
inline constexpr auto nonzero = detail::predicate{[](auto const& val) -> bool {
FLUX_EXPORT inline constexpr auto nonzero = detail::predicate{[](auto const& val) -> bool {
return val != decltype(val){0};
}};

/// Given a sequence of values, constructs a predicate which returns true
/// if its argument compares equal to one of the values
inline constexpr auto in = [](auto const&... vals) requires (sizeof...(vals) > 0)
FLUX_EXPORT inline constexpr auto in = [](auto const&... vals) requires (sizeof...(vals) > 0)
{
return detail::predicate{[vals...](auto const& arg) -> bool {
return ((arg == vals) || ...);
}};
};

inline constexpr auto even = detail::predicate([](auto const& val) -> bool {
FLUX_EXPORT inline constexpr auto even = detail::predicate([](auto const& val) -> bool {
return val % decltype(val){2} == decltype(val){0};
});

inline constexpr auto odd = detail::predicate([](auto const& val) -> bool {
FLUX_EXPORT inline constexpr auto odd = detail::predicate([](auto const& val) -> bool {
return val % decltype(val){2} != decltype(val){0};
});

Expand Down
2 changes: 2 additions & 0 deletions include/flux/core/inline_sequence_base.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

namespace flux {

FLUX_EXPORT
template <cursor Cur>
struct bounds {
FLUX_NO_UNIQUE_ADDRESS Cur from;
Expand All @@ -23,6 +24,7 @@ struct bounds {
template <cursor Cur>
bounds(Cur, Cur) -> bounds<Cur>;

FLUX_EXPORT
template <sequence Seq>
using bounds_t = bounds<cursor_t<Seq>>;

Expand Down
6 changes: 6 additions & 0 deletions include/flux/core/macros.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,10 @@
::flux::inc(_flux_seq_, _flux_cur_)) \
if (_flux_var_decl_ = ::flux::read_at(_flux_seq_, _flux_cur_); true)

#ifdef FLUX_MODULE_INTERFACE
#define FLUX_EXPORT export
#else
#define FLUX_EXPORT
#endif

#endif // FLUX_CORE_MACROS_HPP_INCLUDED
Loading