- 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 double 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 double node_void::evaluate_node()
    00120 const
    00121 {
    00122   return 0.0;
    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(double value)
    00138 : node_impl(), value_(value)
    00139 {}
    00140
    00141 node_number::node_number(std::istream& stream)
    00142 : node_impl()
    00143 {
    00144   if (not (stream >> value_))
    00145     throw calc_error("malformed library file, cannot read number");
    00146 }
    00147
    00148 double node_number::value()
    00149 const
    00150 {
    00151   return value_;
    00152 }
    00153
    00154 void node_number::print_node(std::ostream& stream, int indent)
    00155 const
    00156 {
    00157   stream << std::setw(indent) << "" << value() << '\n';
    00158 }
    00159
    00160 double node_number::evaluate_node()
    00161 const
    00162 {
    00163   return value();
    00164 }
    00165
    00166 void node_number::save_node(std::ostream& stream)
    00167 const
    00168 {
    00169   stream << "number " << value() << '\n';
    00170 }
    00171
    00172
    00173 node_identifier::node_identifier(std::string const& name)
    00174 : node_impl(), name_(name)
    00175 {}
    00176
    00177 node_identifier::node_identifier(std::istream& stream)
    00178 : node_impl()
    00179 {
    00180   if (not (stream >> name_))
    00181     throw calc_error("malformed library file, cannot read identifier");
    00182 }
    00183
    00184 std::string const& node_identifier::name()
    00185 const
    00186 {
    00187   return name_;
    00188 }
    00189
    00190 void node_identifier::print_node(std::ostream& stream, int indent)
    00191 const
    00192 {
    00193   stream << std::setw(indent) << "" << "identifier " << name() << '\n';
    00194 }
    00195
    00196 double node_identifier::evaluate_node()
    00197 const
    00198 {
    00199   return get_variable(name()).evaluate();
    00200 }
    00201
    00202 std::string node_identifier::evaluate_string()
    00203 const
    00204 {
    00205   return name();
    00206 }
    00207
    00208 void node_identifier::save_node(std::ostream& stream)
    00209 const
    00210 {
    00211   stream << "identifier " << name() << '\n';
    00212 }
    00213
    00214
    00215 node_function::node_function(identifier_list const& parameters, node definition)
    00216 : node_impl(), parameters_(parameters), definition_(definition)
    00217 {}
    00218
    00219 node_function::node_function(std::istream& stream)
    00220 : node_impl()
    00221 {
    00222   std::size_t size;
    00223   if (not (stream >> size))
    00224     throw calc_error("malformed library file, cannot read function");
    00225   parameters_.reserve(size);
    00226   while (size-- != 0) {
    00227     std::string parameter;
    00228     if (not (stream >> parameter))
    00229       throw calc_error("malformed library file, cannot read function parameter");
    00230     parameters_.push_back(parameter);
    00231   }
    00232   definition_ = node(stream);
    00233 }
    00234
    00235 identifier_list const& node_function::parameters()
    00236 const
    00237 {
    00238   return parameters_;
    00239 }
    00240
    00241 node node_function::definition()
    00242 const
    00243 {
    00244   return definition_;
    00245 }
    00246
    00247 void print_identifier_list(std::ostream& stream, identifier_list const& identifiers)
    00248 {
    00249   stream << '(';
    00250   char const* sep = "";
    00251   for (identifier_list::const_iterator id(identifiers.begin()); id != identifiers.end(); ++id) {
    00252     stream << sep << *id;
    00253     sep = ", ";
    00254   }
    00255   stream << ')';
    00256 }
    00257
    00258 void node_function::print_node(std::ostream& stream, int indent)
    00259 const
    00260 {
    00261   stream << std::setw(indent) << "" << "fun\n";
    00262   print_identifier_list(stream, parameters());
    00263   stream << '=';
    00264   definition().print(stream, indent + 2);
    00265 }
    00266
    00267 double node_function::evaluate_node()
    00268 const
    00269 {
    00270   return definition().evaluate();
    00271 }
    00272
    00273 identifier_list const& node_function::evaluate_parameters()
    00274 const
    00275 {
    00276   return parameters();
    00277 }
    00278
    00279 void node_function::save_node(std::ostream& stream)
    00280 const
    00281 {
    00282   stream << "function " << parameters().size() << ' ';
    00283   std::copy(parameters().begin(), parameters().end(), std::ostream_iterator<std::string>(stream, " "));
    00284   definition().save(stream);
    00285 }
    00286
    00287
    00288 node_function_call::node_function_call(std::string const& name, node_list const& arguments)
    00289 : node_impl(), name_(name), arguments_(arguments)
    00290 {}
    00291
    00292 node_function_call::node_function_call(std::istream& stream)
    00293 : node_impl()
    00294 {
    00295   std::string name;
    00296   if (not (stream >> name_))
    00297     throw calc_error("malformed library file, cannot read function call name");
    00298   std::size_t size;
    00299   if (not (stream >> size))
    00300     throw calc_error("malformed library file, cannot read function call");
    00301   arguments_.reserve(size);
    00302   while (size-- != 0) {
    00303     arguments_.push_back(node(stream));
    00304   }
    00305 }
    00306
    00307 std::string node_function_call::name()
    00308 const
    00309 {
    00310   return name_;
    00311 }
    00312
    00313 node_list const& node_function_call::arguments()
    00314 const
    00315 {
    00316   return arguments_;
    00317 }
    00318
    00319 void node_function_call::print_node(std::ostream& stream, int indent)
    00320 const
    00321 {
    00322   stream << std::setw(indent) << "" << name() << "(\n";
    00323   for (node_list::const_iterator first(arguments().begin()), arg(first); arg != arguments().end(); ++arg) {
    00324     stream << std::setw(indent+1) << "" << "arg " << std::distance(first, arg) << ": ";
    00325     arg->print(stream, indent + 2);
    00326   }
    00327   stream << std::setw(indent) << "" << ")\n";
    00328 }
    00329
    00330 double node_function_call::evaluate_node()
    00331 const
    00332 {
    00333   // Create a local symbol table, assigning all the node values to the parameters.
    00334   node function = get_function(name());
    00335   identifier_list const& parameters( function.get_parameters() );
    00336   if (parameters.size() != arguments().size())
    00337     throw function_error(name(), parameters.size(), arguments().size());
    00338   else
    00339   {
    00340     // Create a local symbol table by assigning the arguments to the function parameters.
    00341     symbol_table locals;
    00342     identifier_list::const_iterator parm(parameters.begin());
    00343     for (node_list::const_iterator arg(arguments().begin()); arg != arguments().end(); ++arg, ++parm) {
    00344       locals.insert(std::make_pair(*parm, *arg));
    00345     }
    00346     set_symbol_table syms(locals);
    00347     return function.evaluate();
    00348   }
    00349 }
    00350
    00351 void node_function_call::save_node(std::ostream& stream)
    00352 const
    00353 {
    00354   stream << "call " << name() << ' ' << arguments().size() << ' ';
    00355   for (node_list::const_iterator arg(arguments().begin()); arg != arguments().end(); ++arg)
    00356     arg->save(stream);
    00357 }
    00358
    00359
    00360 node_unary::node_unary(node operand)
    00361 : node_impl(), operand_(operand)
    00362 {}
    00363
    00364 node_unary::node_unary(std::istream& stream)
    00365 : node_impl(), operand_(stream)
    00366 {}
    00367
    00368 node node_unary::operand()
    00369 const
    00370 {
    00371   return operand_;
    00372 }
    00373
    00374 double node_unary::evaluate_operand()
    00375 const
    00376 {
    00377   return operand().evaluate();
    00378 }
    00379
    00380 node_binary::node_binary(node left, node right)
    00381 : left_(left), right_(right)
    00382 {}
    00383
    00384 node_binary::node_binary(std::istream& stream)
    00385 : node_impl(), left_(stream), right_(stream)
    00386 {}
    00387
    00388 node node_binary::left()
    00389 const
    00390 {
    00391   return left_;
    00392 }
    00393
    00394 node node_binary::right()
    00395 const
    00396 {
    00397   return right_;
    00398 }
    00399
    00400 double node_binary::evaluate_left()
    00401 const
    00402 {
    00403   return left().evaluate();
    00404 }
    00405
    00406 double node_binary::evaluate_right()
    00407 const
    00408 {
    00409   return right().evaluate();
    00410 }
    00411
    00412
    00413 node_negate::node_negate(node operand)
    00414 : node_unary(operand)
    00415 {}
    00416
    00417 node_negate::node_negate(std::istream& stream)
    00418 : node_unary(stream)
    00419 {}
    00420
    00421 void node_negate::print_node(std::ostream& stream, int indent)
    00422 const
    00423 {
    00424   stream << std::setw(indent) << "" << "-\n";
    00425   operand().print(stream, indent + 2);
    00426 }
    00427
    00428 double node_negate::evaluate_node()
    00429 const
    00430 {
    00431   return -evaluate_operand();
    00432 }
    00433
    00434 void node_negate::save_node(std::ostream& stream)
    00435 const
    00436 {
    00437   stream << "negate ";
    00438   operand().save(stream);
    00439 }
    00440
    00441
    00442
    00443 node_add::node_add(node left, node right)
    00444 : node_binary(left, right)
    00445 {}
    00446
    00447 node_add::node_add(std::istream& stream)
    00448 : node_binary(stream)
    00449 {}
    00450
    00451 void node_add::print_node(std::ostream& stream, int indent)
    00452 const
    00453 {
    00454   stream << std::setw(indent) << "" << "+\n";
    00455   left().print(stream, indent + 2);
    00456   right().print(stream, indent + 2);
    00457 }
    00458
    00459 double node_add::evaluate_node()
    00460 const
    00461 {
    00462   return evaluate_left() + evaluate_right();
    00463 }
    00464
    00465 void node_add::save_node(std::ostream& stream)
    00466 const
    00467 {
    00468   stream << "add ";
    00469   left().save(stream);
    00470   right().save(stream);
    00471 }
    00472
    00473
    00474 node_subtract::node_subtract(node left, node right)
    00475 : node_binary(left, right)
    00476 {}
    00477
    00478 node_subtract::node_subtract(std::istream& stream)
    00479 : node_binary(stream)
    00480 {}
    00481
    00482 void node_subtract::print_node(std::ostream& stream, int indent)
    00483 const
    00484 {
    00485   stream << std::setw(indent) << "" << "-\n";
    00486   left().print(stream, indent + 2);
    00487   right().print(stream, indent + 2);
    00488 }
    00489
    00490 double node_subtract::evaluate_node()
    00491 const
    00492 {
    00493   return evaluate_left() - evaluate_right();
    00494 }
    00495
    00496 void node_subtract::save_node(std::ostream& stream)
    00497 const
    00498 {
    00499   stream << "subtract ";
    00500   left().save(stream);
    00501   right().save(stream);
    00502 }
    00503
    00504
    00505 node_multiply::node_multiply(node left, node right)
    00506 : node_binary(left, right)
    00507 {}
    00508
    00509 node_multiply::node_multiply(std::istream& stream)
    00510 : node_binary(stream)
    00511 {}
    00512
    00513 void node_multiply::print_node(std::ostream& stream, int indent)
    00514 const
    00515 {
    00516   stream << std::setw(indent) << "" << "*\n";
    00517   left().print(stream, indent + 2);
    00518   right().print(stream, indent + 2);
    00519 }
    00520
    00521 double node_multiply::evaluate_node()
    00522 const
    00523 {
    00524   return evaluate_left() * evaluate_right();
    00525 }
    00526
    00527 void node_multiply::save_node(std::ostream& stream)
    00528 const
    00529 {
    00530   stream << "multiply ";
    00531   left().save(stream);
    00532   right().save(stream);
    00533 }
    00534
    00535
    00536 node_divide::node_divide(node left, node right)
    00537 : node_binary(left, right)
    00538 {}
    00539
    00540 node_divide::node_divide(std::istream& stream)
    00541 : node_binary(stream)
    00542 {}
    00543
    00544 void node_divide::print_node(std::ostream& stream, int indent)
    00545 const
    00546 {
    00547   stream << std::setw(indent) << "" << "/\n";
    00548   left().print(stream, indent + 2);
    00549   right().print(stream, indent + 2);
    00550 }
    00551
    00552 double node_divide::evaluate_node()
    00553 const
    00554 {
    00555   return evaluate_left() / evaluate_right();
    00556 }
    00557
    00558 void node_divide::save_node(std::ostream& stream)
    00559 const
    00560 {
    00561   stream << "divide ";
    00562   left().save(stream);
    00563   right().save(stream);
    00564 }