******************
** Introduction **
******************

The purpose of this document is to describe the design choices that have been
made in the context of the Ada2Java prototype, to present to the Java user a 
Java interface of an Ada API. This is a proposal, supposed to serve as a basis
to discussion. Most of it is currently implemented and experimentable in the 
current ada2java prototype.

**************************
** Packages and classes **
**************************

Ada packages and java packages can be mapped directly. This means that 
entities mapped from an Ada package "pckg" will be in a Java package "pckg" as 
well. However, the subprogram container in Java is a class, while it's a 
package in Ada. Additional work is required to determine in which class
the subprogram has to be stored.

A final class, named after the name of the package, will be used to store 
subprograms that can't fit in any of the class assignment rules
(which will be described later on). So for example, in order to bind the
following:

package Pckg is
   function F return Integer;
end Pckg;

The Java side will look like:

package Pckg;

public final class Pckg_Package {
   public static int F () {/* binding code */}
}

For the rest of this document, we will determine the name of this class by
appening the "_Package" suffix to its Ada name. It will be refered as the java
default package class.

******************
** Scalar types **
******************

Scalar types are bound following this scheme (Ada => Java):

integer types, modular types, enumerations => int
Boolean                                    => boolean
Character                                  => char
floating point types                       => double

When enumerations are bound, an extra java final class is created, named after
the enumeration name, containing the list of the possible values for the 
enumeration. Here's an example of simple binding:

package Pckg is
   type Enum is (A, B, C);
end Pckg;

will give:

package Pckg;

public final class Enum {
   public static final int A = 0;
   public static final int B = 1;
   public static final int C = 2;
}

A first reasonable limitation of this is to refuse to bind enumeration with
representation clauses. However, it should be possible to read them and to
ajust assignment of the java values accordingly.

*************************
** Simple record types **
*************************

Simple (not tagged) record types will be mapped as final classes in Java. 
Fields are accessed through a set of accessors / modifiers. Here's an example
of such a binding:

package Pckg is

   type R is record
      F1 : Integer;
      F2 : Float;
   end R;
   
end Pckg;

will give:

package Pckg;

public final class R {

   public R () {/* binding code */}}
   
   public void F1 (int Val) {/* binding code */}

   public int F1 () {/* binding code */}
   
   public void F2 (double Val) {/* binding code */}
   
   public float F2 () {/* binding code */}

}

Note that commented code will get completed by the binding generator, but it 
is not the purpose of this document to describes how it works.

If the record contains other records, the same set of accessor/modifiers will
be created. Note that in this case, records and access to records behave the
same. Thus the following binding:

package Pckg is

   type Contained_Record is null record;

   type R is record
      F1 : Contained_Record;
      F2 : access Contained_Record;
   end R;
   
end Pckg;

will give:

package Pckg;

public final class R {

   public R () {/* binding code */}
   
   public void F1 (Contained_Record Val) {/* binding code */}

   public Contained_Record F1 () {/* binding code */}
   
   public void F2 (Contained_Record Val){/* binding code */}
   
   public Contained_Record F2 () {/* binding code */}

}

Of course, Contained_Record will have to be bound separately as well. 

Access to access of record are not supported. Only one level of indirection
is.

Private (non tagged) types behave as record type, except that they do not
have any field accessors/modifiers.

**********************
** Global variables **
**********************

Global variables generate a set of accessor modifier stored in the default
package class. Global constants generate only an accessor to their value. For
example:

package Pckg is
   V1 : Integer;
   V2 : constant Integer;
end Pckg;

will be bound in:

public final class Pckg_Package {
   public static void V1 (int Val) {/* binding code */}

   public static int V1 () {/* binding code */}
   
   public static int V2 () {/* binding code */}
}

*****************
** Subprograms **
*****************

Ada procedures and functions are bound into Java functions. Non dispatching
subprograms are qualified "final". We'll see the case of dispatching 
subprograms in the chapter explaining tagged types.

****************************
** Subprograms parameters **
****************************

In order to simplify the binding process, the supported parameters kinds is 
restricted to the following:

 ** Scalar types **
 
 * Access to scalar types are not supported.
 
 * "in" mode scalar types are mapped into the corresponding Java types, for 
  example:
  
  procedure P (V : Integer);
  
  will create:
  
  public void P (int V) {/* binding code */}
  
 * "out" and "in out" modes will be mapped using a intermediate encapsulating
  class. There are four references classes, BooleanRef, CharacterRef, 
  DoubleRef and IntegerRef, each of them encapsulating one of the bound
  primitive type (respectively boolean, character, double and int).
  
  These class are provided with a setValue and getValue function, accessing and
  modifying the encapsulated value. In order to respect Ada semantics, this
  value will possibly change during the call.
  
  ** Object types **
  
  Object types includes bindings of records, tagged records and private types.
  
  * "in", "out", "in out", "access" modes and access to a type directly mapped
    in a class are all bound as a java direct references. For example, the 
    following code:
    
    type R is null record;
    
    type R_A is access all R;
    
    procedure P (V1 : R; V2 : out R; V3 : in out R; V4 : access R; V5 : R_A);
    
    will be bound in:
    
    public static void P (R V1, R V2, R V3, R V4, R V5) {/* binding code */}
 
  * "out" and "in out" modes to an access to a type are bound using an 
    intermediate enclosing class, generated within the initial type. For 
    example:
    
    type R is null record;
    
    type R_A is access all R;
    
    procedure P (V : out R_A);
    
    will be bound into:
    
    public void P (R.Ref V) {/* binding code */}
    
    the "Ref" classes are coming with a setValue and getValue functions which 
    are accessing the enclosed value.
  
  * Further indirection, such as access to access type, are not supported.
  
**************************
** Subprograms location **
**************************

By default, non dispatching subprograms can be placed in the default package 
class, like global variables. Thus the following binding:

package Pckg is
   
   type R is null record;
   
   procedure P (V : R);
   
end Pckg;

becoming:

public final class R {
}

public final class Pckg_Package {
   public void P (R V) {/* binding code */}
}

It's however tempting to try to put them in the "right" class, and make them
member functions of this class. There's unfortunately no "natural" nor "right"
way of doing that - solutions proposed are heuristics trying to make sense in
some/most cases. Therefore, all rules proposed below are by nature optional, 
and should not replace the general solution described above. But they have been 
proven useful in the first context of the use of the tool and should be 
enablable.

We'll consider that a subprogram is a member of a class if:
	- The first parameter of the subprogram is either a private type or a 
	  record type.
	- This parameter can be bound into a direct reference (see the paragraph
	  about subprogram parameter for more details).
	- The type of this subprogram - or the accessed type if it's an access - is
	  declared in the same unit.
	  
A subprogram that is eligible according to these criterias will be made 
accessible from the class resulting of the first parameter type binding, and 
the value of this first parameter will come from the hidden parameter "this".
	  
Therefore, the previous example will give:

public final class R {
   public final void P () {/* binding code */}
}

Note that there are known semantics limitations to this model, in particular in
the case of access types. In this example:

package Pckg is

   type R is null record;

   type R_A is access all R;
   
   procedure P (V : R_A);
   
end Pckg;

we will generate:

public final class R {
   public final void P () {/* binding code */}
}

And calls will look like:

R v = new R ();
v.P ();

Therefore, it will not pe possible to pass null to this subprogram, while it's
accepted by Ada semantics. That's why the initial bound procedure is kept, 
letting possible to write:

Pckg_Package.P (null);

******************
** Tagged types **
******************

Tagged types are mapped into Java classes. If the Ada type is abstract, then
the Java type will be abstract as well.

Dispatching primitives of tagged types are bound into Java function members
of that class. Right now, a bound primitive has to have at least its first 
parameter controlling. For example:

type R is tagged record;
   
procedure P (C : R);
   
will give:

public class R {
   public void P () {/* binding code */}
}

Class-wide parameters are bound into references to the Java bound class. The 
same record types rules described in the previous chapter are applicable for
them.

   ** Ada hierachies **
   
   Ada hierachies of types are preserved in the Java binding. Therefore, the
   following structure:
   
   type R is tagged record;
   
   type R_Child is new R with null record;
   
   Will give:
   
   public class R {
   }
   
   public class R_Child extends R {
   }
   
   Consistency of java types is garanteed at runtime, the actual proxy
   used to represent a class is determined dynamically in the case of an
   ambiguity. For example, the following function:
   
   package Pckg is
      function F return R'Class;
   end Pckg;
   
   will be bound into:
   
   public final class Pckg {
      public R F () {/* binding code */}
   }
   
   However, if the actual type of the returned object is of type R_Child, then
   the proxy returned by the Java function will be also of type R_Child.

   ** Java derivation **

  It's possible to derive the result of a tagged type binding in Java, and then
  use it from the Ada code. For example, after having bound:

  package Pckg

     type R is tagged record;
   
     procedure P (C : R);

     procedure Call_P (C : R'Class);

  end Pckg;

  we can write:

  class R_Child extends R {
 
     public void P () {
        System.out.println ("Hello from Java");
     }

  }
 
  And then use the code in the following way:

  R var = new R_Child ();
  Pck_Package.Call_P (var);

  If Call_P is indeed calling P, this call will print "Hello from Java".

  ** Java references consistency **

  When a java class is derived from derives an Ada bound type, the created Ada 
  object will keep a reference to its java proxy. This is not the case for non 
  java derived objects. So, for example, with:

  package P is
     type R is tagged null record;

     function Return_This (This : R'Class) return R'Class;
  end P;

  paclage body P is
     function Return_This (This : R'Class) return R'Class is
     begin
        return This;
     end Return_This;
  end P;

  and, on the Java side:

  class R_Child extends R {
  }

  R r1 = new R ();
  R r2 = new R_Child ();
  
  the following is true:

  r1 != P_Package.Return_This (r1)
  r2 == P_Package.Return_This (r2)

  As a result, java extensions can add additional fields, which value will not 
  be lost by Ada processing.

  Note that even if the references are not always the same, the equality
  between the references values is kept. These two conditions are true:

  r1.equals (P_Package.Return_This (r1))
  r2.equals (P_Package.Return_This (r2))

  ** Non-first controlling parameter **

  If the first parameter is not controlling, the binding generator will 
  refuse to bind the type (and thus - of course - the primitive as well). 
  That's because in Java, the controlling parameter is always the first 
  (hidden) one. There are however possible solutions to workaround that:

     - Refactor the function in the java side, moving the controlling
       parameter in the front.
     - Add a dummy first controlling parameter.
          
  So for this Ada code

  type R is tagged record;
   
  procedure P (V : Boolean; C : R);

  either of the following binding is possible:

  public class R {
     public void P (boolean V) {/* binding code */}
  }
   
  public class R {
     public void P (boolean V, R C) {/* binding code */}
  }
   
  None of them is fully satifactory - the first one is doing a non-trivial
  refactoring, and breaks the order wanted by the original developper, and the
  second one is introducing a redundancy - we have to decide wether the actual
  parameter is "this", "C", if the two have to be equals...

  Given the problem brought by the two solutions, this construction is 
  currently considered out of the range of the Ada / Java binding.
  
  ** Ada.Finalization.Controlled **
  
  It is possible to bind and derive in Java a type that is a descendent of 
  Ada.Finalization.Controlled. However, in this case, if there is an overridden 
  version  of the Initialize subprogram in Java, it won't be called at the Ada 
  object creation, only the one coming from Ada will be.

*****************************
** Accesses to subprograms **
*****************************

Access to subprograms - sometimes named callbacks - are not trivially mapped 
into Java. It is not possible to give a reference to a java function in a type
safe fashion. There is however a possible workaround for that: passing 
the implementation of an abstract type with an abstract member of the correct
profile. The following can be bound:

type P_Acc is access all procedure (V : Integer);

procedure Call_P_Acc (Proc : P_Acc);

into:

abstract public class P_Acc {
   abstract public P_Acc_Proc (int V);
}

void Call_P_Acc (Proc : P_Acc);

and used in e.g. the following scenario

Proc p = new Proc () {
   
   public P_Acc_Proc (int V) {
      System.out.println ("CALLED WITH " + V);
   }

};

Pckg_Package.Call_P_Acc (p);

There is a non-trivial limitation using this method. On the Ada side, the 
parameter cannot reference anything but an access to a procedure, while what
we really would need is a reference to a Java object. As a result, such 
callbacks can only be called by the Ada code, not stored. Storing such an 
access to procedure and calling it outside the initial call lifetime will 
likely generate a memory corruption. The obvious workaround is the 
modification of the Ada specification, using an Ada tagged type instead of the 
subprogram access type.

*************
** Strings **
*************

Strings are problematic in Ada / Java binding since they require expensive
copy from one side to the other. Therefore, a new type called AdaString has
been created in order to encapsulate such a value.

Strings, access to strings, "in", "in out" and "out" parameters are mapped 
into this type. As we've done with records, "in out" and "out" parameters are
typed as an access to string are using an encapsulation class, AdaString.Ref.

For efficiency, AdaStrings are caching both their Ada and Java values once 
computed. Therefore, if we have the following code to bind:

package Pckg is
   procedure P (V : String);
end Pckg;

we'll have in the Java side:

public final class Pckg_Package {
   public static void P (V : AdaString) {/* binding code */}
}

And if we write:

AdaString str = new AdaString ("A string from Java");
Pckg_Package.P (str);
Pckg_Package.P (str);

Only the first call will require to do the expensive string translation from 
the java UTF-16 strings to the Ada ASCII ones. The second one will direcly use
the cached value.

************
** Arrays **
************

Mapping Ada arrays into Java arrays would be a very expensive solution - since
it would imply a copy of the whole array each time a parameter has to be passed
as opposed to a passing a reference as Java and Ada are doing most of the time.
In order to avoid this kind of performance loss, Ada arrays are bound into
java with dedicated proxy classes. Relevant accessors to attributes and 
components will be generated. For example:

type An_Array is array (X : Integer) of Integer;

will give the following class:

public final class An_Array {

   public void Set_Element_At (int Pos, int Value) {/* binding code */}
   
   public int Get_Element_At (int Pos) {/* binding code */}
   
   public int Length () {/* binding code */}
   
   public int First () {/* binding code */}
   
   public int Last () {/* binding code */}

}

Anonymous arrays are not currently supported.

******************************
** Other consistency issues **
******************************

* Null Ada values will be translated into null java values, and the other way
 around. If a null value is given for a parameter that is not an access type, 
 an exception will be raised.

* Ada exception will be translated to Java as Java exceptions, and the other
 way around.

* Two java references encapsulating the same Ada object may or may not be equals
 regarding the java equality operator ("=="). But they have to be equals 
 regarding the java standard equals function, except if the corresponding ada
 equals operator have been redefined and does not return true for equals 
 objects.

*****************
** Limitations **
*****************

* Generics are not supported. Any subprogram profile or variable containing
a reference to a generic will be passed.

* Interfaces are not supported.

* Tasks and protected types are not supported.
