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