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.
508a⟨global 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.
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.
510⟨extract 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=~/(\b⟨constructor 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.