Implementation of Java/.NET to BETA converters

The two converters are implemented in basically the same way:

The mapping can be outlined as below. The term class is used to denote both classes, types, interfaces below, unless otherwise stated.

  1. First a scan for all refered classes is done in order to collect a list of other BETA files to INCLUDE. This is decribed in more detail in Include Handling.
  2. Then all fields of the class class is processed. This is described in more detail in Fields.
  3. Then all constructors of the class class is processed. This is described in more detail in Constructors.
  4. Then all methods of the class class is processed. This is described in more detail in Methods.
  5. Then nested classes (java: inner classes) of the class class is processed. This is described in more detail in Nested Classes.
  6. Finally the tools check to see if any of the refered classes mentioned needs conversion. If so, these are converted in the same manner.
For the .NET platform a special kind of mapping is needed for the value types and enumeration types, which does not have direct counterparts in Java. This is described in more detail in Value Types and Enums.

Include Handling

...

Fields

...

Constructors

...

Methods

...

Nested Classes

...

Value Types and Enums

Value types (and enums) is a .NET speciality not found in Java. Basically value types er the equivalent of structs known from, e.g. C/C++. That is an untyped blob of memory which has copy-by-value semantics.

In .NET valuetypes are used for "small" objects, which need not have instance-identity. The primary reason for this is efficiency. All primitive types (e.g. all the integer types) are value types. All value types are directly derived from System.ValueType, which derives directly from System.Object. A special exception to this rule is System.Enum, which is the base class of all enumeration types, and which derives directly from System.ValueType:

  System.Object
     |
     `- System.ValueType
            |
            `- System.Enum
...

Mapping ValueTypes

Value types are mapped by dotnet2beta to a specialization of ExternalClass, but using a @ as an indicator in the className to tell the compiler that this is to be treated specially. Example:
DateTime: ExternalClass
  (#
     _init_int64: cons 
       (# result: ^DateTime;
          arg1: @int64;
       enter (arg1)
       exit result[]
       #);
     ...
     get_Month: proc
       (# result: @int32;
       exit result
       #);
     ...
     ToFileTime: proc
       (# result: @int64;
       exit result
       #);
     ...
  do '@valuetype [mscorlib]System.DateTime' -> className;
  #);
This example ValueType has a private int64 instance field, which is not exposed in the ExternalClass declaration, since you cannot access a private field.

ECMA 335 defines how to call methods on value types in section 12.1.6.2.4:

Static methods on value types are handled no differently from static methods on an ordinary class: use a call instruction with a metadata token specifying the value type as the class of the method. Non-static methods (i.e. instance and virtual methods) are supported on value types, but they are given special treatment. A non-static method on a class (rather than a value type) expects a this pointer that is an instance of that class. This makes sense for classes, since they have identity and the this pointer represents that identity. Value types, however, have identity only when boxed. To address this issue, the this pointer on a non-static method of a value type is a by-ref parameter of the value type rather than an ordinary by-value parameter.

A non-static method on a value type may be called in the following ways:

  • Given an unboxed instance of a value type, the compiler will know the exact type of the object statically. The call instruction can be used to invoke the function, passing as the first parameter (the this pointer) the address of the instance. The metadata token used with the call instruction shall specify the value type itself as the class of the method.
  • ...
The special valuetype indicator allows to compiler to emit the special ldflda / ldarga / ldloca instructions to load the address of the value before issuing the call instruction, when calling methods on such ValueTypes.

Mapping Enums

ECMA 335 lists a number of special rules about enums in section 8.5.2:
The CTS supports an enum (also known as an enumeration type), an alternate name for an existing type. For purposes of matching signatures an enum shall not be the same as the underlying type. Instances of an enum, however, shall be assignment compatible with the underlying type and vice versa. That is: no cast or coercion is required to convert from the enum to the underlying type, nor are they required from the underlying type to the enum. An enum is considerably more restricted than a true type:
  • It shall have exactly one instance field, and the type of that field defines the underlying type of the enumeration.
  • It shall not have any methods of its own.
  • It shall not implement any interfaces of its own.
  • It shall not have any properties or events of its own.
  • It shall not have any static fields unless they are literal
  • The underlying type shall be a built-in integer type.
  • Enums shall derive from System.Enum, hence they are value types. Like all value types, they shall be sealed
Problems:
  1. How to declare? Currently as an ExternalClass:
    FileAttributes: ExternalClass
      (#
         ReadOnly:
           (# exit 1 #);
         Hidden:
           (# exit 2 #);
         System:
           (# exit 4 #);
         ...
      do '@valuetype [mscorlib]System.IO.FileAttributes' -> className;
      INNER;
      #);
    
  2. Formal ValueType parameters: how to declare them?
    1. As a dynamic reference?
      somefunction: proc
        (# attr: ^FileAttributes #)
      
      Problem: How to call FileAttributes.ReadOnly->somefunction.
    2. As an integer?
      someFunction: proc
        (# attr: @int32;
        do 'someFunction'->procname
        #)
      
      Problem: Signature for somefunction constructed by BETA compiler will be wrong, since the type of the parameter will become [mscorlib]System.Int32, whereas it should be [mscorlib]System.IO.FileAttributes. Example: GENERATOR/BYTECODE/TEST/hellobox.bet shows an example of this problem (a MessageBox.Show call, where the last two parameters are integers instead of enum types, and where the signature becomes wrong)
      Possible fix: Specify full signature for procname. Compiler will need a way to determine if the procname was full or partial. Scan for parenthesis? Special character?
    3. As a static reference?
      somefunction: proc
        (# attr: @FileAttributes #)
      
      Problem: FileAttributes must be declared with enter/exit part. Probably FileAttributes must derive from some special pattern Enum declared in betaenv?

  3. Integer binary operations must be possible on Enums. E.g.
    do myFile.getAttributes %Band FileAttributes.ReadOnly = FileAttributes.ReadOnly
         -> fileIsReadOnly;
    
    Possible solution 1: Treating enums as static references (as suggested above) in BETA will probably handle this.
    Possible solution 2: Find a way to cast an enum value to integer. Using a special myEnumValue.%asInt32 primitive (should generate no code, except loading the enum to the stack - as noted above in the ECMA quote, no cast/coersion is needed in the generated code: the enum is fully compatible with the underlying type).