diff options
Diffstat (limited to 'src/openvic-simulation/vm')
-rw-r--r-- | src/openvic-simulation/vm/AsmBuilder.hpp | 87 | ||||
-rw-r--r-- | src/openvic-simulation/vm/Codegen.cpp | 82 | ||||
-rw-r--r-- | src/openvic-simulation/vm/Codegen.hpp | 142 | ||||
-rw-r--r-- | src/openvic-simulation/vm/Module.hpp | 49 | ||||
-rw-r--r-- | src/openvic-simulation/vm/Reader.hpp | 45 | ||||
-rw-r--r-- | src/openvic-simulation/vm/RuntimeFiber.hpp | 46 | ||||
-rw-r--r-- | src/openvic-simulation/vm/RuntimeProcess.hpp | 37 | ||||
-rw-r--r-- | src/openvic-simulation/vm/Stacktrace.hpp | 51 | ||||
-rw-r--r-- | src/openvic-simulation/vm/Utility.hpp | 72 | ||||
-rw-r--r-- | src/openvic-simulation/vm/VirtualMachine.hpp | 39 | ||||
-rw-r--r-- | src/openvic-simulation/vm/Writer.hpp | 44 |
11 files changed, 391 insertions, 303 deletions
diff --git a/src/openvic-simulation/vm/AsmBuilder.hpp b/src/openvic-simulation/vm/AsmBuilder.hpp index 31fe0aa..38fa195 100644 --- a/src/openvic-simulation/vm/AsmBuilder.hpp +++ b/src/openvic-simulation/vm/AsmBuilder.hpp @@ -1,91 +1,22 @@ #pragma once +#include "Utility.hpp" #include <lauf/asm/builder.h> #include <lauf/asm/module.h> namespace OpenVic::Vm { - struct AsmBuilder { - AsmBuilder(lauf_asm_build_options options) : _handle(lauf_asm_create_builder(options)) {} + struct AsmBuilder : utility::MoveOnlyHandleBase<AsmBuilder, lauf_asm_builder> { + using MoveOnlyHandleBase::MoveOnlyHandleBase; + using MoveOnlyHandleBase::operator=; - AsmBuilder(AsmBuilder&&) = default; - AsmBuilder& operator=(AsmBuilder&&) = default; - - AsmBuilder(AsmBuilder const&) = delete; - AsmBuilder& operator=(AsmBuilder const&) = delete; + AsmBuilder(lauf_asm_build_options options) : MoveOnlyHandleBase(lauf_asm_create_builder(options)) {} ~AsmBuilder() { - lauf_asm_destroy_builder(_handle); - } - - lauf_asm_builder* handle() { - return _handle; - } - - const lauf_asm_builder* handle() const { - return _handle; - } - - operator lauf_asm_builder*() { - return _handle; - } - - operator const lauf_asm_builder*() const { - return _handle; - } - - struct CodeBuilder { - CodeBuilder(CodeBuilder const&) = delete; - CodeBuilder& operator=(CodeBuilder const&) = delete; - - ~CodeBuilder() { - if (!has_finished()) { - finish(); - } - } - - operator lauf_asm_builder*() { - return _builder.handle(); - } - - operator const lauf_asm_builder*() const { - return _builder.handle(); - } - - bool finish() { - return _has_finished = lauf_asm_build_finish(_builder.handle()); - } - - bool has_finished() const { - return _has_finished; - } - - bool is_well_formed() const { - return _is_well_formed; + if (_handle == nullptr) { + return; } - - void build_function(lauf_asm_function* fn) { - lauf_asm_build(_builder.handle(), _module, fn); - } - - void build_chunk(lauf_asm_chunk* chunk, lauf_asm_signature sig) { - lauf_asm_build_chunk(_builder.handle(), _module, chunk, sig); - } - - private: - friend struct AsmBuilder; - CodeBuilder(AsmBuilder& builder, lauf_asm_module* module) : _builder(builder), _module(module) {} - - bool _has_finished; - bool _is_well_formed; - AsmBuilder& _builder; - lauf_asm_module* _module; - }; - - CodeBuilder code(lauf_asm_module* module) { - return CodeBuilder(*this, module); + lauf_asm_destroy_builder(*this); + _handle = nullptr; } - - private: - lauf_asm_builder* _handle; }; } diff --git a/src/openvic-simulation/vm/Codegen.cpp b/src/openvic-simulation/vm/Codegen.cpp new file mode 100644 index 0000000..b84078e --- /dev/null +++ b/src/openvic-simulation/vm/Codegen.cpp @@ -0,0 +1,82 @@ +#include "Codegen.hpp" + +#include <cctype> +#include <string_view> + +#include <openvic-dataloader/v2script/AbstractSyntaxTree.hpp> + +#include <dryad/node.hpp> +#include <dryad/tree.hpp> + +#include <range/v3/algorithm/equal.hpp> + +#include "tsl/ordered_map.h" +#include <lauf/asm/builder.h> + +using namespace OpenVic::Vm; +using namespace ovdl::v2script::ast; +using namespace ovdl::v2script; + +using namespace std::string_view_literals; + +bool ichar_equals(char a, char b) { + return std::tolower(static_cast<unsigned char>(a)) == std::tolower(static_cast<unsigned char>(b)); +} + +void Codegen::generate_effect_from(Parser const& parser, Node* node) { + bool is_prepping_args = false; + tsl::ordered_map<std::string_view, std::string_view> prepped_arguments; + + dryad::visit_tree( + node, // + [&](dryad::child_visitor<NodeKind> visitor, AssignStatement* statement) { + auto const* left = dryad::node_try_cast<FlatValue>(statement->left()); + if (!left) { + return; + } + + auto const* right = dryad::node_try_cast<FlatValue>(statement->right()); + if (!right) { + is_prepping_args = true; // TODO: determine if scope or list-arg effect + visitor(right); + } else if (ranges::equal(right->value().view(), "yes"sv, ichar_equals)) { + // TODO: insert vic2 bytecode scope object address here + // TODO: calls a builtin for Victoria 2 effects? + } else if (!ranges::equal(right->value().view(), "no"sv, ichar_equals)) { + // TODO: single argument execution + } + }, + [&](FlatValue* value) { + // TODO: handle right side + } + ); +} + +void Codegen::generate_condition_from(Parser const& parser, Node* node) { + bool is_prepping_args = false; + tsl::ordered_map<std::string_view, std::string_view> prepped_arguments; + + dryad::visit_tree( + node, // + [&](dryad::child_visitor<NodeKind> visitor, AssignStatement* statement) { + auto const* left = dryad::node_try_cast<FlatValue>(statement->left()); + if (!left) { + return; + } + + auto const* right = dryad::node_try_cast<FlatValue>(statement->right()); + if (!right) { + is_prepping_args = true; // TODO: determine if scope or list-arg effect + visitor(right); + } else if (ranges::equal(right->value().view(), "yes"sv, ichar_equals)) { + // TODO: insert vic2 bytecode scope object address here + // TODO: calls a builtin for Victoria 2 triggers? + } else if (!ranges::equal(right->value().view(), "no"sv, ichar_equals)) { + // TODO: single argument execution + } + }, + [&](FlatValue* value) { + // TODO: handle right side + } + ); +} diff --git a/src/openvic-simulation/vm/Codegen.hpp b/src/openvic-simulation/vm/Codegen.hpp new file mode 100644 index 0000000..1670718 --- /dev/null +++ b/src/openvic-simulation/vm/Codegen.hpp @@ -0,0 +1,142 @@ +#pragma once + +#include <openvic-dataloader/v2script/AbstractSyntaxTree.hpp> +#include <openvic-dataloader/v2script/Parser.hpp> + +#include "AsmBuilder.hpp" +#include "Module.hpp" +#include <lauf/asm/builder.h> + +namespace OpenVic::Vm { + struct Codegen { + Codegen(const char* module_name, lauf_asm_build_options options = lauf_asm_default_build_options) + : _module(module_name), _builder(options) {} + + Codegen(Module&& module, AsmBuilder&& builder) : _module(std::move(module)), _builder(std::move(builder)) {} + + operator lauf_asm_module*() { + return _module; + } + + operator const lauf_asm_module*() const { + return _module; + } + + operator lauf_asm_builder*() { + return _builder; + } + + operator const lauf_asm_builder*() const { + return _builder; + } + + Module& module() { + return _module; + } + + Module const& module() const { + return _module; + } + + AsmBuilder& builder() { + return _builder; + } + + AsmBuilder const& builder() const { + return _builder; + } + + lauf_asm_block* create_block(size_t input_count) { + return lauf_asm_declare_block(_builder, input_count); + } + + void set_working_block(lauf_asm_block* block) { + lauf_asm_build_block(*this, block); + } + + lauf_asm_function* create_effect_function(ovdl::v2script::Parser const& parser, ovdl::v2script::ast::Node* node); + lauf_asm_function* create_condition_function(ovdl::v2script::Parser const& parser, ovdl::v2script::ast::Node* node); + + void generate_effect_from(ovdl::v2script::Parser const& parser, ovdl::v2script::ast::Node* node); + void generate_condition_from(ovdl::v2script::Parser const& parser, ovdl::v2script::ast::Node* node); + + // Bytecode instructions // + void inst_push_scope_this(); + void inst_push_scope_from(); + + void inst_push_get_country_capital(); + void inst_push_get_country_cultural_union(); + void inst_push_get_country_overlord(); + void inst_push_get_country_sphere_owner(); + + void inst_push_get_province_controller(); + void inst_push_get_province_owner(); + void inst_push_get_province_state(); + + void inst_push_get_pop_location(); + void inst_push_get_pop_country(); + void inst_push_get_pop_cultural_union(); + + void inst_push_get_random_country(); + void inst_push_get_random_owned(); + + void inst_push_get_random_neighbor_province(); + void inst_push_get_random_empty_neighbor_province(); + + void inst_push_get_this_union(); + + void inst_push_get_tag(const char* nation_id); + void inst_push_get_province(const char* province_id); + void inst_push_get_region(const char* region_id); + void inst_push_get_continent(const char* continent_id); + + void inst_push_get_pop_type(const char* pop_type_id); + void inst_push_get_unit_type(const char* unit_type_id); + void inst_push_get_factory_type(const char* factory_type_id); + void inst_push_get_building_type(const char* building_type_id); + void inst_push_get_crime_type(const char* crime_type_id); + + void inst_push_get_culture(const char* culture_id); + void inst_push_get_religion(const char* religion_id); + + void inst_push_get_economic_reform(const char* economic_reform_id); + void inst_push_get_social_reform(const char* social_reform_id); + void inst_push_get_political_reform(const char* political_reform_id); + + void inst_push_get_trade_policy(const char* trade_policy_id); + void inst_push_get_war_policy(const char* war_policy_id); + + void inst_push_get_issue(const char* issue_id); + void inst_push_get_ideology(const char* ideology_id); + void inst_push_get_party(const char* party_id); + + void inst_push_get_military_leader(const char* military_leader_id); + void inst_push_get_personality_trait(const char* personality_trait_id); + void inst_push_get_background_trait(const char* background_trait_id); + + void inst_push_get_event(const char* event_id); + + void inst_push_get_trade_good(const char* trade_good_id); + void inst_push_get_resource(const char* resource_id); + + void inst_push_get_technology(const char* technology_id); + void inst_push_get_government(const char* government_id); + void inst_push_get_casus_belli(const char* casus_belli_id); + void inst_push_get_national_value(const char* national_value_id); + + void inst_push_get_variable(const char* variable_id); + + void inst_push_get_global_flag(const char* flag_id); + + void inst_push_get_country_flag(const char* flag_id); + void inst_push_get_country_modifier(const char* modifier_id); + + void inst_push_get_province_flag(const char* flag_id); + void inst_push_get_province_modifier(const char* modifier_id); + // Bytecode instructions // + + private: + Module _module; + AsmBuilder _builder; + }; +} diff --git a/src/openvic-simulation/vm/Module.hpp b/src/openvic-simulation/vm/Module.hpp index d8a7c6e..9483e26 100644 --- a/src/openvic-simulation/vm/Module.hpp +++ b/src/openvic-simulation/vm/Module.hpp @@ -6,6 +6,7 @@ #include <range/v3/view/enumerate.hpp> +#include "vm/Utility.hpp" #include <lauf/asm/module.h> #include <lauf/asm/program.h> #include <lauf/asm/type.h> @@ -14,34 +15,8 @@ namespace OpenVic::Vm { template<typename T> concept Arithmetic = std::is_arithmetic_v<T>; - struct Module { - Module(const char* module_name) : _handle(lauf_asm_create_module(module_name)) {} - - Module(Module&&) = default; - Module& operator=(Module&&) = default; - - Module(Module const&) = delete; - Module& operator=(Module const&) = delete; - - ~Module() { - lauf_asm_destroy_module(_handle); - } - - lauf_asm_module* handle() { - return _handle; - } - - const lauf_asm_module* handle() const { - return _handle; - } - - operator lauf_asm_module*() { - return _handle; - } - - operator const lauf_asm_module*() const { - return _handle; - } + struct ModuleRef : utility::HandleBase<lauf_asm_module> { + using HandleBase::HandleBase; const char* name() const { return lauf_asm_module_name(_handle); @@ -80,7 +55,7 @@ namespace OpenVic::Vm { define_data(global, { sizeof(T), alignof(T) }, static_cast<const void*>(data)); } - static std::unique_ptr<const lauf_asm_module* const[]> make_list(std::span<Module> mods) { + static std::unique_ptr<const lauf_asm_module* const[]> make_list(std::span<ModuleRef> mods) { auto result = new const lauf_asm_module*[mods.size()]; auto span = std::span<const lauf_asm_module*> { result, mods.size() }; for (auto [count, element] : span | ranges::views::enumerate) { @@ -88,8 +63,20 @@ namespace OpenVic::Vm { } return std::unique_ptr<const lauf_asm_module* const[]>(result); } + }; + + struct Module : utility::MoveOnlyHandleDerived<Module, ModuleRef> { + using MoveOnlyHandleDerived::MoveOnlyHandleDerived; + using MoveOnlyHandleDerived::operator=; - private: - lauf_asm_module* _handle; + Module(const char* module_name) : MoveOnlyHandleDerived(lauf_asm_create_module(module_name)) {} + + ~Module() { + if (_handle == nullptr) { + return; + } + lauf_asm_destroy_module(_handle); + _handle = nullptr; + } }; } diff --git a/src/openvic-simulation/vm/Reader.hpp b/src/openvic-simulation/vm/Reader.hpp index e75042f..83f4788 100644 --- a/src/openvic-simulation/vm/Reader.hpp +++ b/src/openvic-simulation/vm/Reader.hpp @@ -2,58 +2,37 @@ #include <string_view> +#include "Utility.hpp" #include <lauf/reader.h> namespace OpenVic::Vm { template<typename Tag> - struct BasicReader { - BasicReader(BasicReader&&) = default; - BasicReader& operator=(BasicReader&&) = default; - - BasicReader(BasicReader const&) = delete; - BasicReader& operator=(BasicReader const&) = delete; + struct BasicReader : utility::MoveOnlyHandleBase<BasicReader<Tag>, lauf_reader> { + using utility::MoveOnlyHandleBase<BasicReader<Tag>, lauf_reader>::MoveOnlyHandleBase; + using utility::MoveOnlyHandleBase<BasicReader<Tag>, lauf_reader>::operator=; ~BasicReader() { - if (_handle == nullptr) { + if (this->_handle == nullptr) { return; } - lauf_destroy_reader(_handle); - } - - lauf_reader* handle() { - return _handle; - } - - const lauf_reader* handle() const { - return _handle; - } - - operator lauf_reader*() { - return _handle; - } - - operator const lauf_reader*() const { - return _handle; + lauf_destroy_reader(*this); + this->_handle = nullptr; } void set_path(const char* path) { - lauf_reader_set_path(_handle, path); + lauf_reader_set_path(*this, path); } struct StringTag; struct FileTag; struct StdinTag; - - protected: - BasicReader(lauf_reader* reader) : _handle(reader) {} - - private: - lauf_reader* _handle; }; template<> struct BasicReader<BasicReader<void>::StringTag> : BasicReader<void> { using BasicReader<void>::BasicReader; + using BasicReader<void>::operator=; + BasicReader(const char* cstr) : BasicReader(lauf_create_cstring_reader(cstr)) {} BasicReader(std::string_view view) : BasicReader(lauf_create_string_reader(view.data(), view.size())) {} }; @@ -61,6 +40,8 @@ namespace OpenVic::Vm { template<> struct BasicReader<BasicReader<void>::FileTag> : BasicReader<void> { using BasicReader<void>::BasicReader; + using BasicReader<void>::operator=; + BasicReader(const char* path) : BasicReader(lauf_create_file_reader(path)) {} bool is_valid() { @@ -71,6 +52,8 @@ namespace OpenVic::Vm { template<> struct BasicReader<BasicReader<void>::StdinTag> : BasicReader<void> { using BasicReader<void>::BasicReader; + using BasicReader<void>::operator=; + BasicReader() : BasicReader(lauf_create_stdin_reader()) {} }; diff --git a/src/openvic-simulation/vm/RuntimeFiber.hpp b/src/openvic-simulation/vm/RuntimeFiber.hpp index 2c4d21d..7e37e27 100644 --- a/src/openvic-simulation/vm/RuntimeFiber.hpp +++ b/src/openvic-simulation/vm/RuntimeFiber.hpp @@ -3,7 +3,8 @@ #include <cassert> #include <optional> -#include "vm/Stacktrace.hpp" +#include "Stacktrace.hpp" +#include "Utility.hpp" #include <lauf/runtime/process.h> #include <lauf/runtime/value.h> @@ -12,24 +13,8 @@ namespace OpenVic::Vm { struct RuntimeFiber; - struct RuntimeFiberRef { - RuntimeFiberRef(lauf_runtime_fiber* fiber) : _handle(fiber) {} - - lauf_runtime_fiber* handle() { - return _handle; - } - - const lauf_runtime_fiber* handle() const { - return _handle; - } - - operator lauf_runtime_fiber*() { - return _handle; - } - - operator const lauf_runtime_fiber*() const { - return _handle; - } + struct RuntimeFiberRef : utility::HandleBase<lauf_runtime_fiber> { + using HandleBase::HandleBase; lauf_runtime_address lauf_handle() const { assert(is_valid()); @@ -51,28 +36,14 @@ namespace OpenVic::Vm { bool is_valid() const { return _handle != nullptr; } - - protected: - lauf_runtime_fiber* _handle; }; - struct RuntimeFiber : RuntimeFiberRef { - RuntimeFiber(RuntimeFiber&&) = default; - RuntimeFiber& operator=(RuntimeFiber&&) = default; - - RuntimeFiber(RuntimeFiber const&) = delete; - RuntimeFiber& operator=(RuntimeFiber const&) = delete; + struct RuntimeFiber : utility::MoveOnlyHandleDerived<RuntimeFiber, RuntimeFiberRef> { + using MoveOnlyHandleDerived::MoveOnlyHandleDerived; + using MoveOnlyHandleDerived::operator=; ~RuntimeFiber(); - RuntimeFiberRef& as_ref() { - return *this; - } - - RuntimeFiberRef const& as_ref() const { - return *this; - } - std::optional<Stacktrace> get_stacktrace() const; std::optional<RuntimeFiberRef> get_parent(); @@ -87,9 +58,8 @@ namespace OpenVic::Vm { void destroy(); private: - friend RuntimeFiberRef; friend struct RuntimeProcess; - RuntimeFiber(RuntimeProcess* process, lauf_runtime_fiber* fiber) : RuntimeFiberRef(fiber), _process(process) {} + RuntimeFiber(RuntimeProcess* process, lauf_runtime_fiber* fiber) : MoveOnlyHandleDerived(fiber), _process(process) {} RuntimeProcess* _process; }; diff --git a/src/openvic-simulation/vm/RuntimeProcess.hpp b/src/openvic-simulation/vm/RuntimeProcess.hpp index be183e6..4ab8eb0 100644 --- a/src/openvic-simulation/vm/RuntimeProcess.hpp +++ b/src/openvic-simulation/vm/RuntimeProcess.hpp @@ -2,6 +2,7 @@ #include "vm/RuntimeFiber.hpp" #include "vm/Stacktrace.hpp" +#include "vm/Utility.hpp" #include <lauf/runtime/memory.h> #include <lauf/runtime/process.h> #include <lauf/runtime/stacktrace.h> @@ -9,31 +10,13 @@ namespace OpenVic::Vm { struct VirtualMachine; - struct RuntimeProcess { - RuntimeProcess(RuntimeProcess&&) = default; - RuntimeProcess& operator=(RuntimeProcess&&) = default; - - RuntimeProcess(RuntimeProcess const&) = delete; - RuntimeProcess& operator=(RuntimeProcess const&) = delete; + struct RuntimeProcess : utility::MoveOnlyHandleBase<RuntimeProcess, lauf_runtime_process> { + using MoveOnlyHandleBase::MoveOnlyHandleBase; + using MoveOnlyHandleBase::operator=; ~RuntimeProcess() { - lauf_runtime_destroy_process(_handle); - } - - lauf_runtime_process* handle() { - return _handle; - } - - const lauf_runtime_process* handle() const { - return _handle; - } - - operator lauf_runtime_process*() { - return _handle; - } - - operator const lauf_runtime_process*() const { - return _handle; + lauf_runtime_destroy_process(*this); + _handle = nullptr; } RuntimeFiber create_fiber(const lauf_asm_function* fn) { @@ -41,17 +24,15 @@ namespace OpenVic::Vm { } RuntimeFiberRef get_current_fiber() { - return lauf_runtime_get_current_fiber(_handle); + return lauf_runtime_get_current_fiber(*this); } RuntimeFiberRef get_fiber_ptr(lauf_runtime_address addr) { - return lauf_runtime_get_fiber_ptr(_handle, addr); + return lauf_runtime_get_fiber_ptr(*this, addr); } private: friend struct VirtualMachine; - RuntimeProcess(lauf_runtime_process* process) : _handle(process) {} - - lauf_runtime_process* _handle; + RuntimeProcess(lauf_runtime_process* process) : MoveOnlyHandleBase(process) {} }; } diff --git a/src/openvic-simulation/vm/Stacktrace.hpp b/src/openvic-simulation/vm/Stacktrace.hpp index 016443a..35f8a0c 100644 --- a/src/openvic-simulation/vm/Stacktrace.hpp +++ b/src/openvic-simulation/vm/Stacktrace.hpp @@ -2,64 +2,35 @@ #include <optional> +#include "Utility.hpp" #include <lauf/runtime/stacktrace.h> namespace OpenVic::Vm { struct RuntimeFiber; - struct StacktraceRef { - lauf_runtime_stacktrace* handle() { - return _handle; - } - - const lauf_runtime_stacktrace* handle() const { - return _handle; - } - - operator lauf_runtime_stacktrace*() { - return _handle; - } - - operator const lauf_runtime_stacktrace*() const { - return _handle; - } + struct StacktraceRef : utility::HandleBase<lauf_runtime_stacktrace> { + using HandleBase<lauf_runtime_stacktrace>::HandleBase; std::optional<StacktraceRef> get_parent() { auto result = lauf_runtime_stacktrace_parent(_handle); if (result == nullptr) { + _handle = nullptr; return std::nullopt; } return StacktraceRef(result); } - - protected: - friend struct RuntimeFiber; - StacktraceRef(lauf_runtime_stacktrace* stacktrace) : _handle(stacktrace) {} - - lauf_runtime_stacktrace* _handle; }; - struct Stacktrace : StacktraceRef { - Stacktrace(Stacktrace&&) = default; - Stacktrace& operator=(Stacktrace&&) = default; - - StacktraceRef& as_ref() { - return *this; - } - - StacktraceRef const& as_ref() const { - return *this; - } - - Stacktrace(Stacktrace const&) = delete; - Stacktrace& operator=(Stacktrace const&) = delete; + struct Stacktrace : utility::MoveOnlyHandleDerived<Stacktrace, StacktraceRef> { + using MoveOnlyHandleDerived::MoveOnlyHandleDerived; + using MoveOnlyHandleDerived::operator=; ~Stacktrace() { + if (_handle == nullptr) { + return; + } lauf_runtime_destroy_stacktrace(_handle); + _handle = nullptr; } - - private: - friend struct RuntimeFiber; - Stacktrace(lauf_runtime_stacktrace* stacktrace) : StacktraceRef(stacktrace) {} }; } diff --git a/src/openvic-simulation/vm/Utility.hpp b/src/openvic-simulation/vm/Utility.hpp new file mode 100644 index 0000000..189225e --- /dev/null +++ b/src/openvic-simulation/vm/Utility.hpp @@ -0,0 +1,72 @@ +#pragma once + +namespace OpenVic::Vm::utility { + template<typename T> + struct HandleBase { + HandleBase(T* handle) : _handle(handle) {} + + T* handle() { + return this->_handle; + } + + const T* handle() const { + return this->_handle; + } + + operator T*() { + return this->_handle; + } + + operator const T*() const { + return this->_handle; + } + + protected: + T* _handle; + }; + + template<typename Self, typename T> + struct MoveOnlyHandleBase : HandleBase<T> { + MoveOnlyHandleBase(Self&& other) : HandleBase<T>(other._handle) { + other._handle = nullptr; + } + + Self& operator=(Self&& other) { + this->_handle = other._handle; + other._handle = nullptr; + return *this; + } + + MoveOnlyHandleBase(Self const&) = delete; + Self& operator=(Self const&) = delete; + + protected: + using HandleBase<T>::HandleBase; + }; + + template<typename Self, typename Derived> + struct MoveOnlyHandleDerived : Derived { + using Derived::Derived; + + MoveOnlyHandleDerived(Self&& other) : Derived(other._handle) { + other._handle = nullptr; + } + + Self& operator=(Self&& other) { + this->_handle = other._handle; + other._handle = nullptr; + return *this; + } + + MoveOnlyHandleDerived(Self const&) = delete; + Self& operator=(Self const&) = delete; + + Derived& as_ref() { + return *this; + } + + Derived const& as_ref() const { + return *this; + } + }; +} diff --git a/src/openvic-simulation/vm/VirtualMachine.hpp b/src/openvic-simulation/vm/VirtualMachine.hpp index 1c130b2..4398f91 100644 --- a/src/openvic-simulation/vm/VirtualMachine.hpp +++ b/src/openvic-simulation/vm/VirtualMachine.hpp @@ -1,43 +1,26 @@ #pragma once #include "RuntimeProcess.hpp" +#include "Utility.hpp" #include <lauf/vm.h> namespace OpenVic::Vm { - struct VirtualMachine { - VirtualMachine(lauf_vm_options options) : _handle(lauf_create_vm(options)) {} + struct VirtualMachine : utility::MoveOnlyHandleBase<VirtualMachine, lauf_vm> { + using MoveOnlyHandleBase::MoveOnlyHandleBase; + using MoveOnlyHandleBase::operator=; - VirtualMachine(VirtualMachine&&) = default; - VirtualMachine& operator=(VirtualMachine&&) = default; - - VirtualMachine(VirtualMachine const&) = delete; - VirtualMachine& operator=(VirtualMachine const&) = delete; + VirtualMachine(lauf_vm_options options) : MoveOnlyHandleBase(lauf_create_vm(options)) {} ~VirtualMachine() { - lauf_destroy_vm(_handle); - } - - lauf_vm* handle() { - return _handle; - } - - const lauf_vm* handle() const { - return _handle; - } - - operator lauf_vm*() { - return _handle; - } - - operator const lauf_vm*() const { - return _handle; + if (_handle == nullptr) { + return; + } + lauf_destroy_vm(*this); + _handle = nullptr; } RuntimeProcess start_process(const lauf_asm_program* program) { - return RuntimeProcess(lauf_vm_start_process(_handle, program)); + return RuntimeProcess(lauf_vm_start_process(*this, program)); } - - private: - lauf_vm* _handle; }; } diff --git a/src/openvic-simulation/vm/Writer.hpp b/src/openvic-simulation/vm/Writer.hpp index 2a7696b..595a3da 100644 --- a/src/openvic-simulation/vm/Writer.hpp +++ b/src/openvic-simulation/vm/Writer.hpp @@ -1,50 +1,32 @@ #pragma once +#include "Utility.hpp" #include <lauf/writer.h> namespace OpenVic::Vm { template<typename Tag> - struct BasicWriter { - BasicWriter(BasicWriter&&) = default; - BasicWriter& operator=(BasicWriter&&) = default; - - BasicWriter(BasicWriter const&) = delete; - BasicWriter& operator=(BasicWriter const&) = delete; + struct BasicWriter : utility::MoveOnlyHandleBase<BasicWriter<Tag>, lauf_writer> { + using utility::MoveOnlyHandleBase<BasicWriter<Tag>, lauf_writer>::MoveOnlyHandleBase; + using utility::MoveOnlyHandleBase<BasicWriter<Tag>, lauf_writer>::operator=; ~BasicWriter() { - lauf_destroy_writer(_handle); - } - - lauf_writer* handle() { - return _handle; - } - - const lauf_writer* handle() const { - return _handle; - } - - operator lauf_writer*() { - return _handle; - } - - operator const lauf_writer*() const { - return _handle; + if (this->_handle == nullptr) { + return; + } + lauf_destroy_writer(*this); + this->_handle = nullptr; } struct StringTag; struct FileTag; struct StdoutTag; - - protected: - BasicWriter(lauf_writer* writer) : _handle(writer) {} - - private: - lauf_writer* _handle; }; template<> struct BasicWriter<BasicWriter<void>::StringTag> : BasicWriter<void> { using BasicWriter<void>::BasicWriter; + using BasicWriter<void>::operator=; + BasicWriter() : BasicWriter(lauf_create_string_writer()) {} const char* c_str() { @@ -55,12 +37,16 @@ namespace OpenVic::Vm { template<> struct BasicWriter<BasicWriter<void>::FileTag> : BasicWriter<void> { using BasicWriter<void>::BasicWriter; + using BasicWriter<void>::operator=; + BasicWriter(const char* path) : BasicWriter(lauf_create_file_writer(path)) {} }; template<> struct BasicWriter<BasicWriter<void>::StdoutTag> : BasicWriter<void> { using BasicWriter<void>::BasicWriter; + using BasicWriter<void>::operator=; + BasicWriter() : BasicWriter(lauf_create_stdout_writer()) {} }; |