Class BasicInterpreter
- All Implemented Interfaces:
InternalInterpreter,Interpreter
public final class BasicInterpreter extends java.lang.Object implements Interpreter
- Author:
- Peter Verhas date June 22, 2012
-
Constructor Summary
Constructors Constructor Description BasicInterpreter(Context ctx)Create a new interpreter using the context. -
Method Summary
Modifier and Type Method Description java.lang.Objectcall(java.lang.String functionName, java.lang.Object[] arguments)Call a function defined by the program passing the objects as arguments.voiddisableHook()Temporarily disable the hooks.voidenableHook()Enable the hook calls.voidexecute()Execute the program.voidexecute(Command startCommand)Execute the program starting at the commandstartCommandConfigurationgetConfiguration()java.io.WritergetErrorOutput()ScriptContext.getReader()InterpreterHookgetHook()Get the hook object the interpreter has.java.io.ReadergetInput()java.lang.reflect.MethodgetJavaMethod(java.lang.Class<?> klass, java.lang.String methodName)Get the method named from the klass based on the declaration given in a previously executedMETHODbasic command.java.util.Map<java.lang.String,java.lang.Object>getMap()Since the Command objects should not contain runtime information there is a need sometime to store information that is runtime.java.io.WritergetOutput()BuildableProgramgetProgram()RightValuegetReturnValue()Get the return value that was set by the execution of the subroutine.CommandSubgetSubroutine(java.lang.String name)Get a subroutine by its name.java.util.Map<java.lang.String,java.lang.Class<?>>getUseMap()Programs can access Java static methods from different packages.java.lang.ObjectgetVariable(java.lang.String name)Get the value of a variable.HierarchicalVariableMapgetVariables()Get the global variables of the program.Commandpop()Pop the command from the top of the stack and also drop the last local variables frame.voidpush()Same asInternalInterpreter.push(Command)and pushes the currently executing command on the stack.voidpush(Command command)Push a command to the stack.voidregisterFunctions(java.lang.Class<?> klass)Register the functions defined in the class.voidregisterHook(InterpreterHook hook)voidregisterJavaMethod(java.lang.String alias, java.lang.Class<?> klass, java.lang.String methodName, java.lang.Class<?>[] argumentTypes)Register a BASIC function as Java method.voidsetErrorOutput(java.io.Writer errorWriter)voidsetInput(java.io.Reader reader)voidsetNextCommand(Command nextCommand)Tell the interpreter that the next command to call is not the one that follows the actual command but rather the one specified by the argument.voidsetOutput(java.io.Writer writer)voidsetProgram(BuildableProgram buildableProgram)Set the program to execute.voidsetReturnValue(RightValue returnValue)Register the return value.voidsetVariable(java.lang.String name, java.lang.Object value)Set the value of the variable.
-
Constructor Details
-
BasicInterpreter
Create a new interpreter using the context. Also register the null hook, so that other hooks should not worry about the 'next hook' value, it is guaranteed to be not null.- Parameters:
ctx- parameter
-
-
Method Details
-
getHook
Description copied from interface:InterpreterGet the hook object the interpreter has.- Specified by:
getHookin interfaceInterpreter- Returns:
- return value
-
disableHook
public void disableHook()Description copied from interface:InterpreterTemporarily disable the hooks. Following this call the hooks will not be called until theInterpreter.enableHook()is called.Hook disabling was designed with the special case in mind when a hook wants to alter the return value returned from a subroutine. To do so the hook method has to invoke the
Interpreter.setReturnValue(RightValue)method, which was actually calling the hook. To avoid the infinite loop and not to confuse the other hook methods that are in the list sooner the hook methodInterpreterHook.setReturnValue(RightValue)should first disable the hook mechanism, call back to the interpreter object and the enable the hook mechanism again.- Specified by:
disableHookin interfaceInterpreter
-
enableHook
public void enableHook()Description copied from interface:InterpreterEnable the hook calls. This method has to be called after the call toInterpreter.disableHook()to enable again the calling mechanism.- Specified by:
enableHookin interfaceInterpreter
-
registerHook
- Specified by:
registerHookin interfaceInterpreter
-
getInput
public java.io.Reader getInput()- Specified by:
getInputin interfaceInterpreter- Returns:
- the reader
-
setInput
public void setInput(java.io.Reader reader)- Specified by:
setInputin interfaceInterpreter- Parameters:
reader- the reader to set- See Also:
ScriptContext.setReader(Reader)
-
getOutput
public java.io.Writer getOutput()- Specified by:
getOutputin interfaceInterpreter- Returns:
- the writer
-
setOutput
public void setOutput(java.io.Writer writer)- Specified by:
setOutputin interfaceInterpreter- Parameters:
writer- the writer to set- See Also:
ScriptContext.setWriter(Writer)
-
getErrorOutput
public java.io.Writer getErrorOutput()Description copied from interface:InterpreterScriptContext.getReader()- Specified by:
getErrorOutputin interfaceInterpreter- Returns:
- the error
-
setErrorOutput
public void setErrorOutput(java.io.Writer errorWriter)- Specified by:
setErrorOutputin interfaceInterpreter- Parameters:
errorWriter- the error to set- See Also:
ScriptContext.setErrorWriter(Writer)
-
getVariables
Description copied from interface:InterpreterGet the global variables of the program.- Specified by:
getVariablesin interfaceInterpreter- Returns:
- the variables.
-
getSubroutine
Description copied from interface:InterpreterGet a subroutine by its name.- Specified by:
getSubroutinein interfaceInterpreter- Parameters:
name- the name of the subroutine- Returns:
- the "SUB" command that starts the subroutine
-
registerFunctions
public void registerFunctions(java.lang.Class<?> klass)Description copied from interface:InterpreterRegister the functions defined in the class. Functions that can be called from a BASIC program but implemented in Java are static methods that are registered for the interpreter. The easiest way to define these methods are to create a class and annotate the methods that serve as BASIC functions with the annotation@BasicFunction- Specified by:
registerFunctionsin interfaceInterpreter- Parameters:
klass- the class the defines the functions.
-
execute
Description copied from interface:InterpreterExecute the program.- Specified by:
executein interfaceInterpreter- Throws:
ScriptBasicException- in case of exception
-
execute
Description copied from interface:InterpreterExecute the program starting at the commandstartCommand- Specified by:
executein interfaceInterpreter- Parameters:
startCommand- where the execution has to start- Throws:
ScriptBasicException- in case of exception during the execution
-
setVariable
Description copied from interface:InterpreterSet the value of the variable. If the program is in a local scope and there is a variable with the given name in the local scope then the value of that variable is set, even if there is a global variable with that name.- Specified by:
setVariablein interfaceInterpreter- Parameters:
name- the name of the global variablevalue- the value to be set- Throws:
ScriptBasicException- in case of exception
-
getVariable
Description copied from interface:InterpreterGet the value of a variable. Since this is not a BASIC interpreter method, but rather a method that helps the embedding of the interpreter the returned value is a raw Java object and not a RightValue. Thus if the variable value is for example aBasicDoubleValuethen the implementation will return aDouble.- Specified by:
getVariablein interfaceInterpreter- Parameters:
name- the name of the variable- Returns:
- the value of the variable
- Throws:
ScriptBasicException- in case of exception
-
call
public java.lang.Object call(java.lang.String functionName, java.lang.Object[] arguments) throws ScriptBasicExceptionDescription copied from interface:InterpreterCall a function defined by the program passing the objects as arguments.- Specified by:
callin interfaceInterpreter- Parameters:
functionName- the name of the function in the program codearguments- the arguments to the function- Returns:
- the returned object, or
nullif the function does not return value - Throws:
ScriptBasicException- in case of exception
-
getProgram
- Specified by:
getProgramin interfaceInternalInterpreter- Returns:
- the program that the interpreter is executing.
-
setProgram
Description copied from interface:InternalInterpreterSet the program to execute.- Specified by:
setProgramin interfaceInternalInterpreter- Parameters:
buildableProgram- parameter
-
setNextCommand
Description copied from interface:InternalInterpreterTell the interpreter that the next command to call is not the one that follows the actual command but rather the one specified by the argument.- Specified by:
setNextCommandin interfaceInternalInterpreter- Parameters:
nextCommand- is the next command to execute after the current command
-
getMap
public java.util.Map<java.lang.String,java.lang.Object> getMap()Description copied from interface:InternalInterpreterSince the Command objects should not contain runtime information there is a need sometime to store information that is runtime. This method returns a map that is unique to the currently executing Command and is also unique to the Interpreter. Thus if two interpreters simultaneously execute the same command they will return two different maps.The interpreter initializes the map when the command asks for it the first time. The life time of the map is the same as the life time of the interpreter. Thus when a program finishes the map is still available to the command when the Interface 'call' method is called or the interpreter is restarted.
The interpreter does not alter the map in any other way than initializing it to some map implementation containing initially no element.
- Specified by:
getMapin interfaceInternalInterpreter- Returns:
- the map
-
getUseMap
public java.util.Map<java.lang.String,java.lang.Class<?>> getUseMap()Description copied from interface:InternalInterpreterPrograms can access Java static methods from different packages. To do that the programs have to recognize when the call 'out' to Java instead of looking for an internal function implemented in the program. For example the BASIC program has to declare the use of these packages using the command USE. For exampleuse Math from java.lang as m
(the part following the keyword 'as' is optional, in which case the Java name of the class is used). After this statement is executed the use map will contain the classjaval.lang.Mathfor the keym.- Specified by:
getUseMapin interfaceInternalInterpreter- Returns:
- the use map itself.
-
getJavaMethod
public java.lang.reflect.Method getJavaMethod(java.lang.Class<?> klass, java.lang.String methodName)Description copied from interface:InternalInterpreterGet the method named from the klass based on the declaration given in a previously executedMETHODbasic command. The basic command METHOD has the form (example follows):method sin from java.lang.Math is (double)
that defines that the methodsinis in the classjava.lang.Mathand accepts one argument, which isdouble- Specified by:
getJavaMethodin interfaceInternalInterpreter- Parameters:
klass- parametermethodName- parameter- Returns:
- return value
-
registerJavaMethod
public void registerJavaMethod(java.lang.String alias, java.lang.Class<?> klass, java.lang.String methodName, java.lang.Class<?>[] argumentTypes) throws BasicRuntimeExceptionDescription copied from interface:InterpreterRegister a BASIC function as Java method. Java methods may be overloaded but BASIC functions can not. When a BASIC program wants to use a Java method it has to declare it asuse class from package as basicClassReference
for exampleuse Math from java.lang as m
when the methodsinis used, foe examplea = m.sin(1.0)
the BASIC interpreter has to find the methodjava.lang.Math.sin(Double x). The problem is that the method does not exist because the argument is notDoublebut ratherdouble.To help with this situation the BASIC program should declare the Java signature of the method using the BASIC command METHOD. For example:
method sin from java.lang.Math is (double) use as sinus
(Note that the partuse as ...is optional.)After this command is executed the interpreter will use the defined signature to locate the method. You can write in the BASIC program
a = m.sinus(1.0)
registerJavaMethod()registers the basic function alias, class, java method name and the argument types so that later call toInternalInterpreter.getJavaMethod(Class, String)can find the appropriate method.- Specified by:
registerJavaMethodin interfaceInterpreter- Parameters:
alias- the alias how the function will be named in basicklass- the class where the static method ismethodName- the java name of the methodargumentTypes- the types of the arguments to be used to help to identify overloaded methods- Throws:
BasicRuntimeException- in case of exception
-
push
Description copied from interface:InternalInterpreterPush a command to the stack. This is called before a subroutine call is executed. Even though the actual stack is NOT maintained here but rather in the JVM call stack, since function call is implemented using recursive calls to the interpreter the call to this push and pop is vital to keep track the stack trace for debugging purposes and to have a mean to limit the stack size.Calling this method also starts a new local variable frame, thus evaluation of the actual argument values in a function call has to be executed before calling this method.
- Specified by:
pushin interfaceInternalInterpreter- Parameters:
command- the command from which a subroutine call was executed.
-
push
public void push()Description copied from interface:InternalInterpreterSame asInternalInterpreter.push(Command)and pushes the currently executing command on the stack.- Specified by:
pushin interfaceInternalInterpreter
-
pop
Description copied from interface:InternalInterpreterPop the command from the top of the stack and also drop the last local variables frame.- Specified by:
popin interfaceInternalInterpreter- Returns:
- the value
-
getReturnValue
Description copied from interface:InterpreterGet the return value that was set by the execution of the subroutine.- Specified by:
getReturnValuein interfaceInterpreter- Returns:
- return value
-
setReturnValue
Description copied from interface:InterpreterRegister the return value. This method is called from a subroutine.- Specified by:
setReturnValuein interfaceInterpreter- Parameters:
returnValue- the value that the subroutine will return
-
getConfiguration
- Specified by:
getConfigurationin interfaceInterpreter
-