StatementProcessor.cpp

00001 /***************************************************************************
00002   tag: Peter Soetens  Mon Jun 26 13:25:57 CEST 2006  StatementProcessor.cxx 
00003 
00004                         StatementProcessor.cxx -  description
00005                            -------------------
00006     begin                : Mon June 26 2006
00007     copyright            : (C) 2006 Peter Soetens
00008     email                : peter.soetens@fmtc.be
00009  
00010  ***************************************************************************
00011  *   This library is free software; you can redistribute it and/or         *
00012  *   modify it under the terms of the GNU General Public                   *
00013  *   License as published by the Free Software Foundation;                 *
00014  *   version 2 of the License.                                             *
00015  *                                                                         *
00016  *   As a special exception, you may use this file as part of a free       *
00017  *   software library without restriction.  Specifically, if other files   *
00018  *   instantiate templates or use macros or inline functions from this     *
00019  *   file, or you compile this file and link it with other files to        *
00020  *   produce an executable, this file does not by itself cause the         *
00021  *   resulting executable to be covered by the GNU General Public          *
00022  *   License.  This exception does not however invalidate any other        *
00023  *   reasons why the executable file might be covered by the GNU General   *
00024  *   Public License.                                                       *
00025  *                                                                         *
00026  *   This library is distributed in the hope that it will be useful,       *
00027  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00028  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00029  *   Lesser General Public License for more details.                       *
00030  *                                                                         *
00031  *   You should have received a copy of the GNU General Public             *
00032  *   License along with this library; if not, write to the Free Software   *
00033  *   Foundation, Inc., 59 Temple Place,                                    *
00034  *   Suite 330, Boston, MA  02111-1307  USA                                *
00035  *                                                                         *
00036  ***************************************************************************/
00037  
00038  
00039 
00040 #include "StatementProcessor.hpp"
00041 #include "Parser.hpp"
00042 #include "parse_exception.hpp"
00043 
00044 #include "TaskContext.hpp"
00045 #include "DispatchInterface.hpp"
00046 #include "ConditionInterface.hpp"
00047 #include <MultiVector.hpp>
00048 #include <TypeStream.hpp>
00049 #include "Logger.hpp"
00050 
00051 #include <vector>
00052 #include <boost/tuple/tuple.hpp>
00053 #include <iostream>
00054 
00055 
00056 using namespace boost;
00057 
00058 namespace RTT
00059 {
00060     using namespace detail;
00061     struct StatementProcessor::D
00062     {
00063         TaskContext* tc;
00064         std::vector<boost::tuple<int, DispatchInterface::shared_ptr, ConditionInterface*, std::string> > comms;
00065         int seq;
00066         D() : seq(0) {}
00067 
00068         void checkFinished()
00069         {
00070             std::vector<boost::tuple<int, DispatchInterface::shared_ptr, ConditionInterface*, std::string> >::iterator it = comms.begin();
00071             while( it != comms.end() )
00072                 {
00073                     if ( it->get<1>()->valid() && it->get<2>()->evaluate() == true ) {
00074                         Logger::log() <<Logger::Info<<"Command ("<<it->get<0>()<<") '"<< it->get<3>() << "' is done." <<Logger::endl;
00075                         comms.erase(it);
00076                         it = comms.begin(); // reset !
00077                         continue;
00078                     }
00079                     if ( it->get<1>()->accepted() == false ) {
00080                         Logger::log() <<Logger::Error<<"Command ("<<it->get<0>()<<") '"<< it->get<3>() << "' was not accepted." <<Logger::endl;
00081                         comms.erase(it);
00082                         it = comms.begin(); // reset !
00083                         continue;
00084                     } 
00085                     if ( it->get<1>()->executed() == true ) {
00086                         if ( it->get<1>()->valid() == false ) {
00087                             Logger::log() <<Logger::Error<<"Command ("<<it->get<0>()<<") '"<< it->get<3>() << "' was executed but rejected." <<Logger::endl;
00088                             comms.erase(it);
00089                             it = comms.begin(); // reset !
00090                             continue;
00091                         }
00092                         Logger::log() <<Logger::Info<<"Command ("<<it->get<0>()<<") '"<< it->get<3>() << "' is busy." <<Logger::endl;
00093                     }
00094                     ++it;
00095                 }
00096         }
00097 
00098         DispatchInterface::shared_ptr getCommand(int cnr)
00099         {
00100             std::vector<boost::tuple<int, DispatchInterface::shared_ptr, ConditionInterface*, std::string> >::iterator it = comms.begin();
00101             while( it != comms.end() )
00102                 if ( it->get<0>() == cnr )
00103                     return it->get<1>();
00104             return DispatchInterface::shared_ptr();
00105         }
00106 
00107         int add(DispatchInterface* command, ConditionInterface* cond, std::string code)
00108         {
00109             comms.push_back( boost::tuple<int, DispatchInterface::shared_ptr, ConditionInterface*,std::string>(seq, DispatchInterface::shared_ptr(command), cond, code) );
00110             Logger::log() <<Logger::Info<<"Executing Command ("<<seq<<") '"<< code << "'..." <<Logger::endl;
00111             command->dispatch();
00112             ++seq;
00113             return seq -1;
00114         }
00115 
00116         void printResult( DataSourceBase* ds, bool recurse) { 
00117             std::string prompt(" = ");
00118             // setup prompt :
00119             Logger::log() << Logger::Info <<prompt;
00120             doPrint( ds, recurse );
00121             Logger::log() << Logger::endl;
00122         }
00123 
00124         void doPrint( DataSourceBase* ds, bool recurse) {
00125             // this is needed for ds's that rely on initialision.
00126             // e.g. eval true once or time measurements.
00127             // becomes only really handy for 'watches' (todo).
00128             ds->reset();
00133             // this method can print some primitive DataSource<>'s.
00134             DataSource<bool>* dsb = DataSource<bool>::narrow(ds);
00135             if (dsb) {
00136                 Logger::log() << dsb->get();
00137                 return;
00138             }
00139             DataSource<int>* dsi = DataSource<int>::narrow(ds);
00140             if (dsi) {
00141                 Logger::log() << dsi->get() ;
00142                 return;
00143             }
00144 #if 0
00145             // does not work yet with CORBA layer.
00146             DataSource<long>* dsl = DataSource<long>::narrow(ds);
00147             if (dsl) {
00148                 Logger::log() << dsl->get() ;
00149                 return;
00150             }
00151 #endif
00152             DataSource<unsigned int>* dsui = DataSource<unsigned int>::narrow(ds);
00153             if (dsui) {
00154                 Logger::log() << dsui->get() ;
00155                 return;
00156             }
00157             DataSource<std::string>* dss = DataSource<std::string>::narrow(ds);
00158             if (dss) {
00159                 Logger::log() <<'"'<< dss->get() << '"' ;
00160                 return;
00161             }
00162             DataSource<const std::string&>* dscs = DataSource<const std::string&>::narrow(ds);
00163             if (dscs) {
00164                 Logger::log() <<'"'<< dscs->get() <<'"' ;
00165                 return;
00166             }
00167             DataSource<std::vector<double> >* dsvval = DataSource< std::vector<double> >::narrow(ds);
00168             if (dsvval) {
00169                 Logger::log()  << dsvval->get() ;
00170                 return;
00171             }
00172             DataSource<const std::vector<double>& >* dsv = DataSource<const std::vector<double>& >::narrow(ds);
00173             if (dsv) {
00174                 Logger::log()  << dsv->get() ;
00175                 return;
00176             }
00177             DataSource< Double6D >* ds6d = DataSource<Double6D>::narrow(ds);
00178             if (ds6d) {
00179                 Logger::log()  << ds6d->get() ;
00180                 return;
00181             }
00182             DataSource<double>* dsd = DataSource<double>::narrow(ds);
00183             if (dsd) {
00184                 Logger::log() << dsd->get() ;
00185                 return;
00186             }
00187             DataSource<char>* dsc = DataSource<char>::narrow(ds);
00188             if (dsc) {
00189                 Logger::log() <<'\''<< dsc->get()<<'\'' ;
00190                 return;
00191             }
00192 
00193             DataSource<PropertyBag>* dspbag = DataSource<PropertyBag>::narrow(ds);
00194             if (dspbag) {
00195                 PropertyBag bag( dspbag->get() );
00196                 if (!recurse) {
00197                     int siz = bag.getProperties().size();
00198                     Logger::log()  << siz <<" Properties";
00199                 } else {
00200                     if ( ! bag.empty() ) {
00201                         Logger::log()  <<Logger::nl;
00202                         for( PropertyBag::iterator it= bag.getProperties().begin(); it!=bag.getProperties().end(); ++it) {
00203                             Logger::log()  <<(*it)->getType()<<" "<< (*it)->getName();
00204                             DataSourceBase::shared_ptr propds = (*it)->getDataSource();
00205                             this->printResult( propds.get(), false );
00206                             Logger::log()  <<" ("<<(*it)->getDescription()<<')' << Logger::nl;
00207                         }
00208                     } else {
00209                         Logger::log()  <<"(empty PropertyBag)";
00210                     }
00211                 }
00212                 return;
00213             }
00214 
00215             // Leave void  as last since any DS is convertible to void !
00216             DataSource<void>* dsvd = DataSource<void>::narrow(ds);
00217             if (dsvd) {
00218                 dsvd->get();
00219                 Logger::log() << "(void)" ;
00220                 return;
00221             }
00222 
00223             if (ds) {
00224                 ds->evaluate();
00225                 Logger::log() << "( result type '"+ds->getType()+"' not known to TaskBrowser )" ;
00226             }
00227         
00228         }
00229 
00230     };
00231 
00232 
00233     StatementProcessor::StatementProcessor(TaskContext* tc)
00234         : d ( new D() )
00235     {
00236         d->tc = tc;
00237     }
00238 
00239     StatementProcessor::~StatementProcessor() {
00240         delete d;
00241     }
00242     
00243     void StatementProcessor::checkFinished() {
00244         Logger::In in("StatementProcessor");
00245         d->checkFinished();
00246     }
00247     
00248     DispatchInterface::shared_ptr StatementProcessor::getCommand(int cnr) {
00249         Logger::In in("StatementProcessor");
00250         return d->getCommand(cnr);
00251     }
00252     
00253     int StatementProcessor::execute(const std::string& comm)
00254     {
00255         Logger::In in("StatementProcessor");
00256 
00257         d->checkFinished();
00258 
00259         TaskContext* taskcontext = d->tc;
00260 
00261         // Minor hack : also check if it was an attribute of current TC, for example, 
00262         // if both the object and attribute with that name exist. the if
00263         // statement after this one would return and not give the expr parser
00264         // time to evaluate 'comm'. 
00265         if ( taskcontext->attributes()->getValue( comm ) ) {
00266                 d->printResult( taskcontext->attributes()->getValue( comm )->getDataSource().get(), true );
00267                 return 0;
00268         }
00269                     
00270         Parser _parser;
00271         std::pair< CommandInterface*, ConditionInterface*> comcon;
00272         DispatchInterface* command;
00273         ConditionInterface* condition;
00274 
00275         Logger::log() <<Logger::Debug << "Trying ValueChange...";
00276         try {
00277             // Check if it was a method or datasource :
00278             DataSourceBase::shared_ptr ds = _parser.parseValueChange( comm, taskcontext );
00279             // methods and DS'es are processed immediately.
00280             if ( ds.get() != 0 ) {
00281                 Logger::log() << "ok" << Logger::endl;
00282                 d->printResult( ds.get(), false );
00283                 return 0; // done here
00284             } else
00285                 Logger::log() <<Logger::Debug << "no"<<Logger::endl;
00286         } catch ( fatal_semantic_parse_exception& pe ) { // incorr args, ...
00287             // way to fatal,  must be reported immediately
00288             Logger::log() << Logger::Debug << "fatal_semantic_parse_exception: ";
00289             Logger::log() << Logger::Error << pe.what() <<Logger::nl;
00290             return -1;
00291         } catch ( syntactic_parse_exception& pe ) { // wrong content after = sign etc..
00292             // syntactic errors must be reported immediately
00293             Logger::log() << Logger::Error << "syntactic_parse_exception: ";
00294             Logger::log() << Logger::Error << pe.what() <<Logger::nl;
00295             return -1;
00296         } catch ( parse_exception_parser_fail &pe )
00297             {
00298                 // ignore, try next parser
00299                 Logger::log() << Logger::Debug << "Ignoring ValueChange exception :"<<Logger::nl;
00300                 Logger::log() << Logger::Debug << pe.what() <<Logger::nl;
00301         } catch ( parse_exception& pe ) { 
00302             // syntactic errors must be reported immediately
00303             Logger::log() << Logger::Error << "parse_exception :";
00304             Logger::log() << Logger::Error << pe.what() <<Logger::nl;
00305             return -1;
00306         }
00307         Logger::log() << Logger::Debug << "Trying Expression..."<<Logger::nl;
00308         try {
00309             // Check if it was a method or datasource :
00310             DataSourceBase::shared_ptr ds = _parser.parseExpression( comm, taskcontext );
00311             // methods and DS'es are processed immediately.
00312             if ( ds.get() != 0 ) {
00313                 d->printResult( ds.get(), true );
00314                 return 0; // done here
00315             } else
00316                 Logger::log() << Logger::Error << "returned zero !"<<Logger::nl;
00317         } catch ( syntactic_parse_exception& pe ) { // missing brace etc
00318             // syntactic errors must be reported immediately
00319             Logger::log() << Logger::Error << "syntactic_parse_exception :";
00320             Logger::log() << Logger::Error << pe.what() <<Logger::nl;
00321             return -1;
00322         } catch ( fatal_semantic_parse_exception& pe ) { // incorr args, ...
00323             // way to fatal,  must be reported immediately
00324             Logger::log() << Logger::Error << "fatal_semantic_parse_exception :";
00325             Logger::log() << Logger::Error << pe.what() <<Logger::nl;
00326             return -1;
00327         } catch ( parse_exception_parser_fail &pe ) {
00328                 // ignore, try next parser
00329                 Logger::log() << Logger::Debug << "Ignoring Expression exception :"<<Logger::nl;
00330                 Logger::log() << Logger::Debug << pe.what() <<Logger::nl;
00331         } catch ( parse_exception& pe ) { 
00332             // ignore, try next parser
00333             Logger::log() << Logger::Debug << "Ignoring Expression parse_exception :"<<Logger::nl;
00334             Logger::log() << Logger::Debug << pe.what() <<Logger::nl;
00335         }
00336         Logger::log() << Logger::Debug << "Trying Command...";
00337         try {
00338             comcon = _parser.parseCommand( comm, taskcontext, true ); // create a dispatch command.
00339             assert( dynamic_cast<DispatchInterface*>(comcon.first) );
00340             command = dynamic_cast<DispatchInterface*>(comcon.first);
00341             condition = comcon.second;
00342         } catch ( parse_exception& pe ) {
00343             Logger::log() << Logger::Debug << "CommandParser parse_exception :"<<Logger::nl;
00344             Logger::log() << Logger::Error << pe.what() <<Logger::nl;
00345             return -1;
00346         } catch (...) {
00347             Logger::log() << Logger::Error << "Illegal Input."<<Logger::nl;
00348             return -1;
00349         }
00350                 
00351         if ( command == 0 ) { // this should not be reached
00352             Logger::log() << Logger::Error << "Uncaught : Illegal command."<<Logger::nl;
00353             return -1;
00354         }
00355 
00356         return d->add( command, condition, comm);
00357     }
00358     
00359 }
00360 

Generated on Tue Mar 25 17:41:50 2008 for OrocosReal-TimeToolkit by  doxygen 1.5.3