Different mechanisms for argument passing is a major issue for the translation. In FORTRAN, when a function/subroutine is called, the addresses of the actual arguments (variables) are passed to it [6]. In Java, the values of the arguments are passed for primitive data types and the references (a kind of value) are passed for objects [3]. This means, in Java, the values of the actual argument variables will not get changed upon returning from methods, while FORTRAN often expects a change.
There is a similar problem when converting FORTRAN to C. There, pointers are used to solve it [7, 8]. But in Java, there is no pointer.
Two approaches were considered.
Java passes non primitive data (object) to methods by reference -- a kind of address. Thus, if the reference is not modified in the method, i.e., not appearing at left hand side of an assignment statement, the modification to the member of the object is observed by the caller [3].
So, we might declare a class for each FORTRAN data type, for example:
class INTEGER { public int value; };and put all this kind of classes into one package named data_type. This package should be imported in every produced .java file. Then, every variable declaration statement should be converted to the class declaration statement. When a function/subroutine is invoked, the corresponding object should be passed into the function/subroutine. And in the invoked function, memory is not reallocated to the object [3]. The member of the object is modified if the argument in the source FORTRAN file is modified.
For instance, the following FORTRAN program:
program main integer a, b call xx(a,b) end subroutine xx(d,e) integer d, e d = 3 e = 4 return endyields the following Java program:
class main_mc { public static void main(String args[]) { INTEGER a = new INTEGER(); INTEGER b = new INTEGER(); xx_c.xx(a,b); } } class xx_c { public static void xx(INTEGER d, INTEGER e) { d.value = 3; e.value = 4; return; } }
This approach is easy to implement, but not efficient, since objects are artificially created and accessing object is much slower (about 3 times) than primitive type access in Java. We did not use this method in our implementation.
As mentioned above, a class is generated for each function/subroutine. A method semantically equivalent to the function/subroutine is contained in this class. The second approach introduces some class variables into the class, besides the method. Each class variable, which is generated according to the arguments, serves as an intermedium between actual argument and dummy argument: before the function/subroutine returns, the class variable is assigned the value of argument if it is modified in the function/subroutine; after the invocation statement in the caller, the actual argument is assigned the value of the class variable. The names of the class variables are the names of the arguments with `_cv' appended to it.
For the same FORTRAN program above, the following Java program is produced under this scheme.
class main_mc { public static void main(String args[]) { int a=0, b=0; xx_c.xx(a,b); a = xx_c.d_cv; // produced by converter, modify actual arg b = xx_c.e_cv; } } class xx_c { static int d_cv; static int e_cv; public static void xx(int d,int e) { d = 3; e = 4; d_cv = d; e_cv = e; return; } }
This scheme is currently implemented in our converter. Notice how the CALL statement in FORTRAN is converted to corresponding method invocation in Java.
While being more efficient, this method also suffers from a few problems (we thank one of the referees who pointed out some of them). The first problem is that it does not support separate conversion of FORTRAN program unit, namely, names of dummy arguments of a callee must be known when converting a caller. The second problem is incapability of handling dummy arguments' aliasing, namely things like CALL FOO(a,a). In this case, two dummy arguments refer to the same memory location, the order of updating the two dummies in callee determines the value that caller will see after the subroutine returns. But the order of assigning class variables to actual arguments is normally fixed. The third problem is thread safety. Unprotected static class variables may be accessed concurrently in an unpredictable way, when the class is used by multiple threads.