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