next up previous contents
Next: Things Left To Up: Statements Previous: Case

Function Returns

 

In Pascal the returnvalue of a function has to be assigned to the function identifier. This assignment can take place anywhere in the function, even in nested procedures or functions. A function does not return its value until all the code in the function has been executed.

This differs from the function returns in Java where a function returns its value by a return statement, at which point the function returns immediately.

In the bytecode there are specific instructions to return a value from a function. To return a value of type int, float, long, double or reference there are respectively the instructions ireturn, freturn, lreturn, dreturn and areturn. As usual, the instruction to return a value of type int also returns values of types byte, boolean and char. There is also an instruction that returns no value, the return instruction we used in subsection 9.2.1 to return from a procedure.

As in Pascal the function result has to be assigned to the function identifier, we need to have a variable to assign to. I made this variable global, but this causes the same problems as described in subsection 9.1.3, which are to be solved the same way, by making the variable local and passing it as a call-by-reference parameter to every nested procedure or function.

Before the function returns, the value of the variable has to be loaded on the operand stack for the JVM instruction that returns it. This causes a problem if the function identifier was not assigned to. It is practically not possible to check at compile-time if the function identifier has always been assigned to. Instead the ACK Pascal compiler checks if the function identifier was assigned at least once in the code. This means you have to think of a way to check at runtime if the variable contains a value to return.

For this I created a local boolean variable that acts as a flag and is passed together with the variable that contains the function result. When the function identifier is assigned to, the variable is set to true. Before the function returns it is checked to be set and if so, the return value is loaded on the operand stack and the instruction that returns it is invoked.

If the boolean variable contains the value false, there is no value for the function to return. This means a runtime error has to be generated. For this I implemented the following Java class:

public class FunctionResultNeverAssignedException extends Error
{
    FunctionResultNeverAssignedException()
    {
        super("Function result was not assigned to function " +
              "identifier");
    }
}

This class defines a FunctionResultNeverAssignedException(). Because it extends class Error this exception can never be caught once it is thrown. Because of this, the JVM will stop the execution of the program and will write the name of the exception, the string `` Function result was not assigned to function identifier'' and some additional information about the function the error occurred in.

To call this function in the bytecode I created a pcrterror class that contains a method that throws the FunctionResultNeverAssignedException. For this class similar constant_pool[] entries have to be created as for the pcio class described in section 10.5. This means a CONSTANT_Class_info entry to describe the class and CONSTANT_Methodref_info entries and the entries it needs to describe the methods in the class (only one at this time). The entries are put in the constant_pool[] in the same procedure of the compiler that puts the entries for the pcio class in.

The bytecode for function return is now as follows:

 
 aload bool_index				 load the reference to the  boolean
				   variable on the

stack:

iconst_0 load index into array on the stack;

baload load the value of the boolean variable on the stack;

ifne 6 if value is true jump 6 bytes (skip next instruction);

invokestatic exc_index value is false so generate runtime exception;

aload funcres_index load the reference to the variable containing the

function result on the stack;

iconst_0 load index into array on the stack;

<t>aload load the function result on the stack;

<t>return return the function result.

The <t> of the <t>aload is the letter for the type of the array, the return type of the function, where i stands for int, f for float, c for char and b for boolean.

If the return type of the function is one of the types integer, char or boolean, the <t> of the <t>return instruction is the letter i. If the return type of the function is real, it is the letter f.

When the value of the boolean variable is false the instructions following the invokestatic instruction that invokes the method to throw the exception, will never be reached. The program will be stopped immediately.



next up previous contents
Next: Things Left To Up: Statements Previous: Case



mark@bottom.xs4all.nl