• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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