• 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 
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