Next: Support code
Up: Phrase Structure
Previous: Productions from 15: Expressions
A Cluster is a set of compilation units that is complete with
respect to inheritance:
Compiling multiple compilation units[53]
:
Goal:
Cluster .
Cluster:
ClusterElement / Cluster ClusterElement .
ClusterElement:
(CompilationUnit 'EndOfFile')+ 'NoFilesPending' .
This macro is invoked in definition 38.
No compilation unit in the Cluster may inherit from a type available
only in source form unless it is also a member of the Cluster.
Unfortunately, the cluster is defined dynamically.
If name analysis of the cluster reveals undefined types,
the compiler must seek additional compilation units defining those types.
In order to avoid this feedback from the name analysis, we obtain all
files from packages mentioned in import declarations.
NameStack holds the components of a (qualified) name that might appear
in a package or import declaration.
Instantiate necessary modules[54]
:
$/Adt/Stack.gnrc +instance=Name +referto=int :inst
This macro is defined in definitions 54, 59, and 66.
This macro is invoked in definition 13.
InName is true when the parser is within an interesting name, and false
otherwise:
State of import name collection[55]
:
static int InName = 0;
This macro is invoked in definition 67.
Two routines collect each name:
void StartName(void)[56]
:
/* Start collecting the identifiers of a (qualified) name
* On entry-
* The next identifier is the first in an interesting name
* On exit-
* NameStack is empty
* InName is true
***/
{ while (!NameStackEmpty) NameStackPop;
InName = 1;
}
This macro is invoked in definition 67.
void GotNameId(int id)[57]
:
/* Collect an identifier if necessary
* If InName on entry-
* NameStack contains the previous identifiers of the name
* If InName on exit-
* The name indexed by id has been added to NameStack
***/
{ if (InName) NameStackPush(id);
}
This macro is invoked in definition 67.
When the parser reaches the end of the name, it is handled in a manner
dependent on the context:
GotPackageImport(void)[58]
:
/* Handle a package import
* On entry-
* NameStack contains the complete sequence of identifiers for a name
* On exit-
* InName is false
***/
{ if (NameStackSize >= 1) {
int idn = FQName();
Binding bind = BindInScope(PkgRootEnv, idn);
if (!HasTypScope(KeyOf(bind)))
ImportPackage(StringTable(idn), KeyOf(bind));
}
InName = 0;
}
This macro is invoked in definition 67.
PkgRootEnv is defined as an environment with Algol scope rules, because
each package is visible throughout the compilation:
Instantiate necessary modules[59]
:
$/Name/AlgScope.gnrc +instance=Pkg +referto=Pkg :inst
This macro is defined in definitions 54, 59, and 66.
This macro is invoked in definition 13.
The Package property of a package is an environment with one binding
for each type defined in the package.
That binding's identifier is the simple name of the type, and its key is
the key for the fully-qualified type.
Properties and access functions[60]
:
TypScope: Environment [Has]; "envmod.h"
This macro is defined in definitions 60.
This macro is invoked in definition 65.
void GotTypeImport(void)[61]
:
/* Handle a type import
* On entry-
* NameStack contains the complete sequence of identifiers for a name
* On exit-
* InName is false
***/
{ if (NameStackSize >= 2) {
int idn = FQName();
Binding bind = BindInScope(TypRootEnv, idn);
ImportType(StringTable(idn));
}
InName = 0;
}
This macro is invoked in definition 67.
In both cases, the content of the name stack must be used to construct a
fully-qualified name:
{ int i;
for (i = 0; i < NameStackSize; i++) {
char *s = StringTable(NameStackArray(i));
if (i > 0) obstack_1grow(Csm_obstk,'.');
obstack_grow(Csm_obstk, s, strlen(s));
}
obstack_1grow(Csm_obstk,'\0');
CsmStrPtr = (char *)obstack_finish(Csm_obstk);
return MakeName(CsmStrPtr);
}
This macro is invoked in definition 67.
The EndOfFile and NoFilesPending markers do not actually appear in
the source text; they are deduced from conditions checked when the current
input is exhausted.
Therefore the corresponding literals must not be recognized as usual by the
lexical analyzer:
$EndOfFile EndOfFile
$NoFilesPending NoFilesPending
This macro is attached to a product file.
A token procesor that replaces the library end-of-file token processor
recognizes these two markers:
void EndOfText(char *c, int l, int *t, int *s)[64]
:
/* On entry-
* c points to the first character of the scanned string
* l=length of the scanned string
* *t=initial classification
* On exit-
* *t=final classification
* *s=internal representation
***/
{ switch (EOTstate) {
case 0:
*t = EndOfFile; EOTstate = 1; return;
case 1:
if (AnotherCompilationUnit()) break;
*t = NoFilesPending; EOTstate = 2; return;
case 2:
if (AnotherCompilationUnit()) break;
return;
}
ResetScan = 1;
*t = NORETURN; EOTstate = 0; return;
}
This macro is invoked in definition 67.
This macro is attached to a product file.
Instantiate necessary modules[66]
:
$/Input/CoordMap.gnrc :inst
$/Tech/MakeName.gnrc +instance=Identifier :inst
This macro is defined in definitions 54, 59, and 66.
This macro is invoked in definition 13.
Next: Support code
Up: Phrase Structure
Previous: Productions from 15: Expressions
2008-09-11