#include<cstdlib>
#include<cstdint>
#include<cstddef>
#include<cstdio>
#include<initializer_list>
namespace test{
struct operation;
class
operand
{
enum class kind{
integer,
reference,
operation,
} m_kind;
int m_i;
int* m_ip;
const operation* m_o;
public:
operand() noexcept{}
operand(int i) noexcept: m_kind(kind::integer), m_i(i){}
operand(int* ip) noexcept: m_kind(kind::reference), m_ip(ip){}
operand(const operation& o) noexcept: m_kind(kind::operation), m_o(&o){}
int& get() const noexcept{return *m_ip;}
int evaluate() const noexcept;
};
enum class
operato
{
st,
add,
lt,
};
struct
operation
{
operato op;
operand o1;
operand o2;
int evaluate() const noexcept
{
switch(op)
{
case(operato::st):
return o1.get() = o2.evaluate();
case(operato::add):
return o1.get() += o2.evaluate();
case(operato::lt):
return (o1.evaluate() < o2.evaluate())? 1:0;
}
}
};
int
operand::
evaluate() const noexcept
{
return (m_kind == kind::integer )? m_i
:(m_kind == kind::reference)? *m_ip
:m_o->evaluate();
}
enum class
opcode
{
eval_dump,
eval_save,
eval_zero,
jump,
jump_by_condition,
exi,
};
struct
inst_code
{
uint32_t m_data=0;
public:
constexpr inst_code() noexcept{}
constexpr inst_code(opcode op, int16_t v) noexcept: m_data((static_cast<int>(op)<<16)|(v&0xFFFF)){}
constexpr opcode get_opcode() const noexcept{return static_cast<opcode>(m_data>>16);}
constexpr int16_t get_imm() const noexcept{return (m_data&0xFFFF);}
};
class
vm
{
uint32_t m_pc=0;
int32_t m_saved_value;
inst_code m_inst_codes[80];
operation m_operations[8];
bool m_condition;
bool m_is_exited=false;
public:
vm(std::initializer_list<inst_code> ls, std::initializer_list<operation> opls) noexcept
{
inst_code* p = m_inst_codes;
for(auto& icode: ls)
{
*p++ = icode;
}
operation* pp = m_operations;
for(auto& op: opls)
{
*pp++ = op;
}
}
bool is_exited() const noexcept{return m_is_exited;}
uint32_t get_pc() const noexcept{return m_pc;}
void step() noexcept
{
auto& inst = m_inst_codes[m_pc++];
switch(inst.get_opcode())
{
case(opcode::eval_dump):
m_operations[inst.get_imm()].evaluate();
break;
case(opcode::eval_save):
m_saved_value = m_operations[inst.get_imm()].evaluate();
break;
case(opcode::eval_zero):
m_condition = (m_operations[inst.get_imm()].evaluate() == 0);
break;
case(opcode::jump):
m_pc += inst.get_imm();
break;
case(opcode::jump_by_condition):
if(m_condition)
{
m_pc += inst.get_imm();
}
break;
case(opcode::exi):
m_is_exited = true;
break;
}
}
};
}
int
main(int argc, char** argv)
{
using namespace test;
bool pr = (argc > 1);
int i;
test::vm vm({
inst_code(opcode::eval_save,0),
inst_code(opcode::eval_zero,1),
inst_code(opcode::jump_by_condition,2),
inst_code(opcode::eval_dump,2),
inst_code(opcode::jump,-4),
inst_code(opcode::exi,0),
},{
operation{operato::st,&i,0},
operation{operato::lt,&i,0xFFFFFF},
operation{operato::add,&i,1},
}
);
while(!vm.is_exited())
{
if(pr){printf("%8d",vm.get_pc());}
vm.step();
if(pr){printf(" %d\n",i);}
}
return 0;
}
I2luY2x1ZGU8Y3N0ZGxpYj4KI2luY2x1ZGU8Y3N0ZGludD4KI2luY2x1ZGU8Y3N0ZGRlZj4KI2luY2x1ZGU8Y3N0ZGlvPgojaW5jbHVkZTxpbml0aWFsaXplcl9saXN0PgoKCgpuYW1lc3BhY2UgdGVzdHsKCgoKCnN0cnVjdCBvcGVyYXRpb247CgoKY2xhc3MKb3BlcmFuZAp7CiAgZW51bSBjbGFzcyBraW5kewogICAgaW50ZWdlciwKICAgIHJlZmVyZW5jZSwKICAgIG9wZXJhdGlvbiwKICB9IG1fa2luZDsKCgogIGludCAgIG1faTsKICBpbnQqICBtX2lwOwogIGNvbnN0IG9wZXJhdGlvbiogIG1fbzsKCnB1YmxpYzoKICBvcGVyYW5kKCkgbm9leGNlcHR7fQogIG9wZXJhbmQoaW50ICAgaSkgbm9leGNlcHQ6IG1fa2luZChraW5kOjppbnRlZ2VyKSwgbV9pKGkpe30KICBvcGVyYW5kKGludCogIGlwKSBub2V4Y2VwdDogbV9raW5kKGtpbmQ6OnJlZmVyZW5jZSksIG1faXAoaXApe30KICBvcGVyYW5kKGNvbnN0IG9wZXJhdGlvbiYgIG8pIG5vZXhjZXB0OiBtX2tpbmQoa2luZDo6b3BlcmF0aW9uKSwgbV9vKCZvKXt9CgogIGludCYgIGdldCgpIGNvbnN0IG5vZXhjZXB0e3JldHVybiAqbV9pcDt9CgogIGludCAgZXZhbHVhdGUoKSBjb25zdCBub2V4Y2VwdDsKCn07CgoKZW51bSBjbGFzcwpvcGVyYXRvCnsKICBzdCwKICBhZGQsCiAgbHQsCgp9OwoKCnN0cnVjdApvcGVyYXRpb24KewogIG9wZXJhdG8gIG9wOwoKICBvcGVyYW5kICBvMTsKICBvcGVyYW5kICBvMjsKCiAgaW50ICBldmFsdWF0ZSgpIGNvbnN0IG5vZXhjZXB0CiAgewogICAgICBzd2l0Y2gob3ApCiAgICAgIHsKICAgIGNhc2Uob3BlcmF0bzo6c3QpOgogICAgICAgIHJldHVybiBvMS5nZXQoKSA9IG8yLmV2YWx1YXRlKCk7CiAgICBjYXNlKG9wZXJhdG86OmFkZCk6CiAgICAgICAgcmV0dXJuIG8xLmdldCgpICs9IG8yLmV2YWx1YXRlKCk7CiAgICBjYXNlKG9wZXJhdG86Omx0KToKICAgICAgICByZXR1cm4gKG8xLmV2YWx1YXRlKCkgPCBvMi5ldmFsdWF0ZSgpKT8gMTowOwogICAgICB9CiAgfQoKfTsKCgppbnQKb3BlcmFuZDo6CmV2YWx1YXRlKCkgY29uc3Qgbm9leGNlcHQKewogIHJldHVybiAobV9raW5kID09IGtpbmQ6OmludGVnZXIgICk/IG1faQogICAgICAgIDoobV9raW5kID09IGtpbmQ6OnJlZmVyZW5jZSk/ICptX2lwCiAgICAgICAgOm1fby0+ZXZhbHVhdGUoKTsKfQoKCmVudW0gY2xhc3MKb3Bjb2RlCnsKICBldmFsX2R1bXAsCiAgZXZhbF9zYXZlLAogIGV2YWxfemVybywKICBqdW1wLAogIGp1bXBfYnlfY29uZGl0aW9uLAoKICBleGksCn07CgoKc3RydWN0Cmluc3RfY29kZQp7CiAgdWludDMyX3QgIG1fZGF0YT0wOwoKcHVibGljOgogIGNvbnN0ZXhwciBpbnN0X2NvZGUoKSBub2V4Y2VwdHt9CiAgY29uc3RleHByIGluc3RfY29kZShvcGNvZGUgIG9wLCBpbnQxNl90ICB2KSBub2V4Y2VwdDogbV9kYXRhKChzdGF0aWNfY2FzdDxpbnQ+KG9wKTw8MTYpfCh2JjB4RkZGRikpe30KCiAgY29uc3RleHByIG9wY29kZSAgZ2V0X29wY29kZSgpIGNvbnN0IG5vZXhjZXB0e3JldHVybiBzdGF0aWNfY2FzdDxvcGNvZGU+KG1fZGF0YT4+MTYpO30KCiAgY29uc3RleHByIGludDE2X3QgIGdldF9pbW0oKSBjb25zdCBub2V4Y2VwdHtyZXR1cm4gKG1fZGF0YSYweEZGRkYpO30KCn07CgoKY2xhc3MKdm0KewogIHVpbnQzMl90ICBtX3BjPTA7CgogIGludDMyX3QgIG1fc2F2ZWRfdmFsdWU7CgogIGluc3RfY29kZSAgbV9pbnN0X2NvZGVzWzgwXTsKCiAgb3BlcmF0aW9uICBtX29wZXJhdGlvbnNbOF07CgogIGJvb2wgIG1fY29uZGl0aW9uOwoKICBib29sICBtX2lzX2V4aXRlZD1mYWxzZTsKCnB1YmxpYzoKICB2bShzdGQ6OmluaXRpYWxpemVyX2xpc3Q8aW5zdF9jb2RlPiAgbHMsIHN0ZDo6aW5pdGlhbGl6ZXJfbGlzdDxvcGVyYXRpb24+ICBvcGxzKSBub2V4Y2VwdAogIHsKICAgIGluc3RfY29kZSogIHAgPSBtX2luc3RfY29kZXM7CgogICAgICBmb3IoYXV0byYgIGljb2RlOiBscykKICAgICAgewogICAgICAgICpwKysgPSBpY29kZTsKICAgICAgfQoKCiAgICBvcGVyYXRpb24qICBwcCA9IG1fb3BlcmF0aW9uczsKCiAgICAgIGZvcihhdXRvJiAgb3A6IG9wbHMpCiAgICAgIHsKICAgICAgICAqcHArKyA9IG9wOwogICAgICB9CiAgfQoKICBib29sICBpc19leGl0ZWQoKSBjb25zdCBub2V4Y2VwdHtyZXR1cm4gbV9pc19leGl0ZWQ7fQoKICB1aW50MzJfdCAgZ2V0X3BjKCkgY29uc3Qgbm9leGNlcHR7cmV0dXJuIG1fcGM7fQoKICB2b2lkICBzdGVwKCkgbm9leGNlcHQKICB7CiAgICBhdXRvJiAgaW5zdCA9IG1faW5zdF9jb2Rlc1ttX3BjKytdOwoKICAgICAgc3dpdGNoKGluc3QuZ2V0X29wY29kZSgpKQogICAgICB7CiAgICBjYXNlKG9wY29kZTo6ZXZhbF9kdW1wKToKICAgICAgICBtX29wZXJhdGlvbnNbaW5zdC5nZXRfaW1tKCldLmV2YWx1YXRlKCk7CiAgICAgICAgYnJlYWs7CiAgICBjYXNlKG9wY29kZTo6ZXZhbF9zYXZlKToKICAgICAgICBtX3NhdmVkX3ZhbHVlID0gbV9vcGVyYXRpb25zW2luc3QuZ2V0X2ltbSgpXS5ldmFsdWF0ZSgpOwogICAgICAgIGJyZWFrOwogICAgY2FzZShvcGNvZGU6OmV2YWxfemVybyk6CiAgICAgICAgbV9jb25kaXRpb24gPSAobV9vcGVyYXRpb25zW2luc3QuZ2V0X2ltbSgpXS5ldmFsdWF0ZSgpID09IDApOwogICAgICAgIGJyZWFrOwogICAgY2FzZShvcGNvZGU6Omp1bXApOgogICAgICAgIG1fcGMgKz0gaW5zdC5nZXRfaW1tKCk7CiAgICAgICAgYnJlYWs7CiAgICBjYXNlKG9wY29kZTo6anVtcF9ieV9jb25kaXRpb24pOgogICAgICAgICAgaWYobV9jb25kaXRpb24pCiAgICAgICAgICB7CiAgICAgICAgICAgIG1fcGMgKz0gaW5zdC5nZXRfaW1tKCk7CiAgICAgICAgICB9CiAgICAgICAgYnJlYWs7CiAgICBjYXNlKG9wY29kZTo6ZXhpKToKICAgICAgICBtX2lzX2V4aXRlZCA9IHRydWU7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICB9Cgp9OwoKCgp9CgoKaW50Cm1haW4oaW50ICBhcmdjLCBjaGFyKiogIGFyZ3YpCnsKICB1c2luZyBuYW1lc3BhY2UgdGVzdDsKCiAgYm9vbCAgcHIgPSAoYXJnYyA+IDEpOwoKICBpbnQgIGk7CgogIHRlc3Q6OnZtICB2bSh7CiAgICBpbnN0X2NvZGUob3Bjb2RlOjpldmFsX3NhdmUsMCksCiAgICBpbnN0X2NvZGUob3Bjb2RlOjpldmFsX3plcm8sMSksCiAgICBpbnN0X2NvZGUob3Bjb2RlOjpqdW1wX2J5X2NvbmRpdGlvbiwyKSwKICAgIGluc3RfY29kZShvcGNvZGU6OmV2YWxfZHVtcCwyKSwKICAgIGluc3RfY29kZShvcGNvZGU6Omp1bXAsLTQpLAogICAgaW5zdF9jb2RlKG9wY29kZTo6ZXhpLDApLAogIH0sewogICAgb3BlcmF0aW9ue29wZXJhdG86OnN0LCZpLDB9LAogICAgb3BlcmF0aW9ue29wZXJhdG86Omx0LCZpLDB4RkZGRkZGfSwKICAgIG9wZXJhdGlvbntvcGVyYXRvOjphZGQsJmksMX0sCiAgfQogICk7CgogICAgd2hpbGUoIXZtLmlzX2V4aXRlZCgpKQogICAgewppZihwcil7cHJpbnRmKCIlOGQiLHZtLmdldF9wYygpKTt9CiAgICAgIHZtLnN0ZXAoKTsKCmlmKHByKXtwcmludGYoIiAlZFxuIixpKTt9CiAgICB9CgoKCiAgcmV0dXJuIDA7Cn0KCgoK