]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/spirit/example/x3/calc/calc9/compiler.cpp
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / boost / libs / spirit / example / x3 / calc / calc9 / compiler.cpp
CommitLineData
7c673cae
FG
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 "compiler.hpp"
8#include "vm.hpp"
7c673cae
FG
9#include <boost/variant/apply_visitor.hpp>
10#include <boost/assert.hpp>
11#include <boost/lexical_cast.hpp>
12#include <iostream>
13#include <set>
14#include <iostream>
15
16namespace client { namespace code_gen
17{
18 void program::op(int a)
19 {
20 code.push_back(a);
21 }
22
23 void program::op(int a, int b)
24 {
25 code.push_back(a);
26 code.push_back(b);
27 }
28
29 void program::op(int a, int b, int c)
30 {
31 code.push_back(a);
32 code.push_back(b);
33 code.push_back(c);
34 }
35
36 int const* program::find_var(std::string const& name) const
37 {
38 auto i = variables.find(name);
39 if (i == variables.end())
40 return 0;
41 return &i->second;
42 }
43
44 void program::add_var(std::string const& name)
45 {
46 std::size_t n = variables.size();
47 variables[name] = int(n);
48 }
49
50 void program::print_variables(std::vector<int> const& stack) const
51 {
52 for (auto const& p : variables)
53 {
54 std::cout << " " << p.first << ": " << stack[p.second] << std::endl;
55 }
56 }
57
58 void program::print_assembler() const
59 {
60 auto pc = code.begin();
61
62 std::vector<std::string> locals(variables.size());
63 typedef std::pair<std::string, int> pair;
64 for (pair const& p : variables)
65 {
66 locals[p.second] = p.first;
67 std::cout << "local "
68 << p.first << ", @" << p.second << std::endl;
69 }
70
71 std::map<std::size_t, std::string> lines;
72 std::set<std::size_t> jumps;
73
74 while (pc != code.end())
75 {
76 std::string line;
77 std::size_t address = pc - code.begin();
78
79 switch (*pc++)
80 {
81 case op_neg:
82 line += " op_neg";
83 break;
84
85 case op_not:
86 line += " op_not";
87 break;
88
89 case op_add:
90 line += " op_add";
91 break;
92
93 case op_sub:
94 line += " op_sub";
95 break;
96
97 case op_mul:
98 line += " op_mul";
99 break;
100
101 case op_div:
102 line += " op_div";
103 break;
104
105 case op_eq:
106 line += " op_eq";
107 break;
108
109 case op_neq:
110 line += " op_neq";
111 break;
112
113 case op_lt:
114 line += " op_lt";
115 break;
116
117 case op_lte:
118 line += " op_lte";
119 break;
120
121 case op_gt:
122 line += " op_gt";
123 break;
124
125 case op_gte:
126 line += " op_gte";
127 break;
128
129 case op_and:
130 line += " op_and";
131 break;
132
133 case op_or:
134 line += " op_or";
135 break;
136
137 case op_load:
138 line += " op_load ";
139 line += boost::lexical_cast<std::string>(locals[*pc++]);
140 break;
141
142 case op_store:
143 line += " op_store ";
144 line += boost::lexical_cast<std::string>(locals[*pc++]);
145 break;
146
147 case op_int:
148 line += " op_int ";
149 line += boost::lexical_cast<std::string>(*pc++);
150 break;
151
152 case op_true:
153 line += " op_true";
154 break;
155
156 case op_false:
157 line += " op_false";
158 break;
159
160 case op_jump:
161 {
162 line += " op_jump ";
163 std::size_t pos = (pc - code.begin()) + *pc++;
164 if (pos == code.size())
165 line += "end";
166 else
167 line += boost::lexical_cast<std::string>(pos);
168 jumps.insert(pos);
169 }
170 break;
171
172 case op_jump_if:
173 {
174 line += " op_jump_if ";
175 std::size_t pos = (pc - code.begin()) + *pc++;
176 if (pos == code.size())
177 line += "end";
178 else
179 line += boost::lexical_cast<std::string>(pos);
180 jumps.insert(pos);
181 }
182 break;
183
184 case op_stk_adj:
185 line += " op_stk_adj ";
186 line += boost::lexical_cast<std::string>(*pc++);
187 break;
188 }
189 lines[address] = line;
190 }
191
192 std::cout << "start:" << std::endl;
193 for (auto const& l : lines)
194 {
195 std::size_t pos = l.first;
196 if (jumps.find(pos) != jumps.end())
197 std::cout << pos << ':' << std::endl;
198 std::cout << l.second << std::endl;
199 }
200
201 std::cout << "end:" << std::endl;
202 }
203
204 bool compiler::operator()(unsigned int x) const
205 {
206 program.op(op_int, x);
207 return true;
208 }
209
210 bool compiler::operator()(bool x) const
211 {
212 program.op(x ? op_true : op_false);
213 return true;
214 }
215
216 bool compiler::operator()(ast::variable const& x) const
217 {
218 int const* p = program.find_var(x.name);
219 if (p == 0)
220 {
221 error_handler(x, "Undeclared variable: " + x.name);
222 return false;
223 }
224 program.op(op_load, *p);
225 return true;
226 }
227
228 bool compiler::operator()(ast::operation const& x) const
229 {
230 if (!boost::apply_visitor(*this, x.operand_))
231 return false;
232 switch (x.operator_)
233 {
234 case ast::op_plus: program.op(op_add); break;
235 case ast::op_minus: program.op(op_sub); break;
236 case ast::op_times: program.op(op_mul); break;
237 case ast::op_divide: program.op(op_div); break;
238
239 case ast::op_equal: program.op(op_eq); break;
240 case ast::op_not_equal: program.op(op_neq); break;
241 case ast::op_less: program.op(op_lt); break;
242 case ast::op_less_equal: program.op(op_lte); break;
243 case ast::op_greater: program.op(op_gt); break;
244 case ast::op_greater_equal: program.op(op_gte); break;
245
246 case ast::op_and: program.op(op_and); break;
247 case ast::op_or: program.op(op_or); break;
248 default: BOOST_ASSERT(0); return false;
249 }
250 return true;
251 }
252
253 bool compiler::operator()(ast::unary const& x) const
254 {
255 if (!boost::apply_visitor(*this, x.operand_))
256 return false;
257 switch (x.operator_)
258 {
259 case ast::op_negative: program.op(op_neg); break;
260 case ast::op_not: program.op(op_not); break;
261 case ast::op_positive: break;
262 default: BOOST_ASSERT(0); return false;
263 }
264 return true;
265 }
266
267 bool compiler::operator()(ast::expression const& x) const
268 {
269 if (!boost::apply_visitor(*this, x.first))
270 return false;
271 for (ast::operation const& oper : x.rest)
272 {
273 if (!(*this)(oper))
274 return false;
275 }
276 return true;
277 }
278
279 bool compiler::operator()(ast::assignment const& x) const
280 {
281 if (!(*this)(x.rhs))
282 return false;
283 int const* p = program.find_var(x.lhs.name);
284 if (p == 0)
285 {
286 error_handler(x.lhs, "Undeclared variable: " + x.lhs.name);
287 return false;
288 }
289 program.op(op_store, *p);
290 return true;
291 }
292
293 bool compiler::operator()(ast::variable_declaration const& x) const
294 {
295 int const* p = program.find_var(x.assign.lhs.name);
296 if (p != 0)
297 {
298 error_handler(x.assign.lhs, "Duplicate variable: " + x.assign.lhs.name);
299 return false;
300 }
301 bool r = (*this)(x.assign.rhs);
302 if (r) // don't add the variable if the RHS fails
303 {
304 program.add_var(x.assign.lhs.name);
305 program.op(op_store, *program.find_var(x.assign.lhs.name));
306 }
307 return r;
308 }
309
310 bool compiler::operator()(ast::statement const& x) const
311 {
312 return boost::apply_visitor(*this, x);
313 }
314
315 bool compiler::operator()(ast::statement_list const& x) const
316 {
317 for (auto const& s : x)
318 {
319 if (!(*this)(s))
320 return false;
321 }
322 return true;
323 }
324
325 bool compiler::operator()(ast::if_statement const& x) const
326 {
327 if (!(*this)(x.condition))
328 return false;
329 program.op(op_jump_if, 0); // we shall fill this (0) in later
330 std::size_t skip = program.size()-1; // mark its position
331 if (!(*this)(x.then))
332 return false;
333 program[skip] = int(program.size()-skip); // now we know where to jump to (after the if branch)
334
335 if (x.else_) // We got an alse
336 {
337 program[skip] += 2; // adjust for the "else" jump
338 program.op(op_jump, 0); // we shall fill this (0) in later
339 std::size_t exit = program.size()-1; // mark its position
340 if (!(*this)(*x.else_))
341 return false;
342 program[exit] = int(program.size()-exit); // now we know where to jump to (after the else branch)
343 }
344
345 return true;
346 }
347
348 bool compiler::operator()(ast::while_statement const& x) const
349 {
350 std::size_t loop = program.size(); // mark our position
351 if (!(*this)(x.condition))
352 return false;
353 program.op(op_jump_if, 0); // we shall fill this (0) in later
354 std::size_t exit = program.size()-1; // mark its position
355 if (!(*this)(x.body))
356 return false;
357 program.op(op_jump,
358 int(loop-1) - int(program.size())); // loop back
359 program[exit] = int(program.size()-exit); // now we know where to jump to (to exit the loop)
360 return true;
361 }
362
363 bool compiler::start(ast::statement_list const& x) const
364 {
365 program.clear();
366 // op_stk_adj 0 for now. we'll know how many variables we'll have later
367 program.op(op_stk_adj, 0);
368
369 if (!(*this)(x))
370 {
371 program.clear();
372 return false;
373 }
374 program[1] = int(program.nvars()); // now store the actual number of variables
375 return true;
376 }
377}}