summaryrefslogtreecommitdiff
path: root/aisa
diff options
context:
space:
mode:
Diffstat (limited to 'aisa')
-rw-r--r--aisa/aisa.cpp5
-rw-r--r--aisa/aisa.h73
-rw-r--r--aisa/coroutine.h120
3 files changed, 192 insertions, 6 deletions
diff --git a/aisa/aisa.cpp b/aisa/aisa.cpp
index 0c806de..97a3b17 100644
--- a/aisa/aisa.cpp
+++ b/aisa/aisa.cpp
@@ -4,9 +4,4 @@
4 4
5namespace aisa { 5namespace aisa {
6 6
7 void do_something()
8 {
9 std::cout << "Hello, world!\n";
10 }
11
12} 7}
diff --git a/aisa/aisa.h b/aisa/aisa.h
index b570d6b..8cb302e 100644
--- a/aisa/aisa.h
+++ b/aisa/aisa.h
@@ -1,7 +1,78 @@
1#pragma once 1#pragma once
2 2
3#include <coroutine>
4#include <cstdint>
5#include <iostream>
6#include <optional>
7#include <utility>
8#include <vector>
9
10#include "aisa/coroutine.h"
11
3namespace aisa { 12namespace aisa {
4 13
5 void do_something(); 14 using regnum_t = std::uint_fast64_t;
15 using regval_t = std::uint64_t;
16
17 template<typename CRTP> struct EvalState {
18 CRTP & crtp() noexcept { return static_cast<CRTP &>(*this); }
19 task<regval_t> async_load_reg(regnum_t rn)
20 {
21 while (true) {
22 if (auto rv = crtp().load_reg(rn); rv.has_value())
23 co_return *rv;
24 co_await suspend();
25 }
26 }
27 };
28
29 struct Step {
30 const std::optional<std::pair<regnum_t, regval_t>> predicate;
31 const std::vector<regnum_t> source_regs;
32 const std::vector<regnum_t> destination_regs;
33
34 std::optional<regnum_t> predicate_reg() const
35 {
36 if (predicate.has_value())
37 return predicate->first;
38 return {};
39 }
40
41 std::optional<regnum_t> expected_predicate_val() const
42 {
43 if (predicate.has_value())
44 return predicate->second;
45 return {};
46 }
47
48 template<typename State> task<void> evaluate(State &state) const
49 {
50 if (predicate.has_value()) {
51 std::cout << "checking predicate...\n";
52 std::cout << "\texpect " << predicate->second << "\n";
53 regval_t pval = co_await state.async_load_reg(predicate->first);
54 std::cout << "\tgot " << pval << "\n";
55 if (pval != predicate->second) {
56 std::cout << "\tpredicate skipped\n";
57 co_return;
58 } else {
59 std::cout << "\tpredicate not skipped\n";
60 }
61 }
62 std::cout << "reading sources...\n";
63 std::vector<regval_t> source_vals;
64 source_vals.reserve(source_regs.size());
65 for (unsigned int i = 0; i < source_regs.size(); ++i) {
66 std::cout << "\tgetting source " << i << "...\n";
67 source_vals.emplace_back(co_await state.async_load_reg(source_regs[i]));
68 std::cout << "\t\tgot " << source_vals.back() << "\n";
69 }
70 std::cout << "sources:";
71 for (unsigned int i = 0; i < source_regs.size(); ++i)
72 std::cout << " " << source_regs[i] << "=" << source_vals[i];
73 std::cout << "\n";
74 std::cout << "done with evaluate\n";
75 }
76 };
6 77
7} 78}
diff --git a/aisa/coroutine.h b/aisa/coroutine.h
new file mode 100644
index 0000000..40a6982
--- /dev/null
+++ b/aisa/coroutine.h
@@ -0,0 +1,120 @@
1#pragma once
2
3#include <coroutine>
4
5namespace aisa {
6
7 inline auto suspend() noexcept { return std::suspend_always{}; }
8
9 template<typename result_t> struct promise;
10
11 template<typename result_t> struct task : public std::coroutine_handle<promise<result_t>> {
12 using handle = std::coroutine_handle<struct promise<result_t>>;
13 using promise_type = struct promise<result_t>;
14 bool await_ready() const noexcept { return handle::done(); }
15 result_t await_resume() const noexcept;
16 template<typename other_t> void await_suspend(std::coroutine_handle<struct promise<other_t>> h) const noexcept;
17 std::optional<result_t> operator()() noexcept;
18 };
19
20 template<> struct task<void> : public std::coroutine_handle<promise<void>> {
21 using handle = std::coroutine_handle<struct promise<void>>;
22 using promise_type = struct promise<void>;
23 bool await_ready() const noexcept { return handle::done(); }
24 void await_resume() const noexcept;
25 template<typename other_t> void await_suspend(std::coroutine_handle<struct promise<other_t>> h) const noexcept;
26 bool operator()() noexcept;
27 };
28
29 template<typename result_t> struct promise {
30 std::coroutine_handle<> precursor;
31 std::optional<result_t> result;
32 promise() = default;
33 promise(const promise &) = delete;
34 task<result_t> get_return_object() noexcept { return task<result_t>{std::coroutine_handle<promise<result_t>>::from_promise(*this)}; }
35 std::suspend_never initial_suspend() const noexcept { return {}; }
36 std::suspend_always final_suspend() const noexcept { return {}; }
37 void unhandled_exception() { }
38 void return_value(result_t x) noexcept { result = std::move(x); }
39 };
40
41 template<> struct promise<void> {
42 std::coroutine_handle<> precursor;
43 promise() = default;
44 promise(const promise &) = delete;
45 task<void> get_return_object() noexcept { return task<void>{std::coroutine_handle<promise<void>>::from_promise(*this)}; }
46 std::suspend_never initial_suspend() const noexcept { return {}; }
47 std::suspend_always final_suspend() const noexcept { return {}; }
48 void unhandled_exception() { }
49 void return_void() noexcept { }
50 };
51
52 template<typename result_t> result_t task<result_t>::await_resume() const noexcept
53 {
54 auto x = std::move(handle::promise().result.value());
55 handle::destroy();
56 return std::move(x);
57 }
58
59 template<typename result_t> template<typename other_t> void task<result_t>::await_suspend(std::coroutine_handle<struct promise<other_t>> h) const noexcept
60 {
61 h.promise().precursor = *this;
62 }
63
64 template<typename result_t> std::optional<result_t> task<result_t>::operator()() noexcept
65 {
66 if (!handle::operator bool())
67 return {};
68 if (!handle::done()) {
69 auto &precursor = handle::promise().precursor;
70 if (precursor) {
71 if (!precursor.done())
72 precursor.resume();
73 if (precursor.done())
74 precursor = nullptr;
75 }
76 if (!precursor)
77 handle::resume();
78 }
79 if (handle::done()) {
80 auto x = await_resume();
81 handle::operator=(nullptr);
82 return std::move(x);
83 }
84 return {};
85 }
86
87 inline void task<void>::await_resume() const noexcept
88 {
89 handle::destroy();
90 }
91
92 template<typename other_t> void task<void>::await_suspend(std::coroutine_handle<struct promise<other_t>> h) const noexcept
93 {
94 h.promise().precursor = *this;
95 }
96
97 inline bool task<void>::operator()() noexcept
98 {
99 if (!handle::operator bool())
100 return true;
101 if (!handle::done()) {
102 auto &precursor = handle::promise().precursor;
103 if (precursor) {
104 if (!precursor.done())
105 precursor.resume();
106 if (precursor.done())
107 precursor = nullptr;
108 }
109 if (!precursor)
110 handle::resume();
111 }
112 if (handle::done()) {
113 await_resume();
114 handle::operator=(nullptr);
115 return true;
116 }
117 return false;
118 }
119
120}