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.

511bglobal variables 298a+   (297 478b 507 539b)  508d  512a
%DOMAINS=();
%CATEGORIES=();
%EXTENSIONS=();

Defines:
CATEGORIES, used in chunks 510, 513, and 516.
DOMAINS, used in chunks 510, 513, 516, and 517.
EXTENSIONS, used in chunks 510, 513, 517, and 521.

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.

512aglobal variables 298a+   (297 478b 507 539b)  511b  539a
%USES=();

Defines:
USES, used in chunks 510b, 513, 516, and 521.
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.

512bconstructor name regular expression 317+   (308 318 501a 513)  501b
[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.

513extract constructor definitions and uses 513  (511a)
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 317)/) {
            $CATEGORIES{$1}=$libfile;
            $line=$’;
        } elsif (/^extend\s+(constructor name regular expression 317)/) {
            $EXTENSIONS{$1}=$libfile;
            $line=$’;
        } elsif (/^(constructor name regular expression 317)/) {
            $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 317\b)/){
                $line=$’;
                if ($1 ne ’Rep’) {$USES{$libfile}{$1} = 1;}
            } else {
                $line = ’’;
            }
        }
    }
    close(ASFILE);
}

Defines:
extractConstructorDefinitionsAndUses, used in chunk 509b.

Uses CATEGORIES 511b, check 357, DOMAINS 511b, EXTENSIONS 511b, LIB 445, PROJECTROOT 350, and USES 512a.