aboutsummaryrefslogtreecommitdiffstats
path: root/nihil.monad
diff options
context:
space:
mode:
authorLexi Winter <lexi@le-fay.org>2025-07-02 03:25:28 +0100
committerLexi Winter <lexi@le-fay.org>2025-07-02 03:25:28 +0100
commita4607e29540a9352c35afff17193ceeab137cc9d (patch)
tree0e9c2ea9c94f17b81f222fd6ebf1ccd75bb1f7f8 /nihil.monad
parentbde0492644845de63cf95b8997c5e613a9247826 (diff)
downloadnihil-a4607e29540a9352c35afff17193ceeab137cc9d.tar.gz
nihil-a4607e29540a9352c35afff17193ceeab137cc9d.tar.bz2
move monad to util
Diffstat (limited to 'nihil.monad')
-rw-r--r--nihil.monad/CMakeLists.txt22
-rw-r--r--nihil.monad/monad.ccm282
-rw-r--r--nihil.monad/test.cc64
3 files changed, 0 insertions, 368 deletions
diff --git a/nihil.monad/CMakeLists.txt b/nihil.monad/CMakeLists.txt
deleted file mode 100644
index f82e464..0000000
--- a/nihil.monad/CMakeLists.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-# This source code is released into the public domain.
-
-add_library(nihil.monad STATIC)
-target_link_libraries(nihil.monad PRIVATE nihil.std nihil.error)
-target_sources(nihil.monad
- PUBLIC FILE_SET modules TYPE CXX_MODULES FILES
- monad.ccm
-)
-
-if(NIHIL_TESTS)
- enable_testing()
-
- add_executable(nihil.monad.test test.cc)
- target_link_libraries(nihil.monad.test PRIVATE
- nihil.monad
- Catch2::Catch2WithMain
- )
-
- include(CTest)
- include(Catch)
- catch_discover_tests(nihil.monad.test)
-endif()
diff --git a/nihil.monad/monad.ccm b/nihil.monad/monad.ccm
deleted file mode 100644
index cd17e0f..0000000
--- a/nihil.monad/monad.ccm
+++ /dev/null
@@ -1,282 +0,0 @@
-/*
- * From https://github.com/toby-allsopp/coroutine_monad
- *
- * Copyright (c) 2017 Toby Allsopp
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-export module nihil.monad;
-
-import nihil.std;
-
-namespace nihil {
-
-/**********************************************************************
- * return_object_holder
- */
-
-// An object that starts out unitialized. Initialized by a call to emplace.
-export template <typename T>
-using deferred = std::optional<T>;
-
-export template <typename T>
-struct return_object_holder {
- // The staging object that is returned (by copy/move) to the caller of
- // the coroutine.
- deferred<T> stage;
- return_object_holder*& p;
-
- // When constructed, we assign a pointer to ourselves to the supplied
- // reference to pointer.
- return_object_holder(return_object_holder*& p)
- : stage{}
- , p(p)
- {
- p = this;
- }
-
- // Copying doesn't make any sense (which copy should the pointer refer
- // to?).
- return_object_holder(return_object_holder const&) = delete;
-
- // To move, we just update the pointer to point at the new object.
- return_object_holder(return_object_holder&& other)
- : stage(std::move(other.stage))
- , p(other.p)
- {
- p = this;
- }
-
- // Assignment doesn't make sense.
- void operator=(return_object_holder const&) = delete;
- void operator=(return_object_holder&&) = delete;
-
- // A non-trivial destructor is required until
- // https://bugs.llvm.org//show_bug.cgi?id=28593 is fixed.
- ~return_object_holder() {}
-
- // Construct the staging value; arguments are perfect forwarded to T's
- // constructor.
- template <typename... Args>
- void emplace(Args&&... args)
- {
- stage.emplace(std::forward<Args>(args)...);
- }
-
- // We assume that we will be converted only once, so we can move from
- // the staging object. We also assume that `emplace` has been called
- // at least once.
- operator T()
- {
- return std::move(*stage);
- }
-};
-
-export template <typename T>
-auto make_return_object_holder(return_object_holder<T>*& p)
-{
- return return_object_holder<T>{p};
-}
-
-/**********************************************************************
- * std::optional
- */
-
-template <typename T>
-struct optional_promise {
- return_object_holder<std::optional<T>>* data;
-
- auto get_return_object()
- {
- return make_return_object_holder(data);
- }
-
- auto initial_suspend() noexcept -> std::suspend_never
- {
- return {};
- }
-
- auto final_suspend() noexcept -> std::suspend_never
- {
- return {};
- }
-
- void return_value(T x)
- {
- data->emplace(std::move(x));
- }
-
- void unhandled_exception()
- {
- std::rethrow_exception(std::current_exception());
- }
-};
-
-} // namespace nihil
-
-export template <typename T, typename... Args>
-struct std::coroutine_traits<std::optional<T>, Args...> {
- using promise_type = nihil::optional_promise<T>;
-};
-
-namespace nihil {
-
-template <typename T>
-struct optional_awaitable {
- std::optional<T> o;
-
- auto await_ready()
- {
- return o.has_value();
- }
-
- auto await_resume()
- {
- return *o;
- }
-
- template <typename U>
- void await_suspend(std::coroutine_handle<optional_promise<U>> h)
- {
- h.promise().data->emplace(std::nullopt);
- h.destroy();
- }
-};
-
-} // namespace nihil
-
-namespace std {
-
-export template <typename T>
-auto operator co_await(std::optional<T> o) {
- return nihil::optional_awaitable<T>{std::move(o)};
-}
-
-} // namespace std
-
-/**********************************************************************
- * std::expected
- */
-
-namespace nihil {
-
-export template <typename T, typename E>
-struct expected_promise_base {
- return_object_holder<std::expected<T, E>>* data;
-
- auto get_return_object()
- {
- return make_return_object_holder(data);
- }
-
- auto initial_suspend() noexcept -> std::suspend_never
- {
- return {};
- }
-
- auto final_suspend() noexcept -> std::suspend_never
- {
- return {};
- }
-
- void unhandled_exception()
- {
- std::rethrow_exception(std::current_exception());
- }
-};
-
-export template <typename T, typename E>
-struct expected_promise : expected_promise_base<T, E> {
- void return_value(this expected_promise &self, std::unexpected<E> err)
- {
- self.data->emplace(std::move(err));
- }
-
- void return_value(this expected_promise &self, T o)
- {
- self.data->emplace(std::move(o));
- }
-};
-
-export template <typename E>
-struct expected_promise<void, E> : expected_promise_base<void, E> {
- void return_value(this expected_promise &self, std::unexpected<E> err)
- {
- self.data->emplace(std::move(err));
- }
-
- void return_value(this expected_promise &self, std::expected<void, E> o)
- {
- self.data->emplace(std::move(o));
- }
-};
-
-} // namespace nihil
-
-export template <typename T, typename E, typename... Args>
-struct std::coroutine_traits<std::expected<T, E>, Args...> {
- using promise_type = nihil::expected_promise<T, E>;
-};
-
-namespace nihil {
-
-export template<typename T, typename E>
-struct expected_awaitable_base {
- std::expected<T, E> o;
-
- auto await_ready()
- {
- return o.has_value();
- }
-
- template <typename P>
- void await_suspend(std::coroutine_handle<P> h)
- {
- h.promise().data->emplace(std::unexpected(o.error()));
- h.destroy();
- }
-};
-
-export template <typename T, typename E>
-struct expected_awaitable : expected_awaitable_base<T, E> {
- auto await_resume(this expected_awaitable &self)
- {
- return std::move(*self.o);
- }
-};
-
-export template <typename E>
-struct expected_awaitable<void, E> : expected_awaitable_base<void, E> {
- auto await_resume(this expected_awaitable &)
- {
- return std::expected<void, E>();
- }
-};
-
-} // namespace nihil
-
-namespace std {
-
-export template <typename T, typename E>
-auto operator co_await(std::expected<T, E> o) {
- return nihil::expected_awaitable<T, E>{std::move(o)};
-}
-
-} // namespace std
diff --git a/nihil.monad/test.cc b/nihil.monad/test.cc
deleted file mode 100644
index 2cc743c..0000000
--- a/nihil.monad/test.cc
+++ /dev/null
@@ -1,64 +0,0 @@
-// This source code is released into the public domain.
-
-#include <catch2/catch_test_macros.hpp>
-
-import nihil.std;
-import nihil.error;
-import nihil.monad;
-
-TEST_CASE("monad: co_await std::optional<> with value", "[nihil]")
-{
- auto get_value = [] -> std::optional<int> {
- return 42;
- };
-
- auto try_get_value = [&get_value] -> std::optional<int> {
- co_return co_await get_value();
- };
-
- auto o = try_get_value();
- REQUIRE(o == 42);
-}
-
-TEST_CASE("monad: co_await std::optional<> without value", "[nihil]")
-{
- auto get_value = [] -> std::optional<int> {
- return {};
- };
-
- auto try_get_value = [&get_value] -> std::optional<int> {
- co_return co_await get_value();
- };
-
- auto o = try_get_value();
- REQUIRE(!o.has_value());
-}
-
-TEST_CASE("monad: co_await std::expected<> with value", "[nihil]")
-{
- auto get_value = [] -> std::expected<int, std::string> {
- return 42;
- };
-
- auto try_get_value = [&get_value] -> std::expected<int, std::string> {
- co_return co_await get_value();
- };
-
- auto o = try_get_value();
- REQUIRE(o == 42);
-}
-
-TEST_CASE("monad: co_await std::expected<> with error", "[nihil]")
-{
- auto get_value = [] -> std::expected<int, std::string> {
- return std::unexpected("error");
- };
-
- auto try_get_value = [&get_value] -> std::expected<int, std::string> {
- co_return co_await get_value();
- };
-
- auto o = try_get_value();
- REQUIRE(!o);
- REQUIRE(o.error() == "error");
-}