refactor(furvm): integrate handle system into things
Sloppy af Refs: #12
This commit is contained in:
+32
-33
@@ -8,7 +8,6 @@
|
||||
#include "furvm/thing.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace furvm {
|
||||
@@ -29,50 +28,50 @@ struct executor::frame executor::frame() const {
|
||||
return m_frames.top();
|
||||
}
|
||||
|
||||
void executor::push_thing(const thing_p& thing) {
|
||||
thing->add_reference();
|
||||
void executor::push_thing(const thing_h& thing) {
|
||||
(*thing)->add_reference();
|
||||
m_stack.push(thing);
|
||||
}
|
||||
|
||||
void executor::push_thing(thing_p&& thing) {
|
||||
thing->add_reference();
|
||||
void executor::push_thing(thing_h&& thing) {
|
||||
(*thing)->add_reference();
|
||||
m_stack.push(std::move(thing));
|
||||
}
|
||||
|
||||
thing_p executor::pop_thing() {
|
||||
thing_h executor::pop_thing() {
|
||||
if (m_frames.top().stackBase >= m_stack.size()) throw stack_underflow();
|
||||
thing_p top = std::move(m_stack.top());
|
||||
thing_h top = std::move(m_stack.top());
|
||||
m_stack.pop();
|
||||
top->remove_reference();
|
||||
(*top)->remove_reference();
|
||||
return top;
|
||||
}
|
||||
|
||||
thing_p executor::thing() const {
|
||||
thing_h executor::thing() const {
|
||||
if (m_frames.top().stackBase >= m_stack.size()) throw stack_underflow();
|
||||
return m_stack.top();
|
||||
}
|
||||
|
||||
void executor::store_thing(variable_t variable, const thing_p& thing) {
|
||||
void executor::store_thing(variable_t variable, const thing_h& thing) {
|
||||
auto& frame = m_frames.top();
|
||||
frame.variables.resize(variable + 1);
|
||||
if (frame.variables[variable] != nullptr) {
|
||||
frame.variables[variable]->remove_reference();
|
||||
if (*frame.variables[variable] != nullptr) {
|
||||
(*frame.variables[variable])->remove_reference();
|
||||
}
|
||||
frame.variables[variable] = thing;
|
||||
thing->add_reference();
|
||||
(*thing)->add_reference();
|
||||
}
|
||||
|
||||
void executor::store_thing(variable_t variable, thing_p&& thing) {
|
||||
void executor::store_thing(variable_t variable, thing_h&& thing) {
|
||||
auto& frame = m_frames.top();
|
||||
frame.variables.resize(variable + 1);
|
||||
if (frame.variables[variable] != nullptr) {
|
||||
frame.variables[variable]->remove_reference();
|
||||
if ((*frame.variables[variable]) != nullptr) {
|
||||
(*frame.variables[variable])->remove_reference();
|
||||
}
|
||||
thing->add_reference();
|
||||
(*thing)->add_reference();
|
||||
frame.variables[variable] = std::move(thing);
|
||||
}
|
||||
|
||||
thing_p executor::load_thing(variable_t variable) const {
|
||||
thing_h executor::load_thing(variable_t variable) const {
|
||||
const auto& frame = m_frames.top();
|
||||
return frame.variables[variable];
|
||||
}
|
||||
@@ -86,8 +85,8 @@ void executor::step() {
|
||||
switch (instr) {
|
||||
case instruction_t::NoOperation: break;
|
||||
case instruction_t::PushB2I: {
|
||||
auto thing = std::make_shared<class thing>(m_context, thing_t::Int32);
|
||||
thing->int32() = (*frame.mod)->byte(frame.position++);
|
||||
auto thing = m_context->emplace_thing(thing_t::Int32);
|
||||
(*thing)->int32() = (*frame.mod)->byte(frame.position++);
|
||||
push_thing(std::move(thing));
|
||||
} break;
|
||||
case instruction_t::Drop: {
|
||||
@@ -97,62 +96,62 @@ void executor::step() {
|
||||
push_thing(thing());
|
||||
} break;
|
||||
case instruction_t::Clone: {
|
||||
push_thing(std::move(thing::clone(thing())));
|
||||
push_thing(std::move(thing::clone(m_context, thing())));
|
||||
} break;
|
||||
case instruction_t::Add: {
|
||||
auto rhs = pop_thing();
|
||||
auto lhs = pop_thing();
|
||||
push_thing(lhs + rhs);
|
||||
push_thing((*lhs)->add(m_context, rhs));
|
||||
} break;
|
||||
case instruction_t::Sub: {
|
||||
auto rhs = pop_thing();
|
||||
auto lhs = pop_thing();
|
||||
push_thing(lhs - rhs);
|
||||
push_thing((*lhs)->sub(m_context, rhs));
|
||||
} break;
|
||||
case instruction_t::Mul: {
|
||||
auto rhs = pop_thing();
|
||||
auto lhs = pop_thing();
|
||||
push_thing(lhs * rhs);
|
||||
push_thing((*lhs)->mul(m_context, rhs));
|
||||
} break;
|
||||
case instruction_t::Div: {
|
||||
auto rhs = pop_thing();
|
||||
auto lhs = pop_thing();
|
||||
push_thing(lhs / rhs);
|
||||
push_thing((*lhs)->div(m_context, rhs));
|
||||
} break;
|
||||
case instruction_t::Mod: {
|
||||
auto rhs = pop_thing();
|
||||
auto lhs = pop_thing();
|
||||
push_thing(lhs % rhs);
|
||||
push_thing((*lhs)->mod(m_context, rhs));
|
||||
} break;
|
||||
case instruction_t::Equals: {
|
||||
auto rhs = pop_thing();
|
||||
auto lhs = pop_thing();
|
||||
push_thing(lhs == rhs);
|
||||
push_thing((*lhs)->equals(m_context, rhs));
|
||||
} break;
|
||||
case instruction_t::NotEquals: {
|
||||
auto rhs = pop_thing();
|
||||
auto lhs = pop_thing();
|
||||
push_thing(lhs != rhs);
|
||||
push_thing((*lhs)->not_equals(m_context, rhs));
|
||||
} break;
|
||||
case instruction_t::LessThan: {
|
||||
auto rhs = pop_thing();
|
||||
auto lhs = pop_thing();
|
||||
push_thing(lhs < rhs);
|
||||
push_thing((*lhs)->less_than(m_context, rhs));
|
||||
} break;
|
||||
case instruction_t::GreaterThan: {
|
||||
auto rhs = pop_thing();
|
||||
auto lhs = pop_thing();
|
||||
push_thing(lhs > rhs);
|
||||
push_thing((*lhs)->greater_than(m_context, rhs));
|
||||
} break;
|
||||
case instruction_t::LessEqual: {
|
||||
auto rhs = pop_thing();
|
||||
auto lhs = pop_thing();
|
||||
push_thing(lhs <= rhs);
|
||||
push_thing((*lhs)->less_equals(m_context, rhs));
|
||||
} break;
|
||||
case instruction_t::GreaterEqual: {
|
||||
auto rhs = pop_thing();
|
||||
auto lhs = pop_thing();
|
||||
push_thing(lhs >= rhs);
|
||||
push_thing((*lhs)->greater_equals(m_context, rhs));
|
||||
} break;
|
||||
case instruction_t::Load: {
|
||||
variable_t variable = static_cast<std::uint16_t>((*frame.mod)->byte(frame.position)) |
|
||||
@@ -188,7 +187,7 @@ void executor::step() {
|
||||
case instruction_t::JumpNotZero: {
|
||||
byte offset = (*frame.mod)->byte(frame.position++);
|
||||
auto cond = pop_thing();
|
||||
if (cond->int32() != 0) frame.position += offset;
|
||||
if ((*cond)->int32() != 0) frame.position += offset;
|
||||
} break;
|
||||
case instruction_t::Return: {
|
||||
pop_frame();
|
||||
|
||||
+145
-153
@@ -17,23 +17,10 @@ std::size_t thing_type_size(thing_t type) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
thing::thing(const context_p& context, thing_t type)
|
||||
: m_context(context), m_type(type) {
|
||||
thing::thing(thing_t type)
|
||||
: m_type(type) {
|
||||
std::size_t size = thing_type_size(type);
|
||||
std::byte* data = nullptr;
|
||||
if (!m_context->m_deadThingData.empty()) {
|
||||
thing_t itType{};
|
||||
for (auto it = m_context->m_deadThingData.rbegin(); it != m_context->m_deadThingData.rend(); ++it) {
|
||||
std::memcpy(&itType, static_cast<std::byte*>(*it) - sizeof(itType), sizeof(itType));
|
||||
if (size == thing_type_size(itType)) {
|
||||
data = static_cast<std::byte*>(*it);
|
||||
m_context->m_deadThingData.erase(std::next(it).base());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (data == nullptr) data = m_context->m_thingArena.allocate<std::byte>(sizeof(type) + size);
|
||||
|
||||
byte* data = new byte[size];
|
||||
if (data == nullptr) throw std::runtime_error("failed to allocate data for new thing");
|
||||
std::memcpy(data, &type, sizeof(type));
|
||||
m_data = data + sizeof(type);
|
||||
@@ -45,6 +32,20 @@ thing::thing(const context_p& context, thing_t type)
|
||||
}
|
||||
}
|
||||
|
||||
thing::thing(thing_t type, void* data)
|
||||
: m_type(type), m_ownData(false) {
|
||||
std::size_t size = thing_type_size(type);
|
||||
if (data == nullptr) throw std::runtime_error("failed to allocate data for new thing");
|
||||
std::memcpy(data, &type, sizeof(type));
|
||||
m_data = static_cast<char*>(data) + sizeof(type);
|
||||
|
||||
switch (m_type) {
|
||||
// Primitives are zero-initialized.
|
||||
default:
|
||||
case thing_t::Int32: std::memset(m_data, 0, size);
|
||||
}
|
||||
}
|
||||
|
||||
thing::~thing() {
|
||||
switch (m_type) {
|
||||
// Primitives are not destructed.
|
||||
@@ -52,19 +53,19 @@ thing::~thing() {
|
||||
case thing_t::Int32: break;
|
||||
}
|
||||
|
||||
m_context->m_deadThingData.push_back(m_data);
|
||||
if (m_ownData) delete[] static_cast<char*>(m_data);
|
||||
}
|
||||
|
||||
thing::thing(thing&& other) noexcept
|
||||
: m_context(std::move(other.m_context)), m_type(other.m_type), m_refCount(other.m_refCount), m_data(other.m_data) {
|
||||
: m_type(other.m_type), m_refCount(other.m_refCount), m_data(other.m_data) {
|
||||
other.m_type = {};
|
||||
other.m_ownData = false;
|
||||
other.m_refCount = {};
|
||||
other.m_data = nullptr;
|
||||
}
|
||||
|
||||
thing& thing::operator=(thing&& other) noexcept {
|
||||
if (this == &other) return *this;
|
||||
m_context = std::move(other.m_context);
|
||||
m_type = other.m_type;
|
||||
m_refCount = other.m_refCount;
|
||||
m_data = other.m_data;
|
||||
@@ -79,145 +80,15 @@ static constexpr std::uint16_t thing_type_pair(thing_t lhs, thing_t rhs) {
|
||||
return (static_cast<std::uint16_t>(lhs) << 8) | static_cast<std::uint16_t>(rhs);
|
||||
}
|
||||
|
||||
thing_p operator+(const thing_p& lhs, const thing_p& rhs) {
|
||||
switch (thing_type_pair(lhs->m_type, rhs->m_type)) {
|
||||
case thing_type_pair(thing_t::Int32, thing_t::Int32): {
|
||||
auto res = std::make_shared<thing>(lhs->m_context, thing_t::Int32);
|
||||
res->int32() = lhs->int32() + rhs->int32();
|
||||
return res;
|
||||
}
|
||||
default: throw std::runtime_error("unexpected operator");
|
||||
}
|
||||
}
|
||||
|
||||
thing_p operator-(const thing_p& lhs, const thing_p& rhs) {
|
||||
switch (thing_type_pair(lhs->m_type, rhs->m_type)) {
|
||||
case thing_type_pair(thing_t::Int32, thing_t::Int32): {
|
||||
auto res = std::make_shared<thing>(lhs->m_context, thing_t::Int32);
|
||||
res->int32() = lhs->int32() - rhs->int32();
|
||||
return res;
|
||||
}
|
||||
default: throw std::runtime_error("unexpected operator");
|
||||
}
|
||||
}
|
||||
|
||||
thing_p operator*(const thing_p& lhs, const thing_p& rhs) {
|
||||
switch (thing_type_pair(lhs->m_type, rhs->m_type)) {
|
||||
case thing_type_pair(thing_t::Int32, thing_t::Int32): {
|
||||
auto res = std::make_shared<thing>(lhs->m_context, thing_t::Int32);
|
||||
res->int32() = lhs->int32() * rhs->int32();
|
||||
return res;
|
||||
}
|
||||
default: throw std::runtime_error("unexpected operator");
|
||||
}
|
||||
}
|
||||
|
||||
thing_p operator/(const thing_p& lhs, const thing_p& rhs) {
|
||||
switch (thing_type_pair(lhs->m_type, rhs->m_type)) {
|
||||
case thing_type_pair(thing_t::Int32, thing_t::Int32): {
|
||||
auto res = std::make_shared<thing>(lhs->m_context, thing_t::Int32);
|
||||
res->int32() = lhs->int32() / rhs->int32();
|
||||
return res;
|
||||
}
|
||||
default: throw std::runtime_error("unexpected operator");
|
||||
}
|
||||
}
|
||||
|
||||
thing_p operator%(const thing_p& lhs, const thing_p& rhs) {
|
||||
switch (thing_type_pair(lhs->m_type, rhs->m_type)) {
|
||||
case thing_type_pair(thing_t::Int32, thing_t::Int32): {
|
||||
auto res = std::make_shared<thing>(lhs->m_context, thing_t::Int32);
|
||||
res->int32() = lhs->int32() % rhs->int32();
|
||||
return res;
|
||||
}
|
||||
default: throw std::runtime_error("unexpected operator");
|
||||
}
|
||||
}
|
||||
|
||||
thing_p operator==(const thing_p& lhs, const thing_p& rhs) {
|
||||
switch (thing_type_pair(lhs->m_type, rhs->m_type)) {
|
||||
case thing_type_pair(thing_t::Int32, thing_t::Int32): {
|
||||
auto res = std::make_shared<thing>(lhs->m_context, thing_t::Int32);
|
||||
res->int32() = static_cast<std::int32_t>(lhs->int32() == rhs->int32());
|
||||
return res;
|
||||
}
|
||||
default: throw std::runtime_error("unexpected operator");
|
||||
}
|
||||
}
|
||||
|
||||
thing_p operator!=(const thing_p& lhs, const thing_p& rhs) {
|
||||
switch (thing_type_pair(lhs->m_type, rhs->m_type)) {
|
||||
case thing_type_pair(thing_t::Int32, thing_t::Int32): {
|
||||
auto res = std::make_shared<thing>(lhs->m_context, thing_t::Int32);
|
||||
res->int32() = static_cast<std::int32_t>(lhs->int32() != rhs->int32());
|
||||
return res;
|
||||
}
|
||||
default: throw std::runtime_error("unexpected operator");
|
||||
}
|
||||
}
|
||||
|
||||
thing_p operator<(const thing_p& lhs, const thing_p& rhs) {
|
||||
switch (thing_type_pair(lhs->m_type, rhs->m_type)) {
|
||||
case thing_type_pair(thing_t::Int32, thing_t::Int32): {
|
||||
auto res = std::make_shared<thing>(lhs->m_context, thing_t::Int32);
|
||||
res->int32() = static_cast<std::int32_t>(lhs->int32() < rhs->int32());
|
||||
return res;
|
||||
}
|
||||
default: throw std::runtime_error("unexpected operator");
|
||||
}
|
||||
}
|
||||
|
||||
thing_p operator>(const thing_p& lhs, const thing_p& rhs) {
|
||||
switch (thing_type_pair(lhs->m_type, rhs->m_type)) {
|
||||
case thing_type_pair(thing_t::Int32, thing_t::Int32): {
|
||||
auto res = std::make_shared<thing>(lhs->m_context, thing_t::Int32);
|
||||
res->int32() = static_cast<std::int32_t>(lhs->int32() > rhs->int32());
|
||||
return res;
|
||||
}
|
||||
default: throw std::runtime_error("unexpected operator");
|
||||
}
|
||||
}
|
||||
|
||||
thing_p operator<=(const thing_p& lhs, const thing_p& rhs) {
|
||||
switch (thing_type_pair(lhs->m_type, rhs->m_type)) {
|
||||
case thing_type_pair(thing_t::Int32, thing_t::Int32): {
|
||||
auto res = std::make_shared<thing>(lhs->m_context, thing_t::Int32);
|
||||
res->int32() = static_cast<std::int32_t>(lhs->int32() <= rhs->int32());
|
||||
return res;
|
||||
}
|
||||
default: throw std::runtime_error("unexpected operator");
|
||||
}
|
||||
}
|
||||
|
||||
thing_p operator>=(const thing_p& lhs, const thing_p& rhs) {
|
||||
switch (thing_type_pair(lhs->m_type, rhs->m_type)) {
|
||||
case thing_type_pair(thing_t::Int32, thing_t::Int32): {
|
||||
auto res = std::make_shared<thing>(lhs->m_context, thing_t::Int32);
|
||||
res->int32() = static_cast<std::int32_t>(lhs->int32() >= rhs->int32());
|
||||
return res;
|
||||
}
|
||||
default: throw std::runtime_error("unexpected operator");
|
||||
}
|
||||
}
|
||||
|
||||
thing_p thing::clone(const thing_p& thing) {
|
||||
thing_id id = thing->m_context->m_things.size();
|
||||
if (!thing->m_context->m_deadThings.empty()) {
|
||||
id = thing->m_context->m_deadThings.front();
|
||||
thing->m_context->m_deadThings.pop();
|
||||
id += 1 << GENERATION_SIZE;
|
||||
}
|
||||
thing_id idx = id & ((1ULL << ((sizeof(id) * 8) - GENERATION_SIZE)) - 1);
|
||||
|
||||
auto th = std::make_shared<class thing>(thing->m_context, thing->m_type);
|
||||
switch (thing->m_type) {
|
||||
thing_h thing::clone(const context_p& context, const thing_h& thing) {
|
||||
auto th = context->emplace_thing((*thing)->m_type);
|
||||
switch ((*thing)->m_type) {
|
||||
// Primitives
|
||||
default: {
|
||||
memcpy(th->m_data, thing->m_data, thing_type_size(thing->m_type));
|
||||
memcpy((*th)->m_data, (*thing)->m_data, thing_type_size((*thing)->m_type));
|
||||
}
|
||||
}
|
||||
|
||||
thing->m_context->m_things.emplace(thing->m_context->m_things.begin() + idx, th);
|
||||
return std::move(th);
|
||||
}
|
||||
|
||||
@@ -231,6 +102,127 @@ const std::int32_t& thing::int32() const {
|
||||
return *static_cast<std::int32_t*>(m_data);
|
||||
}
|
||||
|
||||
thing_h thing::add(const context_p& context, const thing_h& rhs) const {
|
||||
switch (thing_type_pair(m_type, (*rhs)->m_type)) {
|
||||
case thing_type_pair(thing_t::Int32, thing_t::Int32): {
|
||||
thing_h res = context->emplace_thing(thing_t::Int32);
|
||||
(*res)->int32() = int32() + (*rhs)->int32();
|
||||
return res;
|
||||
}
|
||||
default: throw std::runtime_error("unreachable");
|
||||
}
|
||||
}
|
||||
|
||||
thing_h thing::sub(const context_p& context, const thing_h& rhs) const {
|
||||
switch (thing_type_pair(m_type, (*rhs)->m_type)) {
|
||||
case thing_type_pair(thing_t::Int32, thing_t::Int32): {
|
||||
thing_h res = context->emplace_thing(thing_t::Int32);
|
||||
(*res)->int32() = int32() - (*rhs)->int32();
|
||||
return res;
|
||||
}
|
||||
default: throw std::runtime_error("unreachable");
|
||||
}
|
||||
}
|
||||
|
||||
thing_h thing::mul(const context_p& context, const thing_h& rhs) const {
|
||||
switch (thing_type_pair(m_type, (*rhs)->m_type)) {
|
||||
case thing_type_pair(thing_t::Int32, thing_t::Int32): {
|
||||
thing_h res = context->emplace_thing(thing_t::Int32);
|
||||
(*res)->int32() = int32() * (*rhs)->int32();
|
||||
return res;
|
||||
}
|
||||
default: throw std::runtime_error("unreachable");
|
||||
}
|
||||
}
|
||||
|
||||
thing_h thing::div(const context_p& context, const thing_h& rhs) const {
|
||||
switch (thing_type_pair(m_type, (*rhs)->m_type)) {
|
||||
case thing_type_pair(thing_t::Int32, thing_t::Int32): {
|
||||
thing_h res = context->emplace_thing(thing_t::Int32);
|
||||
(*res)->int32() = int32() / (*rhs)->int32();
|
||||
return res;
|
||||
}
|
||||
default: throw std::runtime_error("unreachable");
|
||||
}
|
||||
}
|
||||
|
||||
thing_h thing::mod(const context_p& context, const thing_h& rhs) const {
|
||||
switch (thing_type_pair(m_type, (*rhs)->m_type)) {
|
||||
case thing_type_pair(thing_t::Int32, thing_t::Int32): {
|
||||
thing_h res = context->emplace_thing(thing_t::Int32);
|
||||
(*res)->int32() = int32() % (*rhs)->int32();
|
||||
return res;
|
||||
}
|
||||
default: throw std::runtime_error("unreachable");
|
||||
}
|
||||
}
|
||||
|
||||
thing_h thing::equals(const context_p& context, const thing_h& rhs) const {
|
||||
switch (thing_type_pair(m_type, (*rhs)->m_type)) {
|
||||
case thing_type_pair(thing_t::Int32, thing_t::Int32): {
|
||||
thing_h res = context->emplace_thing(thing_t::Int32);
|
||||
(*res)->int32() = static_cast<std::int32_t>(int32() == (*rhs)->int32());
|
||||
return res;
|
||||
}
|
||||
default: throw std::runtime_error("unreachable");
|
||||
}
|
||||
}
|
||||
|
||||
thing_h thing::not_equals(const context_p& context, const thing_h& rhs) const {
|
||||
switch (thing_type_pair(m_type, (*rhs)->m_type)) {
|
||||
case thing_type_pair(thing_t::Int32, thing_t::Int32): {
|
||||
thing_h res = context->emplace_thing(thing_t::Int32);
|
||||
(*res)->int32() = static_cast<std::int32_t>(int32() != (*rhs)->int32());
|
||||
return res;
|
||||
}
|
||||
default: throw std::runtime_error("unreachable");
|
||||
}
|
||||
}
|
||||
|
||||
thing_h thing::less_than(const context_p& context, const thing_h& rhs) const {
|
||||
switch (thing_type_pair(m_type, (*rhs)->m_type)) {
|
||||
case thing_type_pair(thing_t::Int32, thing_t::Int32): {
|
||||
thing_h res = context->emplace_thing(thing_t::Int32);
|
||||
(*res)->int32() = static_cast<std::int32_t>(int32() < (*rhs)->int32());
|
||||
return res;
|
||||
}
|
||||
default: throw std::runtime_error("unreachable");
|
||||
}
|
||||
}
|
||||
|
||||
thing_h thing::greater_than(const context_p& context, const thing_h& rhs) const {
|
||||
switch (thing_type_pair(m_type, (*rhs)->m_type)) {
|
||||
case thing_type_pair(thing_t::Int32, thing_t::Int32): {
|
||||
thing_h res = context->emplace_thing(thing_t::Int32);
|
||||
(*res)->int32() = static_cast<std::int32_t>(int32() > (*rhs)->int32());
|
||||
return res;
|
||||
}
|
||||
default: throw std::runtime_error("unreachable");
|
||||
}
|
||||
}
|
||||
|
||||
thing_h thing::less_equals(const context_p& context, const thing_h& rhs) const {
|
||||
switch (thing_type_pair(m_type, (*rhs)->m_type)) {
|
||||
case thing_type_pair(thing_t::Int32, thing_t::Int32): {
|
||||
thing_h res = context->emplace_thing(thing_t::Int32);
|
||||
(*res)->int32() = static_cast<std::int32_t>(int32() <= (*rhs)->int32());
|
||||
return res;
|
||||
}
|
||||
default: throw std::runtime_error("unreachable");
|
||||
}
|
||||
}
|
||||
|
||||
thing_h thing::greater_equals(const context_p& context, const thing_h& rhs) const {
|
||||
switch (thing_type_pair(m_type, (*rhs)->m_type)) {
|
||||
case thing_type_pair(thing_t::Int32, thing_t::Int32): {
|
||||
thing_h res = context->emplace_thing(thing_t::Int32);
|
||||
(*res)->int32() = static_cast<std::int32_t>(int32() >= (*rhs)->int32());
|
||||
return res;
|
||||
}
|
||||
default: throw std::runtime_error("unreachable");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace furvm
|
||||
|
||||
// NOLINTEND(cppcoreguidelines-no-malloc)
|
||||
|
||||
Reference in New Issue
Block a user