- Main Page
- Classes
- Files

# node_impl.cpp

Go to the documentation of this file.

    00001 #include <iomanip>
    00002 #include <iterator>
    00003 #include <ostream>
    00004 #include <sstream>
    00005
    00006 #include "calc_error.hpp"
    00007 #include "node.hpp"
    00008 #include "node_impl.hpp"
    00009 #include "variables.hpp"
    00010
    00011 node_impl::node_impl()
    00012 : refcount_(1)
    00013 {}
    00014
    00015 node_impl::~node_impl()
    00016 {}
    00017
    00018 void node_impl::print(std::ostream& stream, int indent)
    00019 const
    00020 {
    00021   print_node(stream, indent);
    00022 }
    00023
    00024 number node_impl::evaluate()
    00025 const
    00026 {
    00027   return evaluate_node();
    00028 }
    00029
    00030 std::string node_impl::to_string()
    00031 const
    00032 {
    00033   return evaluate_string();
    00034 }
    00035
    00036 void node_impl::add_ref()
    00037 {
    00038   ++refcount_;
    00039 }
    00040
    00041 identifier_list const& node_impl::get_parameters()
    00042 const
    00043 {
    00044   return evaluate_parameters();
    00045 }
    00046
    00047 void node_impl::del_ref()
    00048 {
    00049   --refcount_;
    00050   if (refcount_ == 0)
    00051     delete this;
    00052 }
    00053
    00054 std::string node_impl::evaluate_string()
    00055 const
    00056 {
    00057   std::ostringstream stream;
    00058   stream << evaluate();
    00059   return stream.str();
    00060 }
    00061
    00062 identifier_list const& node_impl::evaluate_parameters()
    00063 const
    00064 {
    00065   static identifier_list const empty;
    00066   return empty;
    00067 }
    00068
    00069 void node_impl::save(std::ostream& stream)
    00070 const
    00071 {
    00072   save_node(stream);
    00073 }
    00074
    00075 /* Factory function to create node_impl objects from a saved library file. */
    00076 node_impl* node_impl::read_node(std::istream& stream)
    00077 {
    00078   std::string type;
    00079   if (not (stream >> type))
    00080     return 0;
    00081   if (type == "void")
    00082     return new node_void(stream);
    00083   if (type == "number")
    00084     return new node_number(stream);
    00085   if (type == "identifier")
    00086     return new node_identifier(stream);
    00087   if (type == "function")
    00088     return new node_function(stream);
    00089   if (type == "call")
    00090     return new node_function_call(stream);
    00091   if (type == "negate")
    00092     return new node_negate(stream);
    00093   if (type == "add")
    00094     return new node_add(stream);
    00095   if (type == "subtract")
    00096     return new node_subtract(stream);
    00097   if (type == "multiply")
    00098     return new node_multiply(stream);
    00099   if (type == "divide")
    00100     return new node_divide(stream);
    00101
    00102   throw calc_error("unknown node type: " + type);
    00103 }
    00104
    00105 node_void::node_void()
    00106 : node_impl()
    00107 {}
    00108
    00109 node_void::node_void(std::istream&)
    00110 : node_impl()
    00111 {}
    00112
    00113 void node_void::print_node(std::ostream& stream, int indent)
    00114 const
    00115 {
    00116   stream << std::setw(indent) << "" << "void\n";
    00117 }
    00118
    00119 number node_void::evaluate_node()
    00120 const
    00121 {
    00122   return number();
    00123 }
    00124
    00125 std::string node_void::evaluate_string()
    00126 const
    00127 {
    00128   return std::string();
    00129 }
    00130
    00131 void node_void::save_node(std::ostream& stream)
    00132 const
    00133 {
    00134   stream << "void\n";
    00135 }
    00136
    00137 node_number::node_number(number value)
    00138 : node_impl(), value_(value)
    00139 {}
    00140
    00141 node_number::node_number(std::istream& stream)
    00142 : node_impl(), value_(stream)
    00143 {}
    00144
    00145 number node_number::value()
    00146 const
    00147 {
    00148   return value_;
    00149 }
    00150
    00151 void node_number::print_node(std::ostream& stream, int indent)
    00152 const
    00153 {
    00154   stream << std::setw(indent) << "" << value() << '\n';
    00155 }
    00156
    00157 number node_number::evaluate_node()
    00158 const
    00159 {
    00160   return value();
    00161 }
    00162
    00163 void node_number::save_node(std::ostream& stream)
    00164 const
    00165 {
    00166   stream << "number ";
    00167   value().save(stream);
    00168   stream << '\n';
    00169 }
    00170
    00171
    00172 node_identifier::node_identifier(std::string const& name)
    00173 : node_impl(), name_(name)
    00174 {}
    00175
    00176 node_identifier::node_identifier(std::istream& stream)
    00177 : node_impl()
    00178 {
    00179   if (not (stream >> name_))
    00180     throw calc_error("malformed library file, cannot read identifier");
    00181 }
    00182
    00183 std::string const& node_identifier::name()
    00184 const
    00185 {
    00186   return name_;
    00187 }
    00188
    00189 void node_identifier::print_node(std::ostream& stream, int indent)
    00190 const
    00191 {
    00192   stream << std::setw(indent) << "" << "identifier " << name() << '\n';
    00193 }
    00194
    00195 number node_identifier::evaluate_node()
    00196 const
    00197 {
    00198   return get_variable(name()).evaluate();
    00199 }
    00200
    00201 std::string node_identifier::evaluate_string()
    00202 const
    00203 {
    00204   return name();
    00205 }
    00206
    00207 void node_identifier::save_node(std::ostream& stream)
    00208 const
    00209 {
    00210   stream << "identifier " << name() << '\n';
    00211 }
    00212
    00213
    00214 node_function::node_function(identifier_list const& parameters, node definition)
    00215 : node_impl(), parameters_(parameters), definition_(definition)
    00216 {}
    00217
    00218 node_function::node_function(std::istream& stream)
    00219 : node_impl()
    00220 {
    00221   std::size_t size;
    00222   if (not (stream >> size))
    00223     throw calc_error("malformed library file, cannot read function");
    00224   parameters_.reserve(size);
    00225   while (size-- != 0) {
    00226     std::string parameter;
    00227     if (not (stream >> parameter))
    00228       throw calc_error("malformed library file, cannot read function parameter");
    00229     parameters_.push_back(parameter);
    00230   }
    00231   definition_ = node(stream);
    00232 }
    00233
    00234 identifier_list const& node_function::parameters()
    00235 const
    00236 {
    00237   return parameters_;
    00238 }
    00239
    00240 node node_function::definition()
    00241 const
    00242 {
    00243   return definition_;
    00244 }
    00245
    00246 void print_identifier_list(std::ostream& stream, identifier_list const& identifiers)
    00247 {
    00248   stream << '(';
    00249   char const* sep = "";
    00250   for (identifier_list::const_iterator id(identifiers.begin()); id != identifiers.end(); ++id) {
    00251     stream << sep << *id;
    00252     sep = ", ";
    00253   }
    00254   stream << ')';
    00255 }
    00256
    00257 void node_function::print_node(std::ostream& stream, int indent)
    00258 const
    00259 {
    00260   stream << std::setw(indent) << "" << "fun\n";
    00261   print_identifier_list(stream, parameters());
    00262   stream << '=';
    00263   definition().print(stream, indent + 2);
    00264 }
    00265
    00266 number node_function::evaluate_node()
    00267 const
    00268 {
    00269   return definition().evaluate();
    00270 }
    00271
    00272 identifier_list const& node_function::evaluate_parameters()
    00273 const
    00274 {
    00275   return parameters();
    00276 }
    00277
    00278 void node_function::save_node(std::ostream& stream)
    00279 const
    00280 {
    00281   stream << "function " << parameters().size() << ' ';
    00282   std::copy(parameters().begin(), parameters().end(), std::ostream_iterator<std::string>(stream, " "));
    00283   definition().save(stream);
    00284 }
    00285
    00286
    00287 node_function_call::node_function_call(std::string const& name, node_list const& arguments)
    00288 : node_impl(), name_(name), arguments_(arguments)
    00289 {}
    00290
    00291 node_function_call::node_function_call(std::istream& stream)
    00292 : node_impl()
    00293 {
    00294   std::string name;
    00295   if (not (stream >> name_))
    00296     throw calc_error("malformed library file, cannot read function call name");
    00297   std::size_t size;
    00298   if (not (stream >> size))
    00299     throw calc_error("malformed library file, cannot read function call");
    00300   arguments_.reserve(size);
    00301   while (size-- != 0) {
    00302     arguments_.push_back(node(stream));
    00303   }
    00304 }
    00305
    00306 std::string node_function_call::name()
    00307 const
    00308 {
    00309   return name_;
    00310 }
    00311
    00312 node_list const& node_function_call::arguments()
    00313 const
    00314 {
    00315   return arguments_;
    00316 }
    00317
    00318 void node_function_call::print_node(std::ostream& stream, int indent)
    00319 const
    00320 {
    00321   stream << std::setw(indent) << "" << name() << "(\n";
    00322   for (node_list::const_iterator first(arguments().begin()), arg(first); arg != arguments().end(); ++arg) {
    00323     stream << std::setw(indent+1) << "" << "arg " << std::distance(first, arg) << ": ";
    00324     arg->print(stream, indent + 2);
    00325   }
    00326   stream << std::setw(indent) << "" << ")\n";
    00327 }
    00328
    00329 number node_function_call::evaluate_node()
    00330 const
    00331 {
    00332   // Create a local symbol table, assigning all the node values to the parameters.
    00333   node function = get_function(name());
    00334   identifier_list const& parameters( function.get_parameters() );
    00335   if (parameters.size() != arguments().size())
    00336     throw function_error(name(), parameters.size(), arguments().size());
    00337   else
    00338   {
    00339     // Create a local symbol table by assigning the arguments to the function parameters.
    00340     symbol_table locals;
    00341     identifier_list::const_iterator parm(parameters.begin());
    00342     for (node_list::const_iterator arg(arguments().begin()); arg != arguments().end(); ++arg, ++parm) {
    00343       locals.insert(std::make_pair(*parm, *arg));
    00344     }
    00345     set_symbol_table syms(locals);
    00346     return function.evaluate();
    00347   }
    00348 }
    00349
    00350 void node_function_call::save_node(std::ostream& stream)
    00351 const
    00352 {
    00353   stream << "call " << name() << ' ' << arguments().size() << ' ';
    00354   for (node_list::const_iterator arg(arguments().begin()); arg != arguments().end(); ++arg)
    00355     arg->save(stream);
    00356 }
    00357
    00358
    00359 node_unary::node_unary(node operand)
    00360 : node_impl(), operand_(operand)
    00361 {}
    00362
    00363 node_unary::node_unary(std::istream& stream)
    00364 : node_impl(), operand_(stream)
    00365 {}
    00366
    00367 node node_unary::operand()
    00368 const
    00369 {
    00370   return operand_;
    00371 }
    00372
    00373 number node_unary::evaluate_operand()
    00374 const
    00375 {
    00376   return operand().evaluate();
    00377 }
    00378
    00379 node_binary::node_binary(node left, node right)
    00380 : left_(left), right_(right)
    00381 {}
    00382
    00383 node_binary::node_binary(std::istream& stream)
    00384 : node_impl(), left_(stream), right_(stream)
    00385 {}
    00386
    00387 node node_binary::left()
    00388 const
    00389 {
    00390   return left_;
    00391 }
    00392
    00393 node node_binary::right()
    00394 const
    00395 {
    00396   return right_;
    00397 }
    00398
    00399 number node_binary::evaluate_left()
    00400 const
    00401 {
    00402   return left().evaluate();
    00403 }
    00404
    00405 number node_binary::evaluate_right()
    00406 const
    00407 {
    00408   return right().evaluate();
    00409 }
    00410
    00411
    00412 node_negate::node_negate(node operand)
    00413 : node_unary(operand)
    00414 {}
    00415
    00416 node_negate::node_negate(std::istream& stream)
    00417 : node_unary(stream)
    00418 {}
    00419
    00420 void node_negate::print_node(std::ostream& stream, int indent)
    00421 const
    00422 {
    00423   stream << std::setw(indent) << "" << "-\n";
    00424   operand().print(stream, indent + 2);
    00425 }
    00426
    00427 number node_negate::evaluate_node()
    00428 const
    00429 {
    00430   return -evaluate_operand();
    00431 }
    00432
    00433 void node_negate::save_node(std::ostream& stream)
    00434 const
    00435 {
    00436   stream << "negate ";
    00437   operand().save(stream);
    00438 }
    00439
    00440
    00441
    00442 node_add::node_add(node left, node right)
    00443 : node_binary(left, right)
    00444 {}
    00445
    00446 node_add::node_add(std::istream& stream)
    00447 : node_binary(stream)
    00448 {}
    00449
    00450 void node_add::print_node(std::ostream& stream, int indent)
    00451 const
    00452 {
    00453   stream << std::setw(indent) << "" << "+\n";
    00454   left().print(stream, indent + 2);
    00455   right().print(stream, indent + 2);
    00456 }
    00457
    00458 number node_add::evaluate_node()
    00459 const
    00460 {
    00461   return evaluate_left() + evaluate_right();
    00462 }
    00463
    00464 void node_add::save_node(std::ostream& stream)
    00465 const
    00466 {
    00467   stream << "add ";
    00468   left().save(stream);
    00469   right().save(stream);
    00470 }
    00471
    00472
    00473 node_subtract::node_subtract(node left, node right)
    00474 : node_binary(left, right)
    00475 {}
    00476
    00477 node_subtract::node_subtract(std::istream& stream)
    00478 : node_binary(stream)
    00479 {}
    00480
    00481 void node_subtract::print_node(std::ostream& stream, int indent)
    00482 const
    00483 {
    00484   stream << std::setw(indent) << "" << "-\n";
    00485   left().print(stream, indent + 2);
    00486   right().print(stream, indent + 2);
    00487 }
    00488
    00489 number node_subtract::evaluate_node()
    00490 const
    00491 {
    00492   return evaluate_left() - evaluate_right();
    00493 }
    00494
    00495 void node_subtract::save_node(std::ostream& stream)
    00496 const
    00497 {
    00498   stream << "subtract ";
    00499   left().save(stream);
    00500   right().save(stream);
    00501 }
    00502
    00503
    00504 node_multiply::node_multiply(node left, node right)
    00505 : node_binary(left, right)
    00506 {}
    00507
    00508 node_multiply::node_multiply(std::istream& stream)
    00509 : node_binary(stream)
    00510 {}
    00511
    00512 void node_multiply::print_node(std::ostream& stream, int indent)
    00513 const
    00514 {
    00515   stream << std::setw(indent) << "" << "*\n";
    00516   left().print(stream, indent + 2);
    00517   right().print(stream, indent + 2);
    00518 }
    00519
    00520 number node_multiply::evaluate_node()
    00521 const
    00522 {
    00523   return evaluate_left() * evaluate_right();
    00524 }
    00525
    00526 void node_multiply::save_node(std::ostream& stream)
    00527 const
    00528 {
    00529   stream << "multiply ";
    00530   left().save(stream);
    00531   right().save(stream);
    00532 }
    00533
    00534
    00535 node_divide::node_divide(node left, node right)
    00536 : node_binary(left, right)
    00537 {}
    00538
    00539 node_divide::node_divide(std::istream& stream)
    00540 : node_binary(stream)
    00541 {}
    00542
    00543 void node_divide::print_node(std::ostream& stream, int indent)
    00544 const
    00545 {
    00546   stream << std::setw(indent) << "" << "/\n";
    00547   left().print(stream, indent + 2);
    00548   right().print(stream, indent + 2);
    00549 }
    00550
    00551 number node_divide::evaluate_node()
    00552 const
    00553 {
    00554   return evaluate_left() / evaluate_right();
    00555 }
    00556
    00557 void node_divide::save_node(std::ostream& stream)
    00558 const
    00559 {
    00560   stream << "divide ";
    00561   left().save(stream);
    00562   right().save(stream);
    00563 }