]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/spirit/example/x3/calc/calc8/compiler.cpp
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / boost / libs / spirit / example / x3 / calc / calc8 / compiler.cpp
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"
9 #include <boost/variant/apply_visitor.hpp>
10 #include <boost/assert.hpp>
11 #include <iostream>
12
13 namespace client { namespace code_gen
14 {
15 void program::op(int a)
16 {
17 code.push_back(a);
18 }
19
20 void program::op(int a, int b)
21 {
22 code.push_back(a);
23 code.push_back(b);
24 }
25
26 void program::op(int a, int b, int c)
27 {
28 code.push_back(a);
29 code.push_back(b);
30 code.push_back(c);
31 }
32
33 int const* program::find_var(std::string const& name) const
34 {
35 auto i = variables.find(name);
36 if (i == variables.end())
37 return 0;
38 return &i->second;
39 }
40
41 void program::add_var(std::string const& name)
42 {
43 std::size_t n = variables.size();
44 variables[name] = int(n);
45 }
46
47 void program::print_variables(std::vector<int> const& stack) const
48 {
49 for (auto const& p : variables)
50 {
51 std::cout << " " << p.first << ": " << stack[p.second] << std::endl;
52 }
53 }
54
55 void program::print_assembler() const
56 {
57 auto pc = code.begin();
58
59 std::vector<std::string> locals(variables.size());
60 typedef std::pair<std::string, int> pair;
61 for (pair const& p : variables)
62 {
63 locals[p.second] = p.first;
64 std::cout << "local "
65 << p.first << ", @" << p.second << std::endl;
66 }
67
68 while (pc != code.end())
69 {
70 switch (*pc++)
71 {
72 case op_neg:
73 std::cout << "op_neg" << std::endl;
74 break;
75
76 case op_add:
77 std::cout << "op_add" << std::endl;
78 break;
79
80 case op_sub:
81 std::cout << "op_sub" << std::endl;
82 break;
83
84 case op_mul:
85 std::cout << "op_mul" << std::endl;
86 break;
87
88 case op_div:
89 std::cout << "op_div" << std::endl;
90 break;
91
92 case op_load:
93 std::cout << "op_load " << locals[*pc++] << std::endl;
94 break;
95
96 case op_store:
97 std::cout << "op_store " << locals[*pc++] << std::endl;
98 break;
99
100 case op_int:
101 std::cout << "op_int " << *pc++ << std::endl;
102 break;
103
104 case op_stk_adj:
105 std::cout << "op_stk_adj " << *pc++ << std::endl;
106 break;
107 }
108 }
109 }
110
111 bool compiler::operator()(unsigned int x) const
112 {
113 program.op(op_int, x);
114 return true;
115 }
116
117 bool compiler::operator()(ast::variable const& x) const
118 {
119 int const* p = program.find_var(x.name);
120 if (p == 0)
121 {
122 error_handler(x, "Undeclared variable: " + x.name);
123 return false;
124 }
125 program.op(op_load, *p);
126 return true;
127 }
128
129 bool compiler::operator()(ast::operation const& x) const
130 {
131 if (!boost::apply_visitor(*this, x.operand_))
132 return false;
133 switch (x.operator_)
134 {
135 case '+': program.op(op_add); break;
136 case '-': program.op(op_sub); break;
137 case '*': program.op(op_mul); break;
138 case '/': program.op(op_div); break;
139 default: BOOST_ASSERT(0); return false;
140 }
141 return true;
142 }
143
144 bool compiler::operator()(ast::signed_ const& x) const
145 {
146 if (!boost::apply_visitor(*this, x.operand_))
147 return false;
148 switch (x.sign)
149 {
150 case '-': program.op(op_neg); break;
151 case '+': break;
152 default: BOOST_ASSERT(0); return false;
153 }
154 return true;
155 }
156
157 bool compiler::operator()(ast::expression const& x) const
158 {
159 if (!boost::apply_visitor(*this, x.first))
160 return false;
161 for (ast::operation const& oper : x.rest)
162 {
163 if (!(*this)(oper))
164 return false;
165 }
166 return true;
167 }
168
169 bool compiler::operator()(ast::assignment const& x) const
170 {
171 if (!(*this)(x.rhs))
172 return false;
173 int const* p = program.find_var(x.lhs.name);
174 if (p == 0)
175 {
176 error_handler(x.lhs, "Undeclared variable: " + x.lhs.name);
177 return false;
178 }
179 program.op(op_store, *p);
180 return true;
181 }
182
183 bool compiler::operator()(ast::variable_declaration const& x) const
184 {
185 int const* p = program.find_var(x.assign.lhs.name);
186 if (p != 0)
187 {
188 error_handler(x.assign.lhs, "Duplicate variable: " + x.assign.lhs.name);
189 return false;
190 }
191 bool r = (*this)(x.assign.rhs);
192 if (r) // don't add the variable if the RHS fails
193 {
194 program.add_var(x.assign.lhs.name);
195 program.op(op_store, *program.find_var(x.assign.lhs.name));
196 }
197 return r;
198 }
199
200 bool compiler::operator()(ast::statement_list const& x) const
201 {
202 program.clear();
203
204 // op_stk_adj 0 for now. we'll know how many variables we'll have later
205 program.op(op_stk_adj, 0);
206 for (ast::statement const& s : x)
207 {
208 if (!boost::apply_visitor(*this, s))
209 {
210 program.clear();
211 return false;
212 }
213 }
214 program[1] = int(program.nvars()); // now store the actual number of variables
215 return true;
216 }
217 }}