vm.cpp 4.7 KB

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