1#ifndef HALCHECK_GEN_SHRINKS_HPP
2#define HALCHECK_GEN_SHRINKS_HPP
4#include <halcheck/gen/label.hpp>
5#include <halcheck/gen/shrink.hpp>
6#include <halcheck/lib/any.hpp>
7#include <halcheck/lib/atom.hpp>
8#include <halcheck/lib/effect.hpp>
9#include <halcheck/lib/functional.hpp>
10#include <halcheck/lib/iterator.hpp>
11#include <halcheck/lib/optional.hpp>
12#include <halcheck/lib/pp.hpp>
13#include <halcheck/lib/scope.hpp>
14#include <halcheck/lib/trie.hpp>
15#include <halcheck/lib/type_traits.hpp>
16#include <halcheck/lib/utility.hpp>
26namespace halcheck {
namespace gen {
46 : calls(calls), input(input) {}
48 lib::optional<lib::trie<lib::atom, lib::optional<std::uintmax_t>>> operator()() {
49 while (call_index < calls->
size() && sample_index == (*calls)[call_index].
size) {
54 if (call_index == calls->size())
57 return input->set((*calls)[call_index].path, sample_index++);
61 const lib::trie<lib::atom, lib::optional<std::uintmax_t>> *input =
nullptr;
66struct shrink_handler : lib::effect::handler<shrink_handler, gen::shrink_effect, gen::label_effect> {
68 lib::trie<
lib::atom, lib::optional<std::uintmax_t>> input,
71 : input(
std::move(input)), path(
std::move(path)), calls(
std::move(calls)) {}
73 lib::optional<std::uintmax_t> operator()(gen::shrink_effect args)
final {
75 if (!output && args.size > 0) {
76 if (
auto locked = calls.lock()) {
78 locked->data.push_back({path, args.size});
79 locked->size += args.size;
82 if (args.size == 0 || !output)
85 return std::min(*output, args.size - 1);
88 lib::finally_t<> operator()(gen::label_effect args)
final {
90 input = input.drop(args.value);
91 path.push_back(args.value);
98 lib::trie<lib::atom, lib::optional<std::uintmax_t>> input;
108 template<
typename F,
typename... Args,
HALCHECK_REQUIRE(lib::is_invocable_r<T, F, Args...>())>
109 shrinks(lib::trie<
lib::atom, lib::optional<std::uintmax_t>> input, F func, Args &&...args)
116 class children_view :
public lib::view_interface<children_view> {
118 explicit children_view(
const shrinks &parent) : _parent(&parent) {}
120 lib::generate_iterator<detail::to_tries> begin()
const {
121 return lib::make_generate_iterator(detail::to_tries{&_parent->_calls, &_parent->_input});
124 lib::generate_iterator<detail::to_tries> end()
const {
return {}; }
129 const shrinks *_parent;
132 children_view children()
const {
return children_view(*
this); }
135 template<
typename F,
typename... Args>
138 lib::trie<
lib::atom, lib::optional<std::uintmax_t>> input,
141 : _value(detail::shrink_handler(input, {}, calls).handle([&] {
146 return std::move(calls->data);
148 _input(std::move(input)), _size(calls->size) {}
150 lib::result_holder<T> _value;
152 lib::trie<lib::atom, lib::optional<std::uintmax_t>> _input;
157 template<
typename F,
typename... Args,
HALCHECK_REQUIRE(lib::is_invocable<F, Args...>())>
159 operator()(lib::trie<
lib::atom, lib::optional<std::uintmax_t>> input, F func, Args &&...args)
const {
166 template<
typename F,
typename... Args,
HALCHECK_REQUIRE(lib::is_invocable<F, Args...>())>
169 lib::trie<lib::atom, lib::optional<std::uintmax_t>>(),
static struct halcheck::gen::@9 label
Extends the unique identifiers passed to other random generation functions.
std::uintmax_t size()
Gets the maximum size of value that should be generated.
Definition size.hpp:35
lib::variant< lib::symbol, lib::number > atom
An atom is either a symbol or a number.
Definition atom.hpp:194
decltype(lib::invoke(std::declval< F >(), std::declval< Args >()...)) invoke_result_t
An implementation of std::invoke_result_t.
Definition invoke.hpp:42
HALCHECK_INLINE_CONSTEXPR struct halcheck::lib::@25 size
Obtains the size of a range.
static constexpr nullopt_t nullopt
An implementation of std::nullopt.
Definition optional.hpp:41
#define HALCHECK_INLINE_CONSTEXPR
A backwards-compatible substitute for inline constexpr.
Definition pp.hpp:70
lib::finally_t< F > finally(F func)
Definition scope.hpp:157
typename std::add_lvalue_reference< T >::type add_lvalue_reference_t
An implementation of std::add_lvalue_reference_t.
Definition type_traits.hpp:199
#define HALCHECK_REQUIRE(...)
Expands to a template argument that is only valid if the given argument evaluates to true.
Definition type_traits.hpp:24