IScript.h

00001 /***************************************************************************
00002  *                                                                         *
00003  *   (c) Art Tevs, MPI Informatik Saarbruecken                             *
00004  *       mailto: <tevs@mpi-sb.mpg.de>                                      *
00005  *                                                                         *
00006  *   This program is free software; you can redistribute it and/or modify  *
00007  *   it under the terms of the GNU General Public License as published by  *
00008  *   the Free Software Foundation; either version 2 of the License, or     *
00009  *   (at your option) any later version.                                   *
00010  *                                                                         *
00011  ***************************************************************************/
00012 
00013 
00014 #ifndef _NR_SCRIPT_INTERFACE_RESOURCE__H_
00015 #define _NR_SCRIPT_INTERFACE_RESOURCE__H_
00016 
00017 
00018 //----------------------------------------------------------------------------------
00019 // Includes
00020 //----------------------------------------------------------------------------------
00021 #include "Prerequisities.h"
00022 #include "Resource.h"
00023 #include "ITask.h"
00024 
00025 /*!
00026  * \defgroup script Engine Scripting
00027  *
00028  * Scripting is our form of data driven design of our engine. Scripts
00029  * are also resources that are loaded through specified loader. Scripts are
00030  * used to program the engine from the outside of the source code. You are
00031  * able to program the engine in the runtime by executing the scripts through
00032  * a console provided by the engine. To understand what the scripts are good for
00033  * use appropriate literature from the internet.
00034  *
00035  * Our engine is designed to be very expandable and generic, so we are not use
00036  * specific kind of script language. nrEngine does only provide an interface
00037  * for a script classes that are implemented by plugins. The main idea of such
00038  * an interface is to create a binding between the script language and the engine.
00039  *
00040  * The plugins classes have to know how to bind the specific script language with
00041  * the script interface of the engine. The console will acquire a script object to
00042  * be used for the console scripting. This script object is provided by the plugins
00043  * so it uses that language which is implemented in the plugin.
00044  *
00045  * If there no plugins providing a scripting language so the default one is used.
00046  * The default scripting language does not support anything except of some function calls.
00047  * This very simple languge can be used to load another script language or
00048  * to setup some properties of the engine.
00049  *
00050  * Because there is thousands of scripting languages outside and they can be bounded
00051  * on different ways we do not provide any bounding routine. If you using any scripting
00052  * language in your application, than you have to bind your code with the script code by your
00053  * self. Mostly this is done through metaprogramming or through preproccessing
00054  * routines on the scripting language. Therefor providing such an interface through
00055  * plugins for the engine seems not to be managable. Therefor all default functions used
00056  * in our engine are registered by the script engine. By adding or deleting any
00057  * script function there will be an event. Your glue-code has to catch this event to
00058  * take care off registering or derigistering this function in your scripting language.
00059  *
00060  * For example you want to use lua in your application. You use some 3rd party tools
00061  * like tolua which does generate a c++ code form pkg files. This newly generated files
00062  * can be used to provide your c++ classes in lua. Now to provide the engine's scripting
00063  * functions, which are registered by the ScriptEngine you have to write a wrapper which will
00064  * call ScriptEngine::call() method if appropriate function was called from lua.
00065  *
00066  * Probalby in later version we can provide some binding to you (loadtime plugins), which
00067  * does provide this functionality. But at now there is no other way to do this.
00068  **/
00069 
00070 namespace nrEngine{
00071 
00072 
00073         //! Script interface for any kind of script languages
00074         /**
00075         * This is an interface for any kind of scripting language provided by the plugins.
00076         * This interface is used to executed strings typed in the console or readed from
00077         * the scripting files.
00078         *
00079         * We also define each script as an task in the kernel. So the script will be
00080         * updated in each tick by the kernel and will be unloaded from the task queue as soon
00081         * as the script ends his execution. Using of scripts as a task has the advantage, that
00082         * we are able to run scripts with a certain priority/order number. So the script_Task can
00083         * run before certain application task or after them.
00084         *
00085         * Each script can not only be executed, but if specify any functions or routines,
00086         * so this routines could be explicitely called. You can also specify arguments
00087         * for such a routine. Therefor the IScript interface does only store
00088         * the arguments and their type as a string. Derived class should read this
00089         * and pass the parameters in the right way. If a derived script language
00090         * does not support any arguments or function calling so just ignore them.
00091         * Passed parameters will be automaticaly removed from the waiting list as
00092         * soon as the function from the script will be called.
00093         *
00094         * @see IResource, ITask
00095         * \ingroup script
00096         **/
00097         class _NRExport IScript : public IResource, public ITask{
00098                 public:
00099                         //! You can also push a list of arguments to the function directly
00100                         typedef std::list<std::pair<std::string, std::string> > ArgumentList;
00101 
00102                         /**
00103                          * Returns the content of the script file
00104                          **/
00105                         NR_FORCEINLINE const std::string& getContent() const { return mContent; }
00106 
00107                         /**
00108                         * Load a script from string. The given string should contain
00109                         * the script in the appropriate language, so it can be executed.
00110                         *
00111                         * @param str String containing the script
00112                         * @return either OK or:
00113                         *               - SCRIPT_PARSE_ERROR
00114                         **/
00115                         virtual Result loadFromString(const std::string& str) = 0;
00116 
00117                         /**
00118                         * Get short description of the last error.
00119                         **/
00120                         std::string popLastError();
00121 
00122                         /**
00123                          * Execute the script. The script will be executed completely, before
00124                          * go back to the system run. Execution is done by adding the script to
00125                          * the kernel's pipeline. In the next cycle the script will be then executed.
00126                          *
00127                          * @param runOnce If true, so the script method run() will be called only
00128                          *                      once. If you specify false, so run() will be called in each
00129                          *                      kernel cycle.
00130                          *
00131                          * NOTE: If you want to execute script immidiately, use forceExecute() instead
00132                          **/
00133                         Result execute(bool runOnce = true);
00134 
00135                         /**
00136                          * Force starting the script. Script will be added to the kernel
00137                          * and started immeiately after that, by calling the run() method.
00138                          * Afer that the script will be updated in each cycle if not otherwise
00139                          * specified.
00140                          *
00141                          * @see execute()
00142                          **/
00143                         Result forceExecute(bool runOnce = true);
00144 
00145                         /**
00146                          * By calling the execute() method you will execute the whole script completely.
00147                          * This is usefull if you do not interested in the results of the scripts, but
00148                          * in its handling. However if you wish to call a certain function from the script
00149                          * (only if function calling is supported by the scripting language), so you
00150                          * have to use this method.
00151                          *
00152                          * Here a certain function from the script will be called. The result of this function
00153                          * will be given back in a generic type ScriptResult. You have to know how
00154                          * to interpret the results given back by the script. If any error occurs the
00155                          * error message will be logged and an exception will be thrown. Catch
00156                          * the exception to handle the errors.
00157                          *
00158                          * @param funcName Name of the function to call
00159                          *
00160                          * @return result from the script execution converted into generic
00161                          * ScriptResult object.
00162                          *
00163                          * NOTE: To pass parameters to function use pushArgument()
00164                          **/
00165                         ScriptResult call(const std::string& funcName);
00166 
00167                         /**
00168                          * User application can also specify certain arguments for functions
00169                          * in the script. The derived class implementing specific script
00170                          * language must read out this values before starting the script.
00171                          * The derived class should also know how to pass them to the script
00172                          * language and how to parse them. If a script does not support function
00173                          * calling or argument binding, so this values can be ignored.
00174                          *
00175                          * @param funcName Name of the function/routine in the script for which one
00176                          *                                      the parameters are specified
00177                          * @param type String containing the name of the type of the argument
00178                          * @param value String containing the value of the argument.
00179                          *
00180                          * @return Number of arguments currently stored for the given function including
00181                          *                      the new argument.
00182                          *
00183                          * NOTE: Push arguments from the first to the last.
00184                          **/
00185                         uint32 pushArgument(const std::string& funcName, const std::string& type, const std::string& value);
00186 
00187                         /**
00188                          * Same as pushArgument() but set argument from the list. Already pushed
00189                          * arguments will be removed !
00190                          **/
00191                         uint32 setArguments(const std::string& funcName, const ArgumentList& args);
00192 
00193                         /**
00194                          * Derived class should use this function to pop the first parameter
00195                          * from the list. The argument type and the value will be stored in
00196                          * the given variables. The function does return the number of
00197                          * remaining parameters. If function returns 0, so no parameters are
00198                          * available.
00199                          *
00200                          * @param funcName Name of the function for which the arguments are retrieved
00201                          * @param type Here the type of the argument will be stored
00202                          * @param value Here the value of the argument will be stored
00203                          *
00204                          * @return Number of remaining arguments for the function. If the resulting
00205                          *                      value is -1, so no parameters for the function exists
00206                          *
00207                          * NOTE: The arguments are returned from the first to the last
00208                          **/
00209                         int32 popArgument(const std::string& funcName, std::string& type, std::string& value);
00210 
00211                 protected:
00212 
00213                         /**
00214                          * Run the script. This method must be overriden by the derived classes.
00215                          * run will be called by the execution of the script. However you can not
00216                          * be sure if the script executed completely or only stepwise by this method,
00217                          * this depends only on the implementation. Read appropriate documentation of
00218                          * script language implementation.
00219                          **/
00220                         virtual Result run() = 0;
00221 
00222                         /**
00223                          * Derived class can overload this method if a implemented script language
00224                          * does support function calling. Default behaviour of this method
00225                          * is not to call any function or to execute a script. Overload
00226                          * this if you wish to have another behaviour.
00227                          *
00228                          * @param funcName name of the function to call
00229                          * @param result Store here the result of a call of a function
00230                          * @return OK if no error during the execution occurs or an error code.
00231                          *                      If any error code will be returned so an exception will
00232                          *                      be thrown.
00233                          **/
00234                         virtual Result callfunc(const std::string& funcName, ScriptResult& result);
00235 
00236                         /**
00237                          * If any error occurs stor here the error messages.
00238                          * The base class will deliver them to the user. Also the base
00239                          * class does implement error message stack, so returned messages are
00240                          * automaticaly removed from the message stack.
00241                          **/
00242                         void pushErrorMessage(const std::string& msg);
00243 
00244                         /**
00245                          * Initialize the script interface
00246                          * Specify also the script type name, so we know of which
00247                          * type is the given script
00248                          **/
00249                         IScript(const std::string&);
00250 
00251                         /**
00252                          * Virtual destructor
00253                          **/
00254                         virtual ~IScript();
00255 
00256                         /**
00257                          * Run one step from the script. This method will be automaticaly
00258                          * called from the engine's kernel.
00259                          **/
00260                         Result updateTask();
00261 
00262                         /**
00263                          * Method is called from kernel, when script starts its execution
00264                          **/
00265                         Result onStartTask();
00266 
00267                         //! Here we store the whole script as a string
00268                         std::string mContent;
00269 
00270                         /**
00271                          * Bypass the IResource::unloadRes() function, so that derived
00272                          * class can overload them
00273                          **/
00274                         virtual Result unloadResource() {return OK;}
00275                         virtual Result reloadResource(PropertyList* params) {return OK;}
00276 
00277                         //! Check if script should only run once
00278                         bool shouldRunOnce() const { return mbRunOnce; }
00279 
00280                         //! Should the script run only once (no loop)
00281                         void setRunOnce(bool b) { mbRunOnce = b; }
00282 
00283                         /**
00284                          * This method will be called to check from base class to
00285                          * check if run completes. If derived class returns false,
00286                          * so script will be removed from the kernel
00287                          **/
00288                         virtual bool hasCommands() = 0;
00289 
00290                         /**
00291                          * This method will be called if a script is gonna be executed.
00292                          * Override this method to make some initializations for example.
00293                          **/
00294                         virtual void onStartScript() {};
00295 
00296                         /**
00297                          * Call this method to manually specify, that a script is
00298                          * loaded and can be executed. The method should be called
00299                          * from loadFromString() method by derived classes
00300                          **/
00301                         void notifyLoaded();
00302 
00303                 private:
00304 
00305                         //! Should this script run once
00306                         bool mbRunOnce;
00307 
00308                         //! Store here error messages
00309                         std::list<std::string> mErrorMsg;
00310 
00311                         typedef std::map<std::string, ArgumentList>             ArgumentDatabase;
00312 
00313                         //! Here we store the arguments for the script
00314                         ArgumentDatabase mArguments;
00315 
00316         };
00317 
00318 
00319         //! Empty script object that just do nothing(idle).
00320         /**
00321          * Empty script objects do nothing. They idle.
00322          * \ingroup script
00323          **/
00324         class _NRExport EmptyScript : public IScript{
00325         public:
00326 
00327                 //! Constructor does not call anything
00328                 EmptyScript(const std::string& typeName);
00329 
00330                 //! Release used memory
00331                 ~EmptyScript();
00332 
00333                 //! Loading an empty script from file does not affect anything
00334                 Result loadFromString(const std::string& str);
00335 
00336                 //! Executing of empty script does return immideately
00337                 Result run();
00338         private:
00339                 bool hasCommands() { return false; }
00340         };
00341 
00342 };
00343 
00344 #endif

Generated on Wed Sep 12 23:19:42 2007 for nrEngine by  doxygen 1.5.1