From 7bf04d5338d18e0a5397238c6470ecd9a09e9333 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Mon, 17 Feb 2020 18:08:46 -0500 Subject: [PATCH] Adds a prototype reflective enum. I need to make this scopeable before it is acceptable. --- Analyser/Static/Macintosh/Target.hpp | 14 ++-- .../Clock Signal.xcodeproj/project.pbxproj | 2 + Reflection/Enum.h | 80 +++++++++++++++++++ 3 files changed, 88 insertions(+), 8 deletions(-) create mode 100644 Reflection/Enum.h diff --git a/Analyser/Static/Macintosh/Target.hpp b/Analyser/Static/Macintosh/Target.hpp index 5d70748f0..d1bb2d5be 100644 --- a/Analyser/Static/Macintosh/Target.hpp +++ b/Analyser/Static/Macintosh/Target.hpp @@ -9,19 +9,17 @@ #ifndef Analyser_Static_Macintosh_Target_h #define Analyser_Static_Macintosh_Target_h +#include "../../../Reflection/Enum.h" + +ReflectiveEnum(MacintoshModel, int, Mac128k, Mac512k, Mac128ke, MacPlus); + namespace Analyser { namespace Static { namespace Macintosh { -struct Target: public ::Analyser::Static::Target { - enum class Model { - Mac128k, - Mac512k, - Mac512ke, - MacPlus - }; - Model model = Model::MacPlus; +struct Target: public ::Analyser::Static::Target { + MacintoshModel model = MacintoshModel::MacPlus; }; } diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index ed74f9c91..3f246ad8d 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -1138,6 +1138,7 @@ 4B643F3C1D77AE5C00D431D6 /* CSMachine+Target.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "CSMachine+Target.h"; sourceTree = ""; }; 4B643F3E1D77B88000D431D6 /* DocumentController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DocumentController.swift; sourceTree = ""; }; 4B644ED023F0FB55006C0CC5 /* ScanSynchroniser.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ScanSynchroniser.hpp; sourceTree = ""; }; + 4B644ED123FAF162006C0CC5 /* Enum.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Enum.h; path = ../../Reflection/Enum.h; sourceTree = ""; }; 4B65085F22F4CF8D009C1100 /* Keyboard.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Keyboard.cpp; sourceTree = ""; }; 4B670A832401CB8400D4E002 /* z80memptr.tap */ = {isa = PBXFileReference; lastKnownFileType = file; path = z80memptr.tap; sourceTree = ""; }; 4B670A852401CB8400D4E002 /* z80ccf.tap */ = {isa = PBXFileReference; lastKnownFileType = file; path = z80ccf.tap; sourceTree = ""; }; @@ -3246,6 +3247,7 @@ 4BB73E951B587A5100552FC2 = { isa = PBXGroup; children = ( + 4B644ED123FAF162006C0CC5 /* Enum.h */, 4BC76E6A1C98F43700E6EF73 /* Accelerate.framework */, 4B51F70820A521D700AFA2C1 /* Activity */, 4B8944E2201967B4007DE474 /* Analyser */, diff --git a/Reflection/Enum.h b/Reflection/Enum.h new file mode 100644 index 000000000..0b7c329c9 --- /dev/null +++ b/Reflection/Enum.h @@ -0,0 +1,80 @@ +// +// Enum.h +// Clock Signal +// +// Created by Thomas Harte on 17/02/2020. +// Copyright © 2020 Thomas Harte. All rights reserved. +// + +#ifndef Enum_h +#define Enum_h + +#include + +namespace Reflection { + +template struct Enum { + static size_t size() { + return members().size(); + } + + /*! + @returns A @c string_view name for the enum value @c e. + */ + static std::string_view toString(EnumType e) { + return members()[size_t(e)]; + } + + /*! + @returns A value of @c EnumType name for the name @c str, or @c EnumType(-1) if + the string is not found. + */ + static EnumType fromString(const std::string_view &str) { + const auto member_list = members(); + auto position = std::find(member_list.begin(), member_list.end(), str); + if(position == member_list.end()) return EnumType(-1); + return EnumType(position - member_list.begin()); + } + + /*! + @returns A vector of string_views naming the members of this enum in value order. + */ + static std::vector members() { + Enum m; + const char *const declaration = m.declaration(); + const char *d_ptr = declaration; + + std::vector result; + while(true) { + // Skip non-alphas, and exit if the terminator is found. + while(*d_ptr && !isalpha(*d_ptr)) ++d_ptr; + if(!*d_ptr) break; + + // Note the current location and proceed for all alphas and digits. + const auto start = d_ptr; + while(isalpha(*d_ptr) || isdigit(*d_ptr)) ++d_ptr; + + // Add a string view. + result.emplace_back(start, d_ptr - start); + } + + return result; + } + + private: + constexpr const char *declaration(); + +}; + +} + +/*! + Provides a very limited subset of normal enums, with the addition of reflection. + + Enum members must take default values, and this enum must be in the global scope. +*/ +#define ReflectiveEnum(Name, Type, ...) \ + enum class Name: Type { __VA_ARGS__ }; \ + template <> constexpr const char *::Reflection::Enum::declaration() { return #__VA_ARGS__; }; + +#endif /* Enum_h */