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