about summary refs log tree commit diff
path: root/test/dada.hpp
diff options
context:
space:
mode:
authorVincent Ambo <mail@tazj.in>2020-07-15T07·20+0100
committerVincent Ambo <mail@tazj.in>2020-07-15T07·20+0100
commit7f19d641647ac4ef313ed88d6b5c140983ce5436 (patch)
tree31b66c81465293da5c093c5dde3e419758c0d6cc /test/dada.hpp
Squashed 'third_party/immer/' content from commit ad3e3556d
git-subtree-dir: third_party/immer
git-subtree-split: ad3e3556d38bb75966dd24c61a774970a7c7957e
Diffstat (limited to 'test/dada.hpp')
-rw-r--r--test/dada.hpp243
1 files changed, 243 insertions, 0 deletions
diff --git a/test/dada.hpp b/test/dada.hpp
new file mode 100644
index 000000000000..1465bf7bf52d
--- /dev/null
+++ b/test/dada.hpp
@@ -0,0 +1,243 @@
+//
+// immer: immutable data structures for C++
+// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
+//
+// This software is distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
+//
+
+#pragma once
+
+#include <array>
+#include <cstddef>
+#include <utility>
+
+#include <immer/detail/hamts/bits.hpp>
+#include <immer/detail/rbts/bits.hpp>
+
+namespace {
+
+template <typename Iterator>
+struct rotator
+{
+    using value_type = typename std::iterator_traits<Iterator>::value_type;
+
+    Iterator first;
+    Iterator last;
+    Iterator curr;
+
+    void init(Iterator f, Iterator l)
+    {
+        first = f;
+        last  = l;
+        curr  = f;
+    }
+
+    value_type next()
+    {
+        if (curr == last)
+            curr = first;
+        return *curr++;
+    }
+};
+
+template <typename Range>
+struct range_rotator : rotator<typename Range::iterator>
+{
+    using base_t = rotator<typename Range::iterator>;
+
+    Range range;
+
+    range_rotator(Range r)
+        : range{std::move(r)}
+    {
+        base_t::init(range.begin(), range.end());
+    }
+};
+
+template <typename Range>
+auto make_rotator(Range r) -> range_rotator<Range>
+{
+    return {r};
+}
+
+inline auto magic_rotator()
+{
+    return make_rotator(std::array<unsigned, 15>{
+        {7, 11, 2, 3, 5, 7, 11, 13, 17, 19, 23, 5, 29, 31, 37}});
+}
+
+struct dada_error
+{};
+
+struct dadaism;
+static dadaism* g_dadaism = nullptr;
+
+struct dadaism
+{
+    using rotator_t = decltype(magic_rotator());
+
+    rotator_t magic = magic_rotator();
+
+    unsigned step       = magic.next();
+    unsigned count      = 0;
+    unsigned happenings = 0;
+    unsigned last       = 0;
+    bool toggle         = false;
+
+    struct scope
+    {
+        bool moved     = false;
+        dadaism* save_ = g_dadaism;
+        scope(scope&& s)
+        {
+            save_   = s.save_;
+            s.moved = true;
+        }
+        scope(dadaism* self) { g_dadaism = self; }
+        ~scope()
+        {
+            if (!moved)
+                g_dadaism = save_;
+        }
+    };
+
+    static scope disable() { return {nullptr}; }
+
+    scope next()
+    {
+        toggle = last == happenings;
+        last   = happenings;
+        step   = toggle ? step : magic.next();
+        return {this};
+    }
+
+    void dada()
+    {
+        if (toggle && ++count % step == 0) {
+            ++happenings;
+            throw dada_error{};
+        }
+    }
+};
+
+inline void dada()
+{
+    if (g_dadaism)
+        g_dadaism->dada();
+}
+
+inline bool soft_dada()
+{
+    try {
+        dada();
+        return false;
+    } catch (dada_error) {
+        return true;
+    }
+}
+
+template <typename Heap>
+struct dadaist_heap : Heap
+{
+    template <typename... Tags>
+    static auto allocate(std::size_t s, Tags... tags)
+    {
+        dada();
+        return Heap::allocate(s, tags...);
+    }
+};
+
+template <typename MP>
+struct dadaist_memory_policy : MP
+{
+    struct heap
+    {
+        using type = dadaist_heap<typename MP::heap::type>;
+
+        template <std::size_t Size>
+        struct optimized
+        {
+            using base = typename MP::heap::template optimized<Size>::type;
+            using type = dadaist_heap<base>;
+        };
+    };
+};
+
+struct tristan_tzara
+{
+    tristan_tzara() { dada(); }
+    tristan_tzara(const tristan_tzara&) { dada(); }
+    tristan_tzara(tristan_tzara&&) { dada(); }
+    tristan_tzara& operator=(const tristan_tzara&)
+    {
+        dada();
+        return *this;
+    }
+    tristan_tzara& operator=(tristan_tzara&&)
+    {
+        dada();
+        return *this;
+    }
+};
+
+template <typename T>
+struct dadaist : tristan_tzara
+{
+    T value;
+
+    dadaist()
+        : value{}
+    {}
+    dadaist(T v)
+        : value{std::move(v)}
+    {}
+    operator T() const { return value; }
+};
+
+template <typename T>
+struct dadaist_wrapper;
+
+using rbits_t = immer::detail::rbts::bits_t;
+using hbits_t = immer::detail::rbts::bits_t;
+
+template <template <class, class, rbits_t, rbits_t> class V,
+          typename T,
+          typename MP,
+          rbits_t B,
+          rbits_t BL>
+struct dadaist_wrapper<V<T, MP, B, BL>>
+{
+    using type = V<dadaist<T>, dadaist_memory_policy<MP>, B, BL>;
+};
+
+template <template <class, class> class V, typename T, typename MP>
+struct dadaist_wrapper<V<T, MP>>
+{
+    using type = V<dadaist<T>, dadaist_memory_policy<MP>>;
+};
+
+template <template <class, class, class, class, hbits_t> class V,
+          typename T,
+          typename E,
+          typename H,
+          typename MP,
+          hbits_t B>
+struct dadaist_wrapper<V<T, H, E, MP, B>>
+{
+    using type = V<dadaist<T>, H, E, dadaist_memory_policy<MP>, B>;
+};
+
+template <template <class, class, class, class, class, hbits_t> class V,
+          typename K,
+          typename T,
+          typename E,
+          typename H,
+          typename MP,
+          hbits_t B>
+struct dadaist_wrapper<V<K, T, H, E, MP, B>>
+{
+    using type = V<K, dadaist<T>, H, E, dadaist_memory_policy<MP>, B>;
+};
+
+} // anonymous namespace