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