Orocos Real-Time Toolkit  2.5.0
FunctionFactory.cpp
00001 /***************************************************************************
00002   tag: Peter Soetens  Tue Dec 21 22:43:08 CET 2004  FunctionFactory.cxx
00003 
00004                         FunctionFactory.cxx -  description
00005                            -------------------
00006     begin                : Tue December 21 2004
00007     copyright            : (C) 2004 Peter Soetens
00008     email                : peter.soetens@mech.kuleuven.ac.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 #include "FunctionFactory.hpp"
00040 
00041 #include "../ExecutionEngine.hpp"
00042 #include "../internal/GlobalEngine.hpp"
00043 #include "CommandComposite.hpp"
00044 #include "CommandBinary.hpp"
00045 #include "CallFunction.hpp"
00046 #include "ConditionComposite.hpp"
00047 #include "TryCommand.hpp"
00048 #include <sstream>
00049 #include <map>
00050 #include <string>
00051 #include "../internal/mystd.hpp"
00052 #include <PropertyBag.hpp>
00053 #include <Property.hpp>
00054 #include "../Attribute.hpp"
00055 #include "parse_exception.hpp"
00056 #include "../internal/DataSourceCommand.hpp"
00057 #include "../FactoryExceptions.hpp"
00058 #include "../../Handle.hpp"
00059 
00060 
00061 namespace RTT {
00062     using namespace detail;
00063 
00064 
00065         FunctionFactory::FunctionFactory(ProgramInterfacePtr pi, ExecutionEngine* procs)
00066             : func(pi), proc(procs) {}
00067 
00068         std::string FunctionFactory::resultType() const {
00069             return func->getResult() ? func->getResult()->getDataSource()->getTypeName() : "void";
00070         }
00071 
00072         std::string FunctionFactory::getName() const {
00073             return func->getName();
00074         }
00075 
00076         std::string FunctionFactory::description() const {
00077             return "Orocos Program Script Function.";
00078         }
00079 
00080         std::vector< ArgumentDescription > FunctionFactory::getArgumentList() const
00081         {
00082             std::vector<AttributeBase*> origlist = func->getArguments();
00083             std::vector< ArgumentDescription > mlist;
00084             for ( std::vector<AttributeBase*>::const_iterator it = origlist.begin();
00085                   it != origlist.end(); ++it)
00086                 mlist.push_back( ArgumentDescription( "arg", "Function Argument", (*it)->getDataSource()->getType() ) );
00087             return mlist;
00088         }
00089 
00090         unsigned int FunctionFactory::arity( ) const
00091         {
00092             return func->getArguments().size();
00093         }
00094 
00095         unsigned int FunctionFactory::collectArity( ) const
00096         {
00097             return func->getResult() ? 1 : 0;
00098         }
00099 
00100         const types::TypeInfo* FunctionFactory::getArgumentType(unsigned int arg) const
00101         {
00102             if (arg == 0 ) {
00103                 if ( func->getResult() )
00104                     return func->getResult()->getDataSource()->getTypeInfo();
00105                 else
00106                     return DataSourceTypeInfo<void>::getTypeInfo();
00107             }
00108             std::vector<AttributeBase*> origlist = func->getArguments();
00109             if ( arg > origlist.size() )
00110                 return 0;
00111             return origlist[arg - 1]->getDataSource()->getTypeInfo();
00112         }
00113 
00114         const types::TypeInfo* FunctionFactory::getCollectType(unsigned int arg) const {
00115             if (arg == 1 && collectArity() )
00116                 return func->getResult()->getDataSource()->getTypeInfo();
00117             return 0;
00118         }
00119 
00120         DataSourceBase::shared_ptr FunctionFactory::produce(
00121                       const std::vector<DataSourceBase::shared_ptr>& args
00122                       , ExecutionEngine* caller
00123                       ) const {
00124 
00125             // check if correct number of args :
00126             boost::shared_ptr<ProgramInterface> orig = func;
00127             std::vector<AttributeBase*> origlist = orig->getArguments();
00128             if ( args.size() != origlist.size() )
00129                 throw wrong_number_of_args_exception( origlist.size(), args.size() );
00130 
00131             // make a semi-deep copy of the function :
00132             // copy the local variables, but clone() the remote datasources.
00133             std::map<const DataSourceBase*, DataSourceBase*> replacementdss;
00134             assert( orig );
00135             boost::shared_ptr<ProgramInterface> fcopy( orig->copy( replacementdss ) );
00136             assert( fcopy );
00137             // create commands that init all the args :
00138             CommandComposite* icom=  new CommandComposite();
00139 
00140             // get the correct pointers.
00141             origlist = fcopy->getArguments();
00142             std::vector<DataSourceBase::shared_ptr>::const_iterator dit = args.begin();
00143             std::vector<AttributeBase*>::const_iterator tit =  origlist.begin();
00144 #ifndef ORO_EMBEDDED
00145             try {
00146                 for (; dit != args.end(); ++dit, ++tit)
00147                     icom->add( (*tit)->getDataSource()->updateAction( dit->get() ) );
00148             }
00149             catch( const bad_assignment& ) {
00150                 delete icom;
00151                 int parnb = (dit - args.begin()) + 1;
00152                 throw wrong_types_of_args_exception(parnb, (*tit)->getDataSource()->getType() ,(*dit)->getType() );
00153             }
00154 #else
00155             for (; dit != args.end(); ++dit, ++tit) {
00156                 ActionInterface* ret = (*tit)->getDataSource()->updateAction( dit->get() );
00157                 if (ret)
00158                     icom->add( ret );
00159                 else {
00160                     delete icom;
00161                     return 0;
00162                 }
00163             }
00164 #endif
00165 
00166             // the args of the copy can now safely be removed (saves memory):
00167             //fcopy->clearArguments();
00168 
00169             // the command gets ownership of the new function :
00170             // this command is a DataSourceBase...
00171             AttributeBase* ar= fcopy->getResult();
00172             if (!caller)
00173                 caller = GlobalEngine::Instance();
00174             if (ar)
00175                 return ar->getDataSource()->getTypeInfo()->buildActionAlias( new CallFunction( icom, fcopy, proc, caller ), ar->getDataSource()).get();
00176             else // void case, returns result of runFunction (backwards compatibility).
00177                 return new DataSourceCommand( new CallFunction( icom, fcopy, proc, caller ) );
00178         }
00179 
00180         base::DataSourceBase::shared_ptr FunctionFactory::produceHandle() const {
00181             throw no_asynchronous_operation_exception("Send not yet implemented for scripting functions.");
00182             return 0;
00183         }
00184         base::DataSourceBase::shared_ptr FunctionFactory::produceSend(const std::vector<base::DataSourceBase::shared_ptr>& args, ExecutionEngine* caller
00185                                    ) const {
00186             throw no_asynchronous_operation_exception("Send not yet implemented for scripting functions.");
00187             return 0;
00188         }
00189         base::DataSourceBase::shared_ptr FunctionFactory::produceCollect(const std::vector<base::DataSourceBase::shared_ptr>& args, DataSource<bool>::shared_ptr blocking
00190                                    ) const {
00191             if (args.size() != 2) {
00192                 log(Error) <<"Invalid number of arguments. Script functions can only collect the return value." <<endlog();
00193             }
00194             throw no_asynchronous_operation_exception("Send not yet implemented for scripting functions.");
00195             return 0;
00196         }
00197 #ifdef ORO_SIGNALLING_OPERATIONS
00198         Handle FunctionFactory::produceSignal(base::ActionInterface* func, const std::vector<base::DataSourceBase::shared_ptr>& args
00199                                    ) const {
00200             throw no_asynchronous_operation_exception("Send not yet implemented for scripting functions.");
00201             return Handle();
00202         }
00203 #endif
00204 }
00205 
00206