feat(furvm): introduce comparison operators
This commit is contained in:
@@ -65,6 +65,36 @@ enum class instruction_t : byte {
|
|||||||
*/
|
*/
|
||||||
Mod,
|
Mod,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Compares two top-most things from the stack for equality.
|
||||||
|
*/
|
||||||
|
Equals,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Compares two top-most things from the stack for inequality.
|
||||||
|
*/
|
||||||
|
NotEquals,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Compares if the first top-most thing is less than the second top-most thing.
|
||||||
|
*/
|
||||||
|
LessThan,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Compares if the first top-most thing is greater than the second top-most thing.
|
||||||
|
*/
|
||||||
|
GreaterThan,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Compares if the first top-most thing is less than or equal to the second top-most thing.
|
||||||
|
*/
|
||||||
|
LessEqual,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Compares if the first top-most thing is greater than or equal to the second top-most thing.
|
||||||
|
*/
|
||||||
|
GreaterEqual,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Pushes a variable onto the stack.
|
* @brief Pushes a variable onto the stack.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -135,6 +135,59 @@ public:
|
|||||||
* @return Shared pointer to result thing.
|
* @return Shared pointer to result thing.
|
||||||
*/
|
*/
|
||||||
friend thing_p operator%(const thing_p& lhs, const thing_p& rhs);
|
friend thing_p operator%(const thing_p& lhs, const thing_p& rhs);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Compares two things for equality.
|
||||||
|
*
|
||||||
|
* @param lhs Left-hand-side thing.
|
||||||
|
* @param rhs Right-hand-side thing.
|
||||||
|
* @return Shared pointer to result thing.
|
||||||
|
*/
|
||||||
|
friend thing_p operator==(const thing_p& lhs, const thing_p& rhs);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Compares two things for equality.
|
||||||
|
*
|
||||||
|
* @param lhs Left-hand-side thing.
|
||||||
|
* @param rhs Right-hand-side thing.
|
||||||
|
* @return Shared pointer to result thing.
|
||||||
|
*/
|
||||||
|
friend thing_p operator!=(const thing_p& lhs, const thing_p& rhs);
|
||||||
|
/**
|
||||||
|
* @brief Compares if the left thing is less than the right thing.
|
||||||
|
*
|
||||||
|
* @param lhs Left-hand-side thing.
|
||||||
|
* @param rhs Right-hand-side thing.
|
||||||
|
* @return Shared pointer to result thing.
|
||||||
|
*/
|
||||||
|
friend thing_p operator<(const thing_p& lhs, const thing_p& rhs);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Compares if the left thing is greater than the right thing.
|
||||||
|
*
|
||||||
|
* @param lhs Left-hand-side thing.
|
||||||
|
* @param rhs Right-hand-side thing.
|
||||||
|
* @return Shared pointer to result thing.
|
||||||
|
*/
|
||||||
|
friend thing_p operator>(const thing_p& lhs, const thing_p& rhs);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Compares if the left thing is less than or equal to the right thing.
|
||||||
|
*
|
||||||
|
* @param lhs Left-hand-side thing.
|
||||||
|
* @param rhs Right-hand-side thing.
|
||||||
|
* @return Shared pointer to result thing.
|
||||||
|
*/
|
||||||
|
friend thing_p operator<=(const thing_p& lhs, const thing_p& rhs);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Compares if the left thing is greater than or equal to the right thing.
|
||||||
|
*
|
||||||
|
* @param lhs Left-hand-side thing.
|
||||||
|
* @param rhs Right-hand-side thing.
|
||||||
|
* @return Shared pointer to result thing.
|
||||||
|
*/
|
||||||
|
friend thing_p operator>=(const thing_p& lhs, const thing_p& rhs);
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief Returns a new thing.
|
* @brief Returns a new thing.
|
||||||
@@ -208,4 +261,4 @@ private:
|
|||||||
|
|
||||||
} // namespace furvm
|
} // namespace furvm
|
||||||
|
|
||||||
#endif // FURVM_THING_HPP
|
#endif // FURVM_THING_HPP
|
||||||
|
|||||||
@@ -136,6 +136,36 @@ void executor::step() {
|
|||||||
auto lhs = pop_thing();
|
auto lhs = pop_thing();
|
||||||
push_thing(lhs % rhs);
|
push_thing(lhs % rhs);
|
||||||
} break;
|
} break;
|
||||||
|
case instruction_t::Equals: {
|
||||||
|
auto rhs = pop_thing();
|
||||||
|
auto lhs = pop_thing();
|
||||||
|
push_thing(lhs == rhs);
|
||||||
|
} break;
|
||||||
|
case instruction_t::NotEquals: {
|
||||||
|
auto rhs = pop_thing();
|
||||||
|
auto lhs = pop_thing();
|
||||||
|
push_thing(lhs != rhs);
|
||||||
|
} break;
|
||||||
|
case instruction_t::LessThan: {
|
||||||
|
auto rhs = pop_thing();
|
||||||
|
auto lhs = pop_thing();
|
||||||
|
push_thing(lhs < rhs);
|
||||||
|
} break;
|
||||||
|
case instruction_t::GreaterThan: {
|
||||||
|
auto rhs = pop_thing();
|
||||||
|
auto lhs = pop_thing();
|
||||||
|
push_thing(lhs > rhs);
|
||||||
|
} break;
|
||||||
|
case instruction_t::LessEqual: {
|
||||||
|
auto rhs = pop_thing();
|
||||||
|
auto lhs = pop_thing();
|
||||||
|
push_thing(lhs <= rhs);
|
||||||
|
} break;
|
||||||
|
case instruction_t::GreaterEqual: {
|
||||||
|
auto rhs = pop_thing();
|
||||||
|
auto lhs = pop_thing();
|
||||||
|
push_thing(lhs >= rhs);
|
||||||
|
} break;
|
||||||
case instruction_t::Load: {
|
case instruction_t::Load: {
|
||||||
variable_t variable = static_cast<std::uint16_t>(frame.mod->byte(frame.position)) |
|
variable_t variable = static_cast<std::uint16_t>(frame.mod->byte(frame.position)) |
|
||||||
(static_cast<std::uint16_t>(frame.mod->byte(frame.position + 1)) << 8);
|
(static_cast<std::uint16_t>(frame.mod->byte(frame.position + 1)) << 8);
|
||||||
|
|||||||
+67
-1
@@ -141,6 +141,72 @@ thing_p operator%(const thing_p& lhs, const thing_p& 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 = thing::create(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 = thing::create(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 = thing::create(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 = thing::create(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 = thing::create(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 = thing::create(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_p thing::clone(const thing_p& thing) {
|
||||||
thing_handle id = thing->m_context->m_things.size();
|
thing_handle id = thing->m_context->m_things.size();
|
||||||
if (!thing->m_context->m_deadThings.empty()) {
|
if (!thing->m_context->m_deadThings.empty()) {
|
||||||
@@ -174,4 +240,4 @@ const std::int32_t& thing::int32() const {
|
|||||||
|
|
||||||
} // namespace furvm
|
} // namespace furvm
|
||||||
|
|
||||||
// NOLINTEND(cppcoreguidelines-no-malloc)
|
// NOLINTEND(cppcoreguidelines-no-malloc)
|
||||||
|
|||||||
Reference in New Issue
Block a user