38.1 Extract Constructor Definitions and Uses

We check for domain/package and category definitions and domain extensions. These names are put into into the global variables DOMAINS, CATEGORIES, and EXTENSIONS.

The variables collect the filenames where the corresponding category, domain, or package is defined or extended. The key is the constructor. The corresponding value is a filename where the constructor is defined/extended.

508aglobal variables 294a+   (293 474b 503 536b)  504d  508b
%DOMAINS=();
%CATEGORIES=();
%EXTENSIONS=();

Defines:
CATEGORIES, used in chunks 506, 510, and 513.
DOMAINS, used in chunks 506, 510, 513, and 514.
EXTENSIONS, used in chunks 506, 510, 514, and 518.

The variable USES collects the uses of constructor names. For the regular expression of a constructor name see below. $USES{$libfile}{$constructor}=1 says that the $constructor is mentioned in $libfile.

508bglobal variables 294a+   (293 474b 503 536b)  508a  536a
%USES=();

Defines:
USES, used in chunks 506b, 510, 513, and 518.
Convention 26 Names of type constructors like categories, domains and packages must start with a capital letter and followed by alphanumeric characters. Constructor names are at least 2 characters long and must at least contain one lower case character. The special name Rep is not considered to be a constructor.

The following Perl regular expression is used to detect constructor names in a source file.

Note that we work here with the same regular expression as in Section 26.4.

509constructor name regular expression 313+   (304 314 497a 510)  497b
[A-Z][a-zA-Z0-9]*[a-z][a-zA-Z0-9]*
Convention 27 If a constructor name is defined with different types, for example,
DomA(R: Ring, n: Integer): ...  
DomA(m: MachineInteger): ...

then such definitions must occur in the same file.

We skip ++ and -- comments. There is no danger that a constructor name is detected because it appears inside a string constant. String literals are removed and it is taken care of the escape character inside the string so that _" (underscore+double quote) will not falsely end a string.

510extract constructor definitions and uses 510  (507b)
sub extractConstructorDefinitionsAndUses {
    my($file, $LIB) = @_;
    my($libfile)="$LIB $file";
    my($line)="";
    if ($file =~ /([^ ]+) (\w+)/) {$file=$1;}
    $file="$PROJECTROOT/$file";
    open(ASFILE, "${file}.as") ||\
        die "Error: dependencies.pl cannot find ${file}.as\n";
    while (<ASFILE>) {
        if (/^define\s+(constructor name regular expression 313)/) {
            $CATEGORIES{$1}=$libfile;
            $line=$’;
        } elsif (/^extend\s+(constructor name regular expression 313)/) {
            $EXTENSIONS{$1}=$libfile;
            $line=$’;
        } elsif (/^(constructor name regular expression 313)/) {
            $DOMAINS{$1}=$libfile;
            $line=$’;
        } else {
            chomp; #remove newline
            $line=$_;
        }
        # Now let’s check for uses in the current line.

        # First remove string literals and take care of _ escapes.
        $line =~ s/([^"]*)("([^"_]|_.)*)"/$1/g;
        # Then remove comments.
        $line =~ s/(\+\++|--+).*//g;

        while ($line) {
            if ($line=~/(\bconstructor name regular expression 313\b)/){
                $line=$’;
                if ($1 ne ’Rep’) {$USES{$libfile}{$1} = 1;}
            } else {
                $line = ’’;
            }
        }
    }
    close(ASFILE);
}

Defines:
extractConstructorDefinitionsAndUses, used in chunk 505b.

Uses CATEGORIES 508a, check 353, DOMAINS 508a, EXTENSIONS 508a, LIB 441b, PROJECTROOT 346, and USES 508b.