vm.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  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 "config.hpp"
  7. #include "vm.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 (true)
  22. {
  23. switch (*pc++)
  24. {
  25. case op_neg:
  26. stack_ptr[-1] = -stack_ptr[-1];
  27. break;
  28. case op_not:
  29. stack_ptr[-1] = !bool(stack_ptr[-1]);
  30. break;
  31. case op_add:
  32. --stack_ptr;
  33. stack_ptr[-1] += stack_ptr[0];
  34. break;
  35. case op_sub:
  36. --stack_ptr;
  37. stack_ptr[-1] -= stack_ptr[0];
  38. break;
  39. case op_mul:
  40. --stack_ptr;
  41. stack_ptr[-1] *= stack_ptr[0];
  42. break;
  43. case op_div:
  44. --stack_ptr;
  45. stack_ptr[-1] /= stack_ptr[0];
  46. break;
  47. case op_eq:
  48. --stack_ptr;
  49. stack_ptr[-1] = bool(stack_ptr[-1] == stack_ptr[0]);
  50. break;
  51. case op_neq:
  52. --stack_ptr;
  53. stack_ptr[-1] = bool(stack_ptr[-1] != stack_ptr[0]);
  54. break;
  55. case op_lt:
  56. --stack_ptr;
  57. stack_ptr[-1] = bool(stack_ptr[-1] < stack_ptr[0]);
  58. break;
  59. case op_lte:
  60. --stack_ptr;
  61. stack_ptr[-1] = bool(stack_ptr[-1] <= stack_ptr[0]);
  62. break;
  63. case op_gt:
  64. --stack_ptr;
  65. stack_ptr[-1] = bool(stack_ptr[-1] > stack_ptr[0]);
  66. break;
  67. case op_gte:
  68. --stack_ptr;
  69. stack_ptr[-1] = bool(stack_ptr[-1] >= stack_ptr[0]);
  70. break;
  71. case op_and:
  72. --stack_ptr;
  73. stack_ptr[-1] = bool(stack_ptr[-1]) && bool(stack_ptr[0]);
  74. break;
  75. case op_or:
  76. --stack_ptr;
  77. stack_ptr[-1] = bool(stack_ptr[-1]) || bool(stack_ptr[0]);
  78. break;
  79. case op_load:
  80. *stack_ptr++ = frame_ptr[*pc++];
  81. break;
  82. case op_store:
  83. --stack_ptr;
  84. frame_ptr[*pc++] = stack_ptr[0];
  85. break;
  86. case op_int:
  87. *stack_ptr++ = *pc++;
  88. break;
  89. case op_true:
  90. *stack_ptr++ = true;
  91. break;
  92. case op_false:
  93. *stack_ptr++ = false;
  94. break;
  95. case op_jump:
  96. pc += *pc;
  97. break;
  98. case op_jump_if:
  99. if (!bool(stack_ptr[-1]))
  100. pc += *pc;
  101. else
  102. ++pc;
  103. --stack_ptr;
  104. break;
  105. case op_stk_adj:
  106. stack_ptr += *pc++;
  107. break;
  108. case op_call:
  109. {
  110. int nargs = *pc++;
  111. int jump = *pc++;
  112. // a function call is a recursive call to execute
  113. int r = execute(
  114. code
  115. , code.begin() + jump
  116. , stack_ptr - nargs
  117. );
  118. // cleanup after return from function
  119. stack_ptr[-nargs] = r; // get return value
  120. stack_ptr -= (nargs - 1); // the stack will now contain
  121. // the return value
  122. }
  123. break;
  124. case op_return:
  125. return stack_ptr[-1];
  126. }
  127. }
  128. }
  129. }