aboutsummaryrefslogtreecommitdiff
path: root/src/openvic-simulation/vm
diff options
context:
space:
mode:
Diffstat (limited to 'src/openvic-simulation/vm')
-rw-r--r--src/openvic-simulation/vm/AsmBuilder.hpp87
-rw-r--r--src/openvic-simulation/vm/Codegen.cpp82
-rw-r--r--src/openvic-simulation/vm/Codegen.hpp142
-rw-r--r--src/openvic-simulation/vm/Module.hpp49
-rw-r--r--src/openvic-simulation/vm/Reader.hpp45
-rw-r--r--src/openvic-simulation/vm/RuntimeFiber.hpp46
-rw-r--r--src/openvic-simulation/vm/RuntimeProcess.hpp37
-rw-r--r--src/openvic-simulation/vm/Stacktrace.hpp51
-rw-r--r--src/openvic-simulation/vm/Utility.hpp72
-rw-r--r--src/openvic-simulation/vm/VirtualMachine.hpp39
-rw-r--r--src/openvic-simulation/vm/Writer.hpp44
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()) {}
};