38.3 Add Extensions to the Dependency Graph

If a domain D is defined in a file d and extended in a file e then the above code will not yet have added the fact that e depends on d.

514add extend dependencies 514  (507b)
sub addExtendDependencies {
    my($file, $LIB) = @_;
    my($LIBfile)="$LIB $file";
    my($constructor);
    for $constructor (keys %EXTENSIONS) {
        if (exists($DOMAINS{$constructor})) {
            # The domain is defined in the project library.
            &setDependency($EXTENSIONS{$constructor}, $DOMAINS{$constructor});
        }
    }
    insert extensions at the best possible place 518
}

Uses DOMAINS 508a, EXTENSIONS 508a, LIB 441b, and setDependency 512.

Without the help of a proper Aldor parser, the task of finding the right dependencies if extensions are involved is impossible. Assume there are two files x and y with the following content.

--file x  
#include "aldor"  
define Cat1: Category == with {foo1: ()->()}  
extend Integer: Cat1 == add {import from String; ...}

--file y  
#include "aldor"  
define Cat2: Category == with {foo2: ()->()}  
extend String: Cat2 == add {import from Integer; ... foo1() ...}

Clearly, the file x should be compiled before y. However, the code we are presenting below does not necessarily get the dependency right, because it only looks for constructor names. So the information that the name foo1 is used in y is not taken into account. Note that it would be even hard to find out for a simple Perl program whether the appearance of foo1 really refers to an implementation of Cat1 in Integer or an implementation in yet another domain that comes from another file.

Convention 28 In order to resolve problematic code as given above, it must appear in one file or in the file x should appear a definition of a category, domain, or package that is used in the file y.

A simpler problematic case is

--file x  
#include "aldor"  
extend Integer: with {foo: ()->()} == add {import from Dom; ...}

--file y  
#include "aldor"  
Dom: Cat == add {import from Integer; ...}

where y would have to be compiled before x. This case, however, is resolved correctly already by the code above, since the identifier Dom appears explicitly as a use in x.

We try to place the extension of domains as early as possible into the compilation chain.

If a domain A is extended in a file x and A is used in a file y, then y depends on x if and only if x does not depend on y for some other reasons. For example, y could have defined a domain B which is used in x.

In order to find whether or not x already depends on y we simply saturate the dependencies that have been computed so far and then we check whether $DEP{x}{y} is zero.

518insert extensions at the best possible place 518  (514)
for $constructor (keys %{$USES{$LIBfile}}) {
    if (exists($EXTENSIONS{$constructor})) {
        $file = $EXTENSIONS{$constructor};
        my(@circular) = &saturateDependencies($file);
        if (scalar(@circular) > 0) {return}
        if ($DEP{$file}{$LIBfile} == 0) {
            &setDependency($LIBfile, $file);
        }
    }
}

Uses DEP 504c, EXTENSIONS 508a, saturateDependencies 521, setDependency 512, and USES 508b.
ToDo 26 Rewrite the following section. And check the code.

The treatment of extensions is problematic.

Convention 29 For a domain that is defined within the library there can only be one extension inside the same library and this extension must be defined in a separate file.

For a domain, like MachineInteger, for example, that is not defined in the same library, it is not necessary to put it into a separate file. However, also in this case there can be only one extension.

How do we resolve dependencies? Assume there are 3 domains A, B, and C defined in the files a, b, and c respectively. Both in b and c the domain A is mentioned, so we easily find that c and b depend on a. Now there is a file athat extends A and uses B but not C for this extension. So adepends on a and b. In such a case, we add a dependency, namely c depends on a. It basically means that we place extensions in the dependency hierarchy as early as possible.

ToDo 27 Names that start with a capital letter can be extracted from the parsed source. No library is needed, but one must have the include files.
aldor -fap cip.as  
sed -e ’s/([^ ]*\|)//g;s/ */\n/g;’ cip.ap |sort|uniq|grep ^[A-Z]