Current implementation of multi constraint formals

Revision as of 13:33, 15 March 2007 by Seilerm (Talk | contribs) (EXTENDED_TYPE_A)

Warning.png Warning: Warning: Article under development

Introduction

The first implementation of multi constraints is done and this article describes its current implementation status.

Let's take this example

MULTI[G -> {H, COMPARABLE rename is_equal as is_equal_cmp end},
      H -> {NUMERIC rename default_create as default_create_num end, G}]

A type satisfying the constraint of G has the following properties:

  • It conforms to whatever H is and therefore
    • to NUMERIC and
    • by recursion to itself (G)
  • It conforms to its second constraint which is COMPARABLE.


A type satisfying the constraint of H has the following properties:

  • It conforms to NUMERIC.
  • It conforms to G and therefore

As G and H both have to conform to each other the only possibility to satisfy this is that G and H must be the same in the generic derivation. It does not make much sense to program something like that but it is part of the current implementation.

Feature calls

Let's have a look at the following feature written in class MULTI:

feature
    g: G
 
    f: BOOLEAN
            -- Sample feature
        do
            create g -- 1
            Result := g.is_equal(g) -- 2
        end

The following rules have to hold for each call on a multi constraint formal:

  • Every feature which is called has exactly one class which is used as the static type for the call.

This is a major difference to the ECMA standard which allows a call to features which are available through different classes as long as it is the same feature. A definition of what the same feature means can be found here.

In order to achieve that goal if a feature occurs with the same name in different classes one uses a rename clause and renames that feature. If there are name clashes between features and one does not want to call that feature a renaming is not needed.

As we perform calls to default_create (line 1 of f) and is_equal (line 2 of f, which are both features from ANY and each occurs as the same feature once in COMPARABLE and once in NUMERIC. We do this despite the fact that it is actually the same feature. The reason for this can be found in the new semantics of the dynamic binding described in the standard. You may also want to have a look at the following article which discusses the issue.

Renaming on formals

The current implementation rejects a rename clause which is applied to a formal. The following code is therefore currently rejected as H is a formal and we don't allow a renaming on it.

class MULTI[G -> {H rename is_equal as is_equal_prime end, ANY}, H -> ANY]

The rules implemented are chosen so that they are the most restrictive. This is to ensure that written code is likely to compile in the future where the rules might be more relaxed.

Implementation details

The central classes to the current implementation are:

  • TYPE_SET_A
  • EXTENDED_TYPE_A
  • RENAMING_A
  • CONSTRAINING_TYPE_AS
  • and some changes to CLASS_C

The main tasks which have to be performed are:

  • Type checking in particular type conformance.
  • Feature lookup

Both tasks are provided by TYPE_SET_A.

TYPE_SET_A

Conformance

The feature conform_to inherited from TYPE_A can be used to check whether a type set conforms to another type which is possibly a type set as well.

  • A type set conforms to another type if at least one type in the type

set conforms to the type.

  • Another type conforms to a type set if it conforms to all types in the type set.
  • A type set ts1 conforms to a type set ts2 if for each type t in ts2 there is at least one type in ts1 which conforms to t.

If every type is regarded as a type set with one element one can simply always use the last rule.

Feature lookup

There are various features which provide this functionality. Their differences are mostly in the amount of information they provide. Of course the computation gets more expensive if the feature returns more information. Currently the API is pretty much targeted to what the compiler needs. There's a bunch of features of the family e_feature_state_*/feature_i_state_* which are used when most likely only one feature occurs. As soon as you need more information the features of the family info_about_feature_* can help you to get all information about a certain feature for a given type set.

Associated class

This feature is no longer available and therefore exported to NONE. This is simply because there is no single associated class but many. You can use the feature associated_classes instead and get a list of all associated classes. However, the features applicable to the type set is not the same set as the features provided by each element of the associated_classes. This is because one loses the renaming (class RENAMING_A) which is stored inside the TYPE_SET_A in each EXTENDED_TYPE_A instance. This is why there are some places in the code where going from a CLASS_C instance to one of type LIST [CLASS_C] is not enough.

EXTENDED_TYPE_A

The EXTENDED_TYPE_A class basically encapsulates a TYPE_A object and a RENAMING_A object.

The fact that it is conform to TYPE_A opens the door for mistakes: Make sure that you use
{EXTENDED_TYPE_A}.type</a> or <e>{EXTENDED_TYPE_A}.actual_type</a> if your code makes assignment attempts, it is pretty much the same as with the family of the "like" types.
 
===RENAMING_A===
This is the class which provides features to handle the renaming which is applied to the features of the constraint type.
 
It's current implementation is based on a hash table and therefore only one way is efficient.
 
You can find out whether a specific feature is renamed by calling <e>is_feature_renamed
. There's also a predefined feature renamed which takes an integer argument and returns another one. The integer returned is either
  • unchanged, if the feature is not renamed
  • some other positive integer if the feature is renamed under the renaming
  • -1 if the feature was renamed into something else (therefore it is not accessible)

However, this is only relative to the renaming and is not in the context of a specific class. It means that if the feature f does not occur in the class you don't get an error (-1), as RENAMING_A does not consult a context class for its operations.

CLASS_C

A major change here affects the feature constraint (i: INTEGER): TYPE_A. It is used to get the constraint of the formal at position i. A new precondition has been added which states that it is only ok to call that feature if the formal has only one constraint. This is also the reason why currently it is not allowed to apply a renaming to a single constraint. For the multi constraint case the feature constraints (i: INTEGER): TYPE_SET_A should be used instead. It returns a TYPE_SET_A instance which can possibly contain other formals.