1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-06-26 10:29:31 +00:00

Ensures that reflection is completely blind; starts adding SDL instantiation logic.

This commit is contained in:
Thomas Harte 2020-03-12 20:56:02 -04:00
parent 06c08a0574
commit 52f644c4f1
14 changed files with 127 additions and 32 deletions

View File

@ -17,7 +17,7 @@ namespace Analyser {
namespace Static {
namespace Acorn {
struct Target: public ::Analyser::Static::Target, public Reflection::Struct<Target> {
struct Target: public ::Analyser::Static::Target, public Reflection::StructImpl<Target> {
bool has_adfs = false;
bool has_dfs = false;
bool should_shift_restart = false;

View File

@ -18,7 +18,7 @@ namespace Analyser {
namespace Static {
namespace AmstradCPC {
struct Target: public ::Analyser::Static::Target, public Reflection::Struct<Target> {
struct Target: public ::Analyser::Static::Target, public Reflection::StructImpl<Target> {
ReflectableEnum(Model, CPC464, CPC664, CPC6128);
Model model = Model::CPC464;
std::string loading_command;

View File

@ -17,7 +17,7 @@ namespace Analyser {
namespace Static {
namespace AppleII {
struct Target: public ::Analyser::Static::Target, public Reflection::Struct<Target> {
struct Target: public ::Analyser::Static::Target, public Reflection::StructImpl<Target> {
ReflectableEnum(Model,
II,
IIplus,

View File

@ -18,7 +18,7 @@ namespace Analyser {
namespace Static {
namespace Commodore {
struct Target: public ::Analyser::Static::Target, public Reflection::Struct<Target> {
struct Target: public ::Analyser::Static::Target, public Reflection::StructImpl<Target> {
enum class MemoryModel {
Unexpanded,
EightKB,

View File

@ -18,7 +18,7 @@ namespace Analyser {
namespace Static {
namespace MSX {
struct Target: public ::Analyser::Static::Target, public Reflection::Struct<Target> {
struct Target: public ::Analyser::Static::Target, public Reflection::StructImpl<Target> {
bool has_disk_drive = false;
std::string loading_command;

View File

@ -16,7 +16,7 @@ namespace Analyser {
namespace Static {
namespace Macintosh {
struct Target: public ::Analyser::Static::Target, public Reflection::Struct<Target> {
struct Target: public ::Analyser::Static::Target, public Reflection::StructImpl<Target> {
ReflectableEnum(Model, Mac128k, Mac512k, Mac512ke, MacPlus);
Model model = Model::MacPlus;

View File

@ -18,7 +18,7 @@ namespace Analyser {
namespace Static {
namespace Oric {
struct Target: public ::Analyser::Static::Target, public Reflection::Struct<Target> {
struct Target: public ::Analyser::Static::Target, public Reflection::StructImpl<Target> {
ReflectableEnum(ROM,
BASIC10,
BASIC11,

View File

@ -18,7 +18,7 @@ namespace Analyser {
namespace Static {
namespace ZX8081 {
struct Target: public ::Analyser::Static::Target, public Reflection::Struct<Target> {
struct Target: public ::Analyser::Static::Target, public Reflection::StructImpl<Target> {
ReflectableEnum(MemoryModel,
Unexpanded,
SixteenKB,

View File

@ -8,6 +8,7 @@
#include "MachineForTarget.hpp"
// Sources for runtime options.
#include "../AmstradCPC/AmstradCPC.hpp"
#include "../Apple/AppleII/AppleII.hpp"
#include "../Apple/Macintosh/Macintosh.hpp"
@ -21,6 +22,17 @@
#include "../Oric/Oric.hpp"
#include "../ZX8081/ZX8081.hpp"
// Sources for construction options.
#include "../../Analyser/Static/Acorn/Target.hpp"
#include "../../Analyser/Static/AmstradCPC/Target.hpp"
#include "../../Analyser/Static/AppleII/Target.hpp"
#include "../../Analyser/Static/AtariST/Target.hpp"
#include "../../Analyser/Static/Commodore/Target.hpp"
#include "../../Analyser/Static/Macintosh/Target.hpp"
#include "../../Analyser/Static/MSX/Target.hpp"
#include "../../Analyser/Static/Oric/Target.hpp"
#include "../../Analyser/Static/ZX8081/Target.hpp"
#include "../../Analyser/Dynamic/MultiMachine/MultiMachine.hpp"
#include "TypedDynamicMachine.hpp"
@ -155,3 +167,23 @@ std::map<std::string, std::vector<std::unique_ptr<Configurable::Option>>> Machin
return options;
}
std::map<std::string, std::unique_ptr<Reflection::Struct>> Machine::ConstructionOptionsByMachineName() {
std::map<std::string, std::unique_ptr<Reflection::Struct>> options;
#define Add(Name) \
options.emplace(std::make_pair(LongNameForTargetMachine(Analyser::Machine::Name), new Analyser::Static::Name::Target));
Add(AmstradCPC);
Add(AppleII);
// Add(AtariST);
// Add(Electron);
// options.emplace(std::make_pair(LongNameForTargetMachine(Analyser::Machine::Electron), Electron::get_options()));
// options.emplace(std::make_pair(LongNameForTargetMachine(Analyser::Machine::Macintosh), Apple::Macintosh::get_options()));
Add(MSX);
Add(Oric);
// options.emplace(std::make_pair(LongNameForTargetMachine(Analyser::Machine::Vic20), Commodore::Vic20::get_options()));
Add(ZX8081);
return options;
}

View File

@ -10,10 +10,12 @@
#define MachineForTarget_hpp
#include "../../Analyser/Static/StaticAnalyser.hpp"
#include "../../Reflection/Struct.h"
#include "../DynamicMachine.hpp"
#include <map>
#include <memory>
#include <string>
#include <vector>
@ -53,6 +55,8 @@ std::string LongNameForTargetMachine(const Analyser::Machine target);
*/
std::map<std::string, std::vector<std::unique_ptr<Configurable::Option>>> AllOptionsByMachineName();
std::map<std::string, std::unique_ptr<Reflection::Struct>> ConstructionOptionsByMachineName();
}
#endif /* MachineForTarget_hpp */

View File

@ -31,7 +31,7 @@
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Release"
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
enableThreadSanitizer = "YES"
@ -71,7 +71,7 @@
</CommandLineArgument>
<CommandLineArgument
argument = "&quot;/Users/thomasharte/Library/Mobile Documents/com~apple~CloudDocs/Desktop/Soft/Amstrad CPC/Amstrad CPC [TOSEC]/Amstrad CPC - Applications - [DSK] (TOSEC-v2011-08-31_CM)/Tasword (1984)(Tasman Software).dsk&quot;"
isEnabled = "YES">
isEnabled = "NO">
</CommandLineArgument>
<CommandLineArgument
argument = "&quot;/Users/thomasharte/Library/Mobile Documents/com~apple~CloudDocs/Desktop/Soft/Amstrad CPC/Robocop.dsk&quot;"
@ -83,6 +83,10 @@
</CommandLineArgument>
<CommandLineArgument
argument = "--rompath=/Users/thomasharte/Projects/CLK/ROMImages"
isEnabled = "NO">
</CommandLineArgument>
<CommandLineArgument
argument = "--help"
isEnabled = "YES">
</CommandLineArgument>
</CommandLineArguments>

View File

@ -34,6 +34,9 @@
#include "../../Outputs/OpenGL/ScanTarget.hpp"
#include "../../Outputs/OpenGL/Screenshot.hpp"
#include "../../Reflection/Enum.h"
#include "../../Reflection/Struct.h"
namespace {
struct MachineRunner {
@ -478,7 +481,7 @@ int main(int argc, char *argv[]) {
std::cout << "Use alt+enter to toggle full screen display. Use control+shift+V to paste text." << std::endl;
std::cout << "Required machine type and configuration is determined from the file. Machines with further options:" << std::endl << std::endl;
auto all_options = Machine::AllOptionsByMachineName();
const auto all_options = Machine::AllOptionsByMachineName();
for(const auto &machine_options: all_options) {
std::cout << machine_options.first << ":" << std::endl;
for(const auto &option: machine_options.second) {
@ -499,6 +502,32 @@ int main(int argc, char *argv[]) {
}
std::cout << std::endl;
}
const auto construction_options = Machine::ConstructionOptionsByMachineName();
for(const auto &options: construction_options) {
std::cout << options.first << ":" << std::endl;
for(const auto &option: options.second->all_keys()) {
std::cout << '\t' << "--" << option;
const auto type = options.second->type_of(option);
// Is this a registered enum? If so, list options.
if(!Reflection::Enum::name(*type).empty()) {
std::cout << "={";
bool is_first = true;
for(const auto &value: Reflection::Enum::all_values(*type)) {
if(!is_first) std::cout << '|';
is_first = false;
std::cout << value;
}
std::cout << "}";
}
// TODO: if not a registered enum... then assume it was a Boolean?
std::cout << std::endl;
}
std::cout << std::endl;
}
return EXIT_SUCCESS;
}

View File

@ -72,19 +72,20 @@ class Enum {
}
members_by_type_.emplace(std::make_pair(&typeid(Type), result));
names_by_type_.emplace(std::make_pair(&typeid(Type), std::string(name)));
}
/*!
@returns the declared name of the enum @c Type if it has been registered; the empty string otherwise.
*/
template <typename Type> const std::string &name() {
template <typename Type> static const std::string &name() {
return name(typeid(Type));
}
/*!
@returns the declared name of the enum with type_info @c type if it has been registered; the empty string otherwise.
*/
const std::string &name(const std::type_info &type) {
static const std::string &name(const std::type_info &type) {
const auto entry = names_by_type_.find(&type);
if(entry == names_by_type_.end()) return empty_string_;
return entry->second;
@ -93,14 +94,14 @@ class Enum {
/*!
@returns the number of members of the enum @c Type if it has been registered; 0 otherwise.
*/
template <typename Type> size_t size() {
template <typename Type> static size_t size() {
return size(typeid(Type));
}
/*!
@returns the number of members of the enum with type_info @c type if it has been registered; @c std::string::npos otherwise.
*/
size_t size(const std::type_info &type) {
static size_t size(const std::type_info &type) {
const auto entry = members_by_type_.find(&type);
if(entry == members_by_type_.end()) return std::string::npos;
return entry->second.size();
@ -109,32 +110,48 @@ class Enum {
/*!
@returns A @c std::string name for the enum value @c e.
*/
template <typename Type> static const std::string &toString(Type e) {
return toString(typeid(Type), size_t(e));
template <typename Type> static const std::string &to_string(Type e) {
return to_string(typeid(Type), size_t(e));
}
/*!
@returns A @c std::string name for the enum value @c e from the enum with type_info @c type.
*/
static const std::string &toString(const std::type_info &type, size_t e) {
static const std::string &to_string(const std::type_info &type, size_t e) {
const auto entry = members_by_type_.find(&type);
if(entry == members_by_type_.end()) return empty_string_;
return entry->second[e];
}
/*!
@returns a vector naming the members of the enum with type_info @c type if it has been registered; an empty vector otherwise.
*/
static const std::vector<std::string> &all_values(const std::type_info &type) {
const auto entry = members_by_type_.find(&type);
if(entry == members_by_type_.end()) return empty_vector_;
return entry->second;
}
/*!
@returns a vector naming the members of the enum @c Type type if it has been registered; an empty vector otherwise.
*/
template <typename Type> static const std::vector<std::string> &all_values() {
return all_values(typeid(Type));
}
/*!
@returns A value of @c Type for the name @c str, or @c EnumType(std::string::npos) if
the name is not found.
*/
template <typename Type> Type fromString(const std::string &str) {
return Type(fromString(typeid(Type), str));
template <typename Type> static Type from_string(const std::string &str) {
return Type(from_string(typeid(Type), str));
}
/*!
@returns A value for the name @c str in the enum with type_info @c type , or @c std::string::npos if
the name is not found.
*/
size_t fromString(const std::type_info &type, const std::string &str) {
static size_t from_string(const std::type_info &type, const std::string &str) {
const auto entry = members_by_type_.find(&type);
if(entry == members_by_type_.end()) return std::string::npos;
const auto iterator = std::find(entry->second.begin(), entry->second.end(), str);
@ -146,6 +163,7 @@ class Enum {
static inline std::unordered_map<const std::type_info *, std::vector<std::string>> members_by_type_;
static inline std::unordered_map<const std::type_info *, std::string> names_by_type_;
static inline const std::string empty_string_;
static inline const std::vector<std::string> empty_vector_;
};
}

View File

@ -19,16 +19,24 @@ namespace Reflection {
#define DeclareField(Name) declare(&Name, #Name)
template <typename Owner> class Struct {
struct Struct {
virtual std::vector<std::string> all_keys() = 0;
virtual const std::type_info *type_of(const std::string &name) = 0;
virtual void set(const std::string &name, const void *value) = 0;
virtual const void *get(const std::string &name) = 0;
virtual ~Struct() {}
};
template <typename Owner> class StructImpl: public Struct {
public:
/*!
@returns the value of type @c Type that is loaded from the offset registered for the field @c name.
It is the caller's responsibility to provide an appropriate type of data.
*/
template <typename Type> const Type *get(const std::string &name) {
const void *get(const std::string &name) final {
const auto iterator = contents_.find(name);
if(iterator == contents_.end()) return nullptr;
return reinterpret_cast<Type *>(reinterpret_cast<uint8_t *>(this) + iterator->second.offset);
return reinterpret_cast<uint8_t *>(this) + iterator->second.offset;
}
/*!
@ -36,16 +44,16 @@ template <typename Owner> class Struct {
It is the caller's responsibility to provide an appropriate type of data.
*/
template <typename Type> void set(const std::string &name, const Type &value) {
void set(const std::string &name, const void *value) final {
const auto iterator = contents_.find(name);
if(iterator == contents_.end()) return;
*reinterpret_cast<Type *>(reinterpret_cast<uint8_t *>(this) + iterator->second.offset) = value;
memcpy(reinterpret_cast<uint8_t *>(this) + iterator->second.offset, value, iterator->second.size);
}
/*!
@returns @c type_info for the field @c name.
*/
const std::type_info *type_of(const std::string &name) {
const std::type_info *type_of(const std::string &name) final {
const auto iterator = contents_.find(name);
if(iterator == contents_.end()) return nullptr;
return iterator->second.type;
@ -54,7 +62,7 @@ template <typename Owner> class Struct {
/*!
@returns A vector of all declared fields for this struct.
*/
std::vector<std::string> all_keys() {
std::vector<std::string> all_keys() final {
std::vector<std::string> keys;
for(const auto &pair: contents_) {
keys.push_back(pair.first);
@ -82,7 +90,7 @@ template <typename Owner> class Struct {
contents_.emplace(
std::make_pair(
name,
Field(typeid(Type), reinterpret_cast<uint8_t *>(t) - reinterpret_cast<uint8_t *>(this))
Field(typeid(Type), reinterpret_cast<uint8_t *>(t) - reinterpret_cast<uint8_t *>(this), sizeof(Type))
));
}
@ -96,9 +104,9 @@ template <typename Owner> class Struct {
private:
struct Field {
const std::type_info *type;
ssize_t offset;
Field(const std::type_info &type, ssize_t offset) :
type(&type), offset(offset) {}
ssize_t offset, size;
Field(const std::type_info &type, ssize_t offset, size_t size) :
type(&type), offset(offset), size(size) {}
};
static inline std::unordered_map<std::string, Field> contents_;
};