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.
511b⟨global 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.
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.
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.
513⟨extract 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=~/(\b⟨constructor 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.