fork download
  1. #include<cstdlib>
  2. #include<cstdint>
  3. #include<cstddef>
  4. #include<cstdio>
  5. #include<initializer_list>
  6.  
  7.  
  8.  
  9. namespace test{
  10.  
  11.  
  12.  
  13.  
  14. struct operation;
  15.  
  16.  
  17. class
  18. operand
  19. {
  20. enum class kind{
  21. integer,
  22. reference,
  23. operation,
  24. } m_kind;
  25.  
  26.  
  27. int m_i;
  28. int* m_ip;
  29. const operation* m_o;
  30.  
  31. public:
  32. operand() noexcept{}
  33. operand(int i) noexcept: m_kind(kind::integer), m_i(i){}
  34. operand(int* ip) noexcept: m_kind(kind::reference), m_ip(ip){}
  35. operand(const operation& o) noexcept: m_kind(kind::operation), m_o(&o){}
  36.  
  37. int& get() const noexcept{return *m_ip;}
  38.  
  39. int evaluate() const noexcept;
  40.  
  41. };
  42.  
  43.  
  44. enum class
  45. operato
  46. {
  47. st,
  48. add,
  49. lt,
  50.  
  51. };
  52.  
  53.  
  54. struct
  55. operation
  56. {
  57. operato op;
  58.  
  59. operand o1;
  60. operand o2;
  61.  
  62. int evaluate() const noexcept
  63. {
  64. switch(op)
  65. {
  66. case(operato::st):
  67. return o1.get() = o2.evaluate();
  68. case(operato::add):
  69. return o1.get() += o2.evaluate();
  70. case(operato::lt):
  71. return (o1.evaluate() < o2.evaluate())? 1:0;
  72. }
  73. }
  74.  
  75. };
  76.  
  77.  
  78. int
  79. operand::
  80. evaluate() const noexcept
  81. {
  82. return (m_kind == kind::integer )? m_i
  83. :(m_kind == kind::reference)? *m_ip
  84. :m_o->evaluate();
  85. }
  86.  
  87.  
  88. enum class
  89. opcode
  90. {
  91. eval_dump,
  92. eval_save,
  93. eval_zero,
  94. jump,
  95. jump_by_condition,
  96.  
  97. exi,
  98. };
  99.  
  100.  
  101. struct
  102. inst_code
  103. {
  104. uint32_t m_data=0;
  105.  
  106. public:
  107. constexpr inst_code() noexcept{}
  108. constexpr inst_code(opcode op, int16_t v) noexcept: m_data((static_cast<int>(op)<<16)|(v&0xFFFF)){}
  109.  
  110. constexpr opcode get_opcode() const noexcept{return static_cast<opcode>(m_data>>16);}
  111.  
  112. constexpr int16_t get_imm() const noexcept{return (m_data&0xFFFF);}
  113.  
  114. };
  115.  
  116.  
  117. class
  118. vm
  119. {
  120. uint32_t m_pc=0;
  121.  
  122. int32_t m_saved_value;
  123.  
  124. inst_code m_inst_codes[80];
  125.  
  126. operation m_operations[8];
  127.  
  128. bool m_condition;
  129.  
  130. bool m_is_exited=false;
  131.  
  132. public:
  133. vm(std::initializer_list<inst_code> ls, std::initializer_list<operation> opls) noexcept
  134. {
  135. inst_code* p = m_inst_codes;
  136.  
  137. for(auto& icode: ls)
  138. {
  139. *p++ = icode;
  140. }
  141.  
  142.  
  143. operation* pp = m_operations;
  144.  
  145. for(auto& op: opls)
  146. {
  147. *pp++ = op;
  148. }
  149. }
  150.  
  151. bool is_exited() const noexcept{return m_is_exited;}
  152.  
  153. uint32_t get_pc() const noexcept{return m_pc;}
  154.  
  155. void step() noexcept
  156. {
  157. auto& inst = m_inst_codes[m_pc++];
  158.  
  159. switch(inst.get_opcode())
  160. {
  161. case(opcode::eval_dump):
  162. m_operations[inst.get_imm()].evaluate();
  163. break;
  164. case(opcode::eval_save):
  165. m_saved_value = m_operations[inst.get_imm()].evaluate();
  166. break;
  167. case(opcode::eval_zero):
  168. m_condition = (m_operations[inst.get_imm()].evaluate() == 0);
  169. break;
  170. case(opcode::jump):
  171. m_pc += inst.get_imm();
  172. break;
  173. case(opcode::jump_by_condition):
  174. if(m_condition)
  175. {
  176. m_pc += inst.get_imm();
  177. }
  178. break;
  179. case(opcode::exi):
  180. m_is_exited = true;
  181. break;
  182. }
  183. }
  184.  
  185. };
  186.  
  187.  
  188.  
  189. }
  190.  
  191.  
  192. int
  193. main(int argc, char** argv)
  194. {
  195. using namespace test;
  196.  
  197. bool pr = (argc > 1);
  198.  
  199. int i;
  200.  
  201. test::vm vm({
  202. inst_code(opcode::eval_save,0),
  203. inst_code(opcode::eval_zero,1),
  204. inst_code(opcode::jump_by_condition,2),
  205. inst_code(opcode::eval_dump,2),
  206. inst_code(opcode::jump,-4),
  207. inst_code(opcode::exi,0),
  208. },{
  209. operation{operato::st,&i,0},
  210. operation{operato::lt,&i,0xFFFFFF},
  211. operation{operato::add,&i,1},
  212. }
  213. );
  214.  
  215. while(!vm.is_exited())
  216. {
  217. if(pr){printf("%8d",vm.get_pc());}
  218. vm.step();
  219.  
  220. if(pr){printf(" %d\n",i);}
  221. }
  222.  
  223.  
  224.  
  225. return 0;
  226. }
  227.  
  228.  
  229.  
  230.  
Success #stdin #stdout 0.64s 4556KB
stdin
Standard input is empty
stdout
Standard output is empty