vm.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. /*=============================================================================
  2. Copyright (c) 2001-2011 Joel de Guzman
  3. Distributed under the Boost Software License, Version 1.0. (See accompanying
  4. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. =============================================================================*/
  6. #include "vm.hpp"
  7. #include <boost/assert.hpp>
  8. #if defined(_MSC_VER)
  9. # pragma warning(disable: 4800) // forcing value to bool 'true' or 'false'
  10. // (performance warning)
  11. #endif
  12. namespace client
  13. {
  14. int vmachine::execute(
  15. std::vector<int> const& code
  16. , std::vector<int>::const_iterator pc
  17. , std::vector<int>::iterator frame_ptr
  18. )
  19. {
  20. std::vector<int>::iterator stack_ptr = frame_ptr;
  21. while (pc != code.end())
  22. {
  23. BOOST_ASSERT(pc != code.end());
  24. switch (*pc++)
  25. {
  26. case op_neg:
  27. stack_ptr[-1] = -stack_ptr[-1];
  28. break;
  29. case op_not:
  30. stack_ptr[-1] = !bool(stack_ptr[-1]);
  31. break;
  32. case op_add:
  33. --stack_ptr;
  34. stack_ptr[-1] += stack_ptr[0];
  35. break;
  36. case op_sub:
  37. --stack_ptr;
  38. stack_ptr[-1] -= stack_ptr[0];
  39. break;
  40. case op_mul:
  41. --stack_ptr;
  42. stack_ptr[-1] *= stack_ptr[0];
  43. break;
  44. case op_div:
  45. --stack_ptr;
  46. stack_ptr[-1] /= stack_ptr[0];
  47. break;
  48. case op_eq:
  49. --stack_ptr;
  50. stack_ptr[-1] = bool(stack_ptr[-1] == stack_ptr[0]);
  51. break;
  52. case op_neq:
  53. --stack_ptr;
  54. stack_ptr[-1] = bool(stack_ptr[-1] != stack_ptr[0]);
  55. break;
  56. case op_lt:
  57. --stack_ptr;
  58. stack_ptr[-1] = bool(stack_ptr[-1] < stack_ptr[0]);
  59. break;
  60. case op_lte:
  61. --stack_ptr;
  62. stack_ptr[-1] = bool(stack_ptr[-1] <= stack_ptr[0]);
  63. break;
  64. case op_gt:
  65. --stack_ptr;
  66. stack_ptr[-1] = bool(stack_ptr[-1] > stack_ptr[0]);
  67. break;
  68. case op_gte:
  69. --stack_ptr;
  70. stack_ptr[-1] = bool(stack_ptr[-1] >= stack_ptr[0]);
  71. break;
  72. case op_and:
  73. --stack_ptr;
  74. stack_ptr[-1] = bool(stack_ptr[-1]) && bool(stack_ptr[0]);
  75. break;
  76. case op_or:
  77. --stack_ptr;
  78. stack_ptr[-1] = bool(stack_ptr[-1]) || bool(stack_ptr[0]);
  79. break;
  80. case op_load:
  81. *stack_ptr++ = frame_ptr[*pc++];
  82. break;
  83. case op_store:
  84. --stack_ptr;
  85. frame_ptr[*pc++] = stack_ptr[0];
  86. break;
  87. case op_int:
  88. *stack_ptr++ = *pc++;
  89. break;
  90. case op_true:
  91. *stack_ptr++ = true;
  92. break;
  93. case op_false:
  94. *stack_ptr++ = false;
  95. break;
  96. case op_jump:
  97. pc += *pc;
  98. break;
  99. case op_jump_if:
  100. if (!bool(stack_ptr[-1]))
  101. pc += *pc;
  102. else
  103. ++pc;
  104. --stack_ptr;
  105. break;
  106. case op_stk_adj:
  107. stack_ptr = stack.begin() + *pc++;
  108. break;
  109. case op_call:
  110. {
  111. int nargs = *pc++;
  112. int jump = *pc++;
  113. // a function call is a recursive call to execute
  114. int r = execute(
  115. code
  116. , code.begin() + jump
  117. , stack_ptr - nargs
  118. );
  119. // cleanup after return from function
  120. stack_ptr[-nargs] = r; // get return value
  121. stack_ptr -= (nargs - 1); // the stack will now contain
  122. // the return value
  123. }
  124. break;
  125. case op_return:
  126. return stack_ptr[-1];
  127. }
  128. }
  129. return -1;
  130. }
  131. }