Experimentation with C++17 compatibilty. Mainly an exercise in rewrting coroutine code in boost::coroutine2. Interesting!

This commit is contained in:
Adrian Conlon 2022-01-01 13:20:34 +00:00
parent fbdf2fcf02
commit bb75f98d5d
12 changed files with 120 additions and 5 deletions

View File

@ -168,7 +168,7 @@ void Game::removeJoystick(SDL_Event& e) {
const auto which = e.jdevice.which;
const auto found = m_gameControllers.find(which);
SDL_assert(found != m_gameControllers.end());
auto controller = found->second;
auto& controller = found->second;
const auto joystickId = controller->getJoystickId();
m_mappedControllers.erase(joystickId);
m_gameControllers.erase(which);
@ -181,7 +181,11 @@ void Game::addJoystick(SDL_Event& e) {
auto controller = std::make_shared<GameController>(which);
const auto joystickId = controller->getJoystickId();
m_gameControllers[which] = controller;
#if __cplusplus >= 202002L
SDL_assert(m_mappedControllers.contains(joystickId));
#else
SDL_assert(m_mappedControllers.find(joystickId) != m_mappedControllers.end());
#endif
m_mappedControllers[joystickId] = which;
SDL_Log("Joystick device %d added (%zd controllers)", which, m_gameControllers.size());
}

View File

@ -210,7 +210,11 @@ void checker_t::check(test_t current) {
const auto pc = cpu.PC().word;
const auto start_opcode = runner().peek(pc);
#if __cplusplus >= 202002L
m_undocumented = m_undocumented_opcodes.contains(start_opcode);
#else
m_undocumented = m_undocumented_opcodes.find(start_opcode) != m_undocumented_opcodes.end();
#endif
if (undocumented()) {
m_valid = false;
m_messages.push_back("Undocumented");

View File

@ -4,7 +4,14 @@
opcode_test_suite_t::opcode_test_suite_t(const std::string path) noexcept
: parser_t(path) {}
#if __cplusplus >= 202002L
EightBit::co_generator_t<test_t> opcode_test_suite_t::generator() {
for (const auto element : *this)
co_yield test_t(element);
}
#else
void opcode_test_suite_t::generator(boost::coroutines2::coroutine<test_t>::push_type& sink) {
for (const auto element : *this)
sink(test_t(element));
}
#endif

View File

@ -2,7 +2,11 @@
#include <string>
#include <co_generator_t.h>
#if __cplusplus >= 202002L
# include <co_generator_t.h>
#else
# include <boost/coroutine2/all.hpp>
#endif
#include "parser_t.h"
#include "test_t.h"
@ -18,5 +22,9 @@ public:
[[nodiscard]] auto begin() const noexcept { return array().begin(); }
[[nodiscard]] auto end() const noexcept { return array().end(); }
#if __cplusplus >= 202002L
[[nodiscard]] EightBit::co_generator_t<test_t> generator();
#else
void generator(boost::coroutines2::coroutine<test_t>::push_type& sink);
#endif
};

View File

@ -19,7 +19,11 @@ public:
parser_t() noexcept {}
parser_t(std::string path) noexcept;
#if __cplusplus >= 202002L
[[nodiscard]] constexpr std::string_view path() const noexcept { return m_path; }
#else
[[nodiscard]] std::string_view path() const noexcept { return m_path; }
#endif
[[nodiscard]] const auto raw() const noexcept { return m_raw; }
virtual void load();

View File

@ -7,8 +7,16 @@ processor_test_suite_t::processor_test_suite_t(std::string location) noexcept
: m_location(location) {
}
#if __cplusplus >= 202002L
EightBit::co_generator_t<opcode_test_suite_t> processor_test_suite_t::generator() {
std::filesystem::path directory = location();
for (const auto& entry : std::filesystem::directory_iterator{ directory })
co_yield opcode_test_suite_t(entry.path().string());
}
#else
void processor_test_suite_t::generator(boost::coroutines2::coroutine<opcode_test_suite_t>::push_type& sink) {
std::filesystem::path directory = location();
for (const auto& entry : std::filesystem::directory_iterator{ directory })
sink(opcode_test_suite_t(entry.path().string()));
}
#endif

View File

@ -3,7 +3,11 @@
#include <string>
#include <string_view>
#include <co_generator_t.h>
#if __cplusplus >= 202002L
# include <co_generator_t.h>
#else
# include <boost/coroutine2/all.hpp>
#endif
#include "opcode_test_suite_t.h"
@ -16,5 +20,9 @@ public:
std::string_view location() const noexcept { return m_location; }
#if __cplusplus >= 202002L
[[nodiscard]] EightBit::co_generator_t<opcode_test_suite_t> generator();
#else
void generator(boost::coroutines2::coroutine<opcode_test_suite_t>::push_type& sink);
#endif
};

View File

@ -21,6 +21,12 @@
#include <mos6502.h>
#include <Disassembly.h>
#include <Symbols.h>
#include <co_generator_t.h>
#if __cplusplus >= 202002L
# include <co_generator_t.h>
#else
# include <boost/coroutine2/all.hpp>
# include <boost/bind.hpp>
#endif
#include "simdjson/simdjson.h"

View File

@ -4,6 +4,10 @@
#include <iostream>
#include <filesystem>
#if __cplusplus < 202002L
# include <boost/bind.hpp>
#endif
#include "TestRunner.h"
#include "checker_t.h"
#include "test_t.h"
@ -26,6 +30,8 @@ int main() {
checker_t checker(runner);
checker.initialise();
#if __cplusplus >= 202002L
processor_test_suite_t m6502_tests(directory);
auto opcode_generator = m6502_tests.generator();
while (opcode_generator) {
@ -56,6 +62,37 @@ int main() {
}
}
#else
processor_test_suite_t m6502_tests(directory);
boost::coroutines2::coroutine<opcode_test_suite_t>::pull_type opcodes(boost::bind(&processor_test_suite_t::generator, &m6502_tests, _1));
for (auto& opcode : opcodes) {
const auto path = std::filesystem::path(opcode.path());
std::cout << "Processing: " << path.filename() << "\n";
opcode.load();
boost::coroutines2::coroutine<test_t>::pull_type tests(boost::bind(&opcode_test_suite_t::generator, &opcode, _1));
for (auto& test : tests) {
checker.check(test);
if (checker.invalid()) {
++invalid_opcode_count;
if (checker.unimplemented())
++unimplemented_opcode_count;
if (checker.undocumented())
++undocumented_opcode_count;
std::cout << "** Failed: " << test.name() << "\n";
for (const auto& message : checker.messages())
std::cout << "**** " << message << "\n";
break;
}
}
}
#endif
const auto finish_time = std::chrono::steady_clock::now();
const auto elapsed_time = finish_time - start_time;
const auto seconds = std::chrono::duration_cast<std::chrono::duration<double>>(elapsed_time).count();

View File

@ -27,6 +27,8 @@ namespace EightBit {
[[nodiscard]] constexpr const auto& instructions() const { return m_instructions; }
[[nodiscard]] constexpr const auto& addresses() const { return m_addresses; }
#if __cplusplus >= 202002L
[[nodiscard]] constexpr auto instructions_available() const noexcept {
const auto found = std::find_if(
instructions().begin(), instructions().end(),
@ -45,6 +47,28 @@ namespace EightBit {
return instructions_available() || addresses_available();
}
#else
[[nodiscard]] auto instructions_available() const noexcept {
const auto found = std::find_if(
instructions().begin(), instructions().end(),
[](const auto& value) { return value != 0; });
return found != instructions().end();
}
[[nodiscard]] auto addresses_available() const noexcept {
const auto found = std::find_if(
addresses().begin(), addresses().end(),
[](const auto& value) { return value != 0; });
return found != addresses().end();
}
[[nodiscard]] auto available() const noexcept {
return instructions_available() || addresses_available();
}
#endif
void dumpInstructionProfiles() const;
void dumpAddressProfiles() const;
};

View File

@ -74,9 +74,15 @@ namespace EightBit {
return lhs.word == rhs.word;
}
#if __cplusplus >= 202002L
[[nodiscard]] constexpr auto operator<=>(const register16_t lhs, const register16_t rhs) noexcept {
return lhs.word <=> rhs.word;
}
#else
[[nodiscard]] constexpr inline auto operator!=(const register16_t lhs, const register16_t rhs) noexcept {
return lhs.word != rhs.word;
}
#endif
[[nodiscard]] constexpr inline auto operator+(register16_t lhs, const register16_t rhs) noexcept {
lhs += rhs;

View File

@ -3,7 +3,6 @@
#endif
#include <cassert>
#include <coroutine>
#include <cstdint>
#include <functional>
#include <stdexcept>