]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/compiler.cpp
1 /*=============================================================================
2 Copyright (c) 2001-2011 Joel de Guzman
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"
9 #include <boost/foreach.hpp>
10 #include <boost/variant/apply_visitor.hpp>
11 #include <boost/assert.hpp>
12 #include <boost/lexical_cast.hpp>
15 namespace client
{ namespace code_gen
17 void program::op(int a
)
22 void program::op(int a
, int b
)
28 void program::op(int a
, int b
, int c
)
35 int const* program::find_var(std::string
const& name
) const
37 std::map
<std::string
, int>::const_iterator i
= variables
.find(name
);
38 if (i
== variables
.end())
43 void program::add_var(std::string
const& name
)
45 std::size_t n
= variables
.size();
49 void program::print_variables(std::vector
<int> const& stack
) const
51 typedef std::pair
<std::string
, int> pair
;
52 BOOST_FOREACH(pair
const& p
, variables
)
54 std::cout
<< " " << p
.first
<< ": " << stack
[p
.second
] << std::endl
;
58 void program::print_assembler() const
60 std::vector
<int>::const_iterator pc
= code
.begin();
62 std::vector
<std::string
> locals(variables
.size());
63 typedef std::pair
<std::string
, int> pair
;
64 BOOST_FOREACH(pair
const& p
, variables
)
66 locals
[p
.second
] = p
.first
;
67 std::cout
<< " local "
68 << p
.first
<< ", @" << p
.second
<< std::endl
;
71 std::map
<std::size_t, std::string
> lines
;
72 std::set
<std::size_t> jumps
;
74 while (pc
!= code
.end())
77 std::size_t address
= pc
- code
.begin();
139 line
+= locals
[*pc
++];
143 line
+= " op_store ";
144 line
+= locals
[*pc
++];
149 line
+= boost::lexical_cast
<std::string
>(*pc
++);
163 std::size_t pos
= (pc
- code
.begin()) + *pc
++;
164 if (pos
== code
.size())
167 line
+= boost::lexical_cast
<std::string
>(pos
);
174 line
+= " op_jump_if ";
175 std::size_t pos
= (pc
- code
.begin()) + *pc
++;
176 if (pos
== code
.size())
179 line
+= boost::lexical_cast
<std::string
>(pos
);
185 line
+= " op_stk_adj ";
186 line
+= boost::lexical_cast
<std::string
>(*pc
++);
189 lines
[address
] = line
;
192 std::cout
<< "start:" << std::endl
;
193 typedef std::pair
<std::size_t, std::string
> line_info
;
194 BOOST_FOREACH(line_info
const& l
, lines
)
196 std::size_t pos
= l
.first
;
197 if (jumps
.find(pos
) != jumps
.end())
198 std::cout
<< pos
<< ':' << std::endl
;
199 std::cout
<< l
.second
<< std::endl
;
202 std::cout
<< "end:" << std::endl
;
205 bool compiler::operator()(unsigned int x
) const
207 program
.op(op_int
, x
);
211 bool compiler::operator()(bool x
) const
213 program
.op(x
? op_true
: op_false
);
217 bool compiler::operator()(ast::variable
const& x
) const
219 int const* p
= program
.find_var(x
.name
);
222 std::cout
<< x
.id
<< std::endl
;
223 error_handler(x
.id
, "Undeclared variable: " + x
.name
);
226 program
.op(op_load
, *p
);
230 bool compiler::operator()(ast::operation
const& x
) const
232 if (!boost::apply_visitor(*this, x
.operand_
))
236 case ast::op_plus
: program
.op(op_add
); break;
237 case ast::op_minus
: program
.op(op_sub
); break;
238 case ast::op_times
: program
.op(op_mul
); break;
239 case ast::op_divide
: program
.op(op_div
); break;
241 case ast::op_equal
: program
.op(op_eq
); break;
242 case ast::op_not_equal
: program
.op(op_neq
); break;
243 case ast::op_less
: program
.op(op_lt
); break;
244 case ast::op_less_equal
: program
.op(op_lte
); break;
245 case ast::op_greater
: program
.op(op_gt
); break;
246 case ast::op_greater_equal
: program
.op(op_gte
); break;
248 case ast::op_and
: program
.op(op_and
); break;
249 case ast::op_or
: program
.op(op_or
); break;
250 default: BOOST_ASSERT(0); return false;
255 bool compiler::operator()(ast::unary
const& x
) const
257 if (!boost::apply_visitor(*this, x
.operand_
))
261 case ast::op_negative
: program
.op(op_neg
); break;
262 case ast::op_not
: program
.op(op_not
); break;
263 case ast::op_positive
: break;
264 default: BOOST_ASSERT(0); return false;
269 bool compiler::operator()(ast::expression
const& x
) const
271 if (!boost::apply_visitor(*this, x
.first
))
273 BOOST_FOREACH(ast::operation
const& oper
, x
.rest
)
281 bool compiler::operator()(ast::assignment
const& x
) const
285 int const* p
= program
.find_var(x
.lhs
.name
);
288 std::cout
<< x
.lhs
.id
<< std::endl
;
289 error_handler(x
.lhs
.id
, "Undeclared variable: " + x
.lhs
.name
);
292 program
.op(op_store
, *p
);
296 bool compiler::operator()(ast::variable_declaration
const& x
) const
298 int const* p
= program
.find_var(x
.assign
.lhs
.name
);
301 std::cout
<< x
.assign
.lhs
.id
<< std::endl
;
302 error_handler(x
.assign
.lhs
.id
, "Duplicate variable: " + x
.assign
.lhs
.name
);
305 bool r
= (*this)(x
.assign
.rhs
);
306 if (r
) // don't add the variable if the RHS fails
308 program
.add_var(x
.assign
.lhs
.name
);
309 program
.op(op_store
, *program
.find_var(x
.assign
.lhs
.name
));
314 bool compiler::operator()(ast::statement
const& x
) const
316 return boost::apply_visitor(*this, x
);
319 bool compiler::operator()(ast::statement_list
const& x
) const
321 BOOST_FOREACH(ast::statement
const& s
, x
)
329 bool compiler::operator()(ast::if_statement
const& x
) const
331 if (!(*this)(x
.condition
))
333 program
.op(op_jump_if
, 0); // we shall fill this (0) in later
334 std::size_t skip
= program
.size()-1; // mark its position
335 if (!(*this)(x
.then
))
337 program
[skip
] = program
.size()-skip
; // now we know where to jump to (after the if branch)
339 if (x
.else_
) // We got an alse
341 program
[skip
] += 2; // adjust for the "else" jump
342 program
.op(op_jump
, 0); // we shall fill this (0) in later
343 std::size_t exit
= program
.size()-1; // mark its position
344 if (!(*this)(*x
.else_
))
346 program
[exit
] = program
.size()-exit
; // now we know where to jump to (after the else branch)
352 bool compiler::operator()(ast::while_statement
const& x
) const
354 std::size_t loop
= program
.size(); // mark our position
355 if (!(*this)(x
.condition
))
357 program
.op(op_jump_if
, 0); // we shall fill this (0) in later
358 std::size_t exit
= program
.size()-1; // mark its position
359 if (!(*this)(x
.body
))
362 int(loop
-1) - int(program
.size())); // loop back
363 program
[exit
] = program
.size()-exit
; // now we know where to jump to (to exit the loop)
367 bool compiler::start(ast::statement_list
const& x
) const
370 // op_stk_adj 0 for now. we'll know how many variables we'll have later
371 program
.op(op_stk_adj
, 0);
378 program
[1] = program
.nvars(); // now store the actual number of variables