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
15namespace client
16{
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 , pc: code.begin() + jump
145 , frame_ptr: 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

source code of boost/libs/spirit/example/qi/compiler_tutorial/calc8/vm.cpp