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