Class BasicInterpreter

java.lang.Object
com.scriptbasic.executors.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.Object call​(java.lang.String functionName, java.lang.Object[] arguments)
    Call a function defined by the program passing the objects as arguments.
    void disableHook()
    Temporarily disable the hooks.
    void enableHook()
    Enable the hook calls.
    void execute()
    Execute the program.
    void execute​(Command startCommand)
    Execute the program starting at the command startCommand
    Configuration getConfiguration()  
    java.io.Writer getErrorOutput()
    ScriptContext.getReader()
    InterpreterHook getHook()
    Get the hook object the interpreter has.
    java.io.Reader getInput()  
    java.lang.reflect.Method getJavaMethod​(java.lang.Class<?> klass, java.lang.String methodName)
    Get the method named from the klass based on the declaration given in a previously executed METHOD basic 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.Writer getOutput()  
    BuildableProgram getProgram()  
    RightValue getReturnValue()
    Get the return value that was set by the execution of the subroutine.
    CommandSub getSubroutine​(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.Object getVariable​(java.lang.String name)
    Get the value of a variable.
    HierarchicalVariableMap getVariables()
    Get the global variables of the program.
    Command pop()
    Pop the command from the top of the stack and also drop the last local variables frame.
    void push()
    Same as InternalInterpreter.push(Command) and pushes the currently executing command on the stack.
    void push​(Command command)
    Push a command to the stack.
    void registerFunctions​(java.lang.Class<?> klass)
    Register the functions defined in the class.
    void registerHook​(InterpreterHook hook)  
    void registerJavaMethod​(java.lang.String alias, java.lang.Class<?> klass, java.lang.String methodName, java.lang.Class<?>[] argumentTypes)
    Register a BASIC function as Java method.
    void setErrorOutput​(java.io.Writer errorWriter)  
    void setInput​(java.io.Reader reader)  
    void setNextCommand​(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.
    void setOutput​(java.io.Writer writer)  
    void setProgram​(BuildableProgram buildableProgram)
    Set the program to execute.
    void setReturnValue​(RightValue returnValue)
    Register the return value.
    void setVariable​(java.lang.String name, java.lang.Object value)
    Set the value of the variable.

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Constructor Details

    • BasicInterpreter

      public BasicInterpreter​(Context ctx)
      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

      public InterpreterHook getHook()
      Description copied from interface: Interpreter
      Get the hook object the interpreter has.
      Specified by:
      getHook in interface Interpreter
      Returns:
      return value
    • disableHook

      public void disableHook()
      Description copied from interface: Interpreter
      Temporarily disable the hooks. Following this call the hooks will not be called until the Interpreter.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 method InterpreterHook.setReturnValue(RightValue) should first disable the hook mechanism, call back to the interpreter object and the enable the hook mechanism again.

      Specified by:
      disableHook in interface Interpreter
    • enableHook

      public void enableHook()
      Description copied from interface: Interpreter
      Enable the hook calls. This method has to be called after the call to Interpreter.disableHook() to enable again the calling mechanism.
      Specified by:
      enableHook in interface Interpreter
    • registerHook

      public void registerHook​(InterpreterHook hook)
      Specified by:
      registerHook in interface Interpreter
    • getInput

      public java.io.Reader getInput()
      Specified by:
      getInput in interface Interpreter
      Returns:
      the reader
    • setInput

      public void setInput​(java.io.Reader reader)
      Specified by:
      setInput in interface Interpreter
      Parameters:
      reader - the reader to set
      See Also:
      ScriptContext.setReader(Reader)
    • getOutput

      public java.io.Writer getOutput()
      Specified by:
      getOutput in interface Interpreter
      Returns:
      the writer
    • setOutput

      public void setOutput​(java.io.Writer writer)
      Specified by:
      setOutput in interface Interpreter
      Parameters:
      writer - the writer to set
      See Also:
      ScriptContext.setWriter(Writer)
    • getErrorOutput

      public java.io.Writer getErrorOutput()
      Description copied from interface: Interpreter
      ScriptContext.getReader()
      Specified by:
      getErrorOutput in interface Interpreter
      Returns:
      the error
    • setErrorOutput

      public void setErrorOutput​(java.io.Writer errorWriter)
      Specified by:
      setErrorOutput in interface Interpreter
      Parameters:
      errorWriter - the error to set
      See Also:
      ScriptContext.setErrorWriter(Writer)
    • getVariables

      public HierarchicalVariableMap getVariables()
      Description copied from interface: Interpreter
      Get the global variables of the program.
      Specified by:
      getVariables in interface Interpreter
      Returns:
      the variables.
    • getSubroutine

      public CommandSub getSubroutine​(java.lang.String name)
      Description copied from interface: Interpreter
      Get a subroutine by its name.
      Specified by:
      getSubroutine in interface Interpreter
      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: Interpreter
      Register 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:
      registerFunctions in interface Interpreter
      Parameters:
      klass - the class the defines the functions.
    • execute

      public void execute() throws ScriptBasicException
      Description copied from interface: Interpreter
      Execute the program.
      Specified by:
      execute in interface Interpreter
      Throws:
      ScriptBasicException - in case of exception
    • execute

      public void execute​(Command startCommand) throws ScriptBasicException
      Description copied from interface: Interpreter
      Execute the program starting at the command startCommand
      Specified by:
      execute in interface Interpreter
      Parameters:
      startCommand - where the execution has to start
      Throws:
      ScriptBasicException - in case of exception during the execution
    • setVariable

      public void setVariable​(java.lang.String name, java.lang.Object value) throws ScriptBasicException
      Description copied from interface: Interpreter
      Set 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:
      setVariable in interface Interpreter
      Parameters:
      name - the name of the global variable
      value - the value to be set
      Throws:
      ScriptBasicException - in case of exception
    • getVariable

      public java.lang.Object getVariable​(java.lang.String name) throws ScriptBasicException
      Description copied from interface: Interpreter
      Get 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 a BasicDoubleValue then the implementation will return a Double.
      Specified by:
      getVariable in interface Interpreter
      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 ScriptBasicException
      Description copied from interface: Interpreter
      Call a function defined by the program passing the objects as arguments.
      Specified by:
      call in interface Interpreter
      Parameters:
      functionName - the name of the function in the program code
      arguments - the arguments to the function
      Returns:
      the returned object, or null if the function does not return value
      Throws:
      ScriptBasicException - in case of exception
    • getProgram

      public BuildableProgram getProgram()
      Specified by:
      getProgram in interface InternalInterpreter
      Returns:
      the program that the interpreter is executing.
    • setProgram

      public void setProgram​(BuildableProgram buildableProgram)
      Description copied from interface: InternalInterpreter
      Set the program to execute.
      Specified by:
      setProgram in interface InternalInterpreter
      Parameters:
      buildableProgram - parameter
    • setNextCommand

      public void setNextCommand​(Command nextCommand)
      Description copied from interface: InternalInterpreter
      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.
      Specified by:
      setNextCommand in interface InternalInterpreter
      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: InternalInterpreter
      Since 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:
      getMap in interface InternalInterpreter
      Returns:
      the map
    • getUseMap

      public java.util.Map<java.lang.String,​java.lang.Class<?>> getUseMap()
      Description copied from interface: InternalInterpreter
      Programs 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 example
       use 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 class javal.lang.Math for the key m.
      Specified by:
      getUseMap in interface InternalInterpreter
      Returns:
      the use map itself.
    • getJavaMethod

      public java.lang.reflect.Method getJavaMethod​(java.lang.Class<?> klass, java.lang.String methodName)
      Description copied from interface: InternalInterpreter
      Get the method named from the klass based on the declaration given in a previously executed METHOD basic command. The basic command METHOD has the form (example follows):
       method sin from java.lang.Math is (double)
       
      that defines that the method sin is in the class java.lang.Math and accepts one argument, which is double
      Specified by:
      getJavaMethod in interface InternalInterpreter
      Parameters:
      klass - parameter
      methodName - 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 BasicRuntimeException
      Description copied from interface: Interpreter
      Register 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 as
       use class from package as basicClassReference
       
      for example
       use Math from java.lang as m
       
      when the method sin is used, foe example
       a = m.sin(1.0)
       
      the BASIC interpreter has to find the method java.lang.Math.sin(Double x). The problem is that the method does not exist because the argument is not Double but rather double.

      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 part use 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 to InternalInterpreter.getJavaMethod(Class, String) can find the appropriate method.

      Specified by:
      registerJavaMethod in interface Interpreter
      Parameters:
      alias - the alias how the function will be named in basic
      klass - the class where the static method is
      methodName - the java name of the method
      argumentTypes - the types of the arguments to be used to help to identify overloaded methods
      Throws:
      BasicRuntimeException - in case of exception
    • push

      public void push​(Command command)
      Description copied from interface: InternalInterpreter
      Push 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:
      push in interface InternalInterpreter
      Parameters:
      command - the command from which a subroutine call was executed.
    • push

      public void push()
      Description copied from interface: InternalInterpreter
      Same as InternalInterpreter.push(Command) and pushes the currently executing command on the stack.
      Specified by:
      push in interface InternalInterpreter
    • pop

      public Command pop()
      Description copied from interface: InternalInterpreter
      Pop the command from the top of the stack and also drop the last local variables frame.
      Specified by:
      pop in interface InternalInterpreter
      Returns:
      the value
    • getReturnValue

      public RightValue getReturnValue()
      Description copied from interface: Interpreter
      Get the return value that was set by the execution of the subroutine.
      Specified by:
      getReturnValue in interface Interpreter
      Returns:
      return value
    • setReturnValue

      public void setReturnValue​(RightValue returnValue)
      Description copied from interface: Interpreter
      Register the return value. This method is called from a subroutine.
      Specified by:
      setReturnValue in interface Interpreter
      Parameters:
      returnValue - the value that the subroutine will return
    • getConfiguration

      public Configuration getConfiguration()
      Specified by:
      getConfiguration in interface Interpreter