Orocos Real-Time Toolkit
2.5.0
|
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