articleUnderused expanded types

Using expanded types for enumerations or aliased type names:

expanded class MY_ENUMERATION
convert
 value: {INTEGER_32}
feature
 make (value_a: INTEGER_32)
  do
   value := value_a
  end
feature
 value: INTEGER_32
end

It's as simple as that. Pass around MY_ENUMERATION and you have an efficient type that can be used like an enumeration or an aliased type name.

Using expanded types for constants:

expanded class MY_CONSTANTS
feature
 red: INTEGER_32 = 1
 blue: INTEGER_32 = 2
 green: INTEGER_32 = 3
end

The class MY_CONSTANTS has no members, so it has no size and therefore no state. It can be used in a local or as a class attribute such as the following:

feature
 constants: MY_CONSTANTS
 
 test
  local
   constants_2: MY_CONSTANTS
  do
   if constants.blue = constants_2.blue then
    io.put_string ("The same")
   end
end

This is an alternative to using inheritance to pull in constants.

A small modification on the above to provide functions

expanded class NATURAL_32_FACILITIES
feature
 rotate_right (value: NATURAL_32; count: INTEGER_32): NATURAL_32
  do
   Result := (value |>> count).bit_or (value |<< (32 - count))
  end
end

These facilities can be used like:

feature
 rotation: NATURAL_32_FACILITIES
 test
  local
   rotation_2: NATURAL_32_FACILITIES
  do
   if rotation.rotate_right (0x3, 1) = rotation_2.rotate_right (0x6, 2) then
    io.put_string ("Successful")
   end
end

Expanded types can be used for output variables by creating an ADT out of the output variables. Take a division function that does a 2 machine word numerator and denominator and gives a 2 machine word quotient and remainder. A c-style way to represent this is:

div (unsigned n, unsigned d, unsigned * q, unsigned * r)

By translating the output variables in to an ADT and making the routine a creation procedure you get an Eiffel equivalent:

expanded class DIVISION_RESULT
feature
 make (n: NATURAL_32; d: NATURAL_32)
  do
   --...
  end
 q: NATURAL_32
 r: NATURAL_32
end

In general if you have a C routine with input parameters pi_1 ... pi_j and output parameters po_1 ... po_j. Move parameters po_1 ... po_j in to attributes of your new expanded class E. Move the C routine in to E as a creation procedure taking in input parameters pi_1 ... pi_j and writing outputs to attributes of the expanded class.

Creation procedures on expanded types can be called statically by the compiler and static calls can be inlined. Using this expanded class ADT method, expanded classes can behave identically to C routines with output parameters when not inlined, or even C macros when the creation procedure is inlined.

Using this pattern allows one to have output parameters that are attached, via CAPs applied in the expanded type's creation procedures. Since this type is expanded it has a performance equivalent to output parameters.

Note: In the current Eiffel Studio compiler implementation, expanded types have a header which isn't really needed. This means expanded types have some size and initialization when they really shouldn't have to; this is an optimization that could be applied.

The current ECMA language specification requires a default_create procedure to be defined. This restriction could be loosened to be: "expanded types must have a default_create creation procedure, or be initialized on creation as class attributes" "expanded types must have a default_create creation procedure or be initialized prior to use as feature locals". This gives backwards compatibility to expanded objects created with default_create and doesn't force a default value of an expanded type which is restrictive especially in void-safe environments.

Syndicate content