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
10namespace client
11{
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 , pc: code.begin() + jump
140 , frame_ptr: 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

source code of boost/libs/spirit/example/x3/calc/calc9/vm.cpp