Class BasicInterpreter

    • Constructor Summary

      Constructors 
      Constructor Description
      BasicInterpreter​(Context ctx)
      Create a new interpreter using the context.
    • Method Summary

      All Methods Instance Methods Concrete Methods 
      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 Detail

      • 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 Detail

      • 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
      • 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)
      • 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.
      • 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
      • 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.
      • 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