FScript is intended to be embedded within other applications.
This can be done in three (count them, three) ways:
The first method is the simplest, but the second provides much greater flexibility, as it is possible to register multiple extensions simultaneously.
You will also need to know the various methods used to load code into FScript, and to execute it.
This is done by simply sub-classing FScript class, and overriding a number of key methods. This resulting class is then used to process the FScript scripts.
The BasicIO class can be examined to see how this is done. The BasicIO class provides (very basic) IO capabilities to FScript. If correctly implemented (see below) such subclasses can themselves be subclassed to add further features.
Also see the JavaDoc for more detailed information.
Methods to Override
There are 3 functions that you may override to integrate FScript with your application. These are:
callFunction
callFunction is called whenever a function call is encountered in the script that has not been previously defined. Hence allowing the application embedding FScript to appear to have functions mapped into FScript's name space. It is called with two parameters, the first being the function name, and the second being an array list of parameters passed to the function from the script.
Typically this Method will perform the actions associated with the passed in function name, and perhaps return a value. A returned value must be one of the FScript supported types (String, Integer and Double).
If the function name does not match one your method is expecting, it is typically an error. The preferred method of handling this is to call super.callFunction . This makes it possible to 'chain' subclasses of FScript together (e.g. you could subclass BasicIO, add one function, and any calls you did not process would be handed back to BasicIO). Although if you are doing this you may want to look at extensions
which could provide a simpler interface.The callFunction method can only throw a FSException, so all exceptions generated by your code will need to be handled (if necessary by re-throwing as an FSException). Any thrown FSException will be caught, and additional context information added, before being re-thrown.
setVar/getVar
This method is called when a FScript variable name is encountered that has not been previously defined - hence allowing the application embedding FScript to appear to have variables mapped into FScript's name space.
setVar is called with two parameters one being the variable name, and the other being the value to which that 'variable' is to be set. getVar is called only with a variable name, and the method is expected to return one of the Java types recognized by FScript (Integer, String and Double).
As with callFunction if the variable name passed in is not one the embedding application expects it should call super.setVar / super.getVar . Also like callFunction only FSExceptions my be thrown by these methods.
Both setVar and getVar have versions that also accept index parameters, this allows for array like access to variables defined in subclasses (see JavaDoc for details).
A more flexible approach than subclassing is using extensions. Any class wishing to register as an extension to FScript must implement the FSExtension interface. This methods defined by this interface mirror the ones discussed above (callFunction,getVar and setVar ). These methods will then be called when unknown variables or function names are encountered in a script.
It is vital that if an extension receives a call for a function or variable name that is not implemented by this extension it must raise a FSUnsupportedExtension . This enables the call to be passed on to other extensions. The only other exception that may be thrown is a FSException which is used to indicate an error condition.
In order to register an extension with FScript the method registerExtension is called. To remove an extension call unRegisterExtension (which may be important as FScript retains a reference to the extension, so it will not be garbage collected).
The fragment of code below shows an example of extension use:
FScript fs=new FScript(); MyDataBaseExtension db=new MyDataBaseExtension(); //register various extensions fs.registerExtension(db); fs.registerExtension(new MyIOExtension()); fs.registerExtensoin(new MyWebExtension()); fs.load(inputFileReader); rs.run(); //just because we can fs.unRegisterExtension(db);
As the FScript class itself implements the FSExtension interface, any subclasses of FScript may also be used as FScript extensions - although this is probably not all that efficient.
A class BasicExtension is provided that can be subclassed to simplify building extensions., It simply implements FSExtension and all method calls throw a FSUnsupportedException.
The FSFastExtension class provides a way of creating even simpler extensions to FScript (i.e they do not have to implement the whole FSExtension interface). To use you register an instance of FSFastExtension with the FScript parser, and then add extensions to the FSFastExtension instance. These extensions can implement FSVarExtension , FSFunctionExtension or FSArrayExtension , where these classes define the relevant methods for handling variables, functions or array type variables. In fact the FSExtension interface is really just a compound of these three interfaces.
The coding needed for these FSFastExtension classes is similar to that for subclasses and extensions mentioned above. See the examples directory for an example of FSFastExtension in use.