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