1986-03-26 15:11:02 +00:00
|
|
|
/* S C O P E M E C H A N I S M */
|
|
|
|
|
1986-05-01 19:06:53 +00:00
|
|
|
#include "debug.h"
|
1986-03-26 15:11:02 +00:00
|
|
|
|
|
|
|
#include <assert.h>
|
|
|
|
#include <alloc.h>
|
1986-03-27 17:37:41 +00:00
|
|
|
#include <em_arith.h>
|
|
|
|
#include <em_label.h>
|
1986-04-22 22:36:16 +00:00
|
|
|
|
1986-03-27 17:37:41 +00:00
|
|
|
#include "LLlex.h"
|
|
|
|
#include "idf.h"
|
1986-03-26 15:11:02 +00:00
|
|
|
#include "scope.h"
|
1986-03-27 17:37:41 +00:00
|
|
|
#include "type.h"
|
|
|
|
#include "def.h"
|
1986-04-08 18:15:46 +00:00
|
|
|
#include "node.h"
|
1986-04-22 22:36:16 +00:00
|
|
|
|
1986-04-28 18:06:58 +00:00
|
|
|
struct scope *PervasiveScope, *GlobalScope;
|
|
|
|
struct scopelist *CurrVis;
|
1986-05-16 17:15:36 +00:00
|
|
|
extern int proclevel;
|
1986-04-28 18:06:58 +00:00
|
|
|
static struct scopelist *PervVis;
|
1986-03-26 15:11:02 +00:00
|
|
|
|
1986-10-06 20:36:30 +00:00
|
|
|
/* STATICALLOCDEF "scope" 10 */
|
1986-03-26 15:11:02 +00:00
|
|
|
|
1986-10-06 20:36:30 +00:00
|
|
|
/* STATICALLOCDEF "scopelist" 10 */
|
1986-04-28 18:06:58 +00:00
|
|
|
|
1986-04-15 17:51:53 +00:00
|
|
|
open_scope(scopetype)
|
1986-03-26 15:11:02 +00:00
|
|
|
{
|
1986-04-03 00:44:39 +00:00
|
|
|
/* Open a scope that is either open (automatic imports) or closed.
|
|
|
|
*/
|
1986-03-26 15:11:02 +00:00
|
|
|
register struct scope *sc = new_scope();
|
1986-04-28 18:06:58 +00:00
|
|
|
register struct scopelist *ls = new_scopelist();
|
1986-05-30 18:48:00 +00:00
|
|
|
|
1986-04-15 17:51:53 +00:00
|
|
|
assert(scopetype == OPENSCOPE || scopetype == CLOSEDSCOPE);
|
1986-05-30 18:48:00 +00:00
|
|
|
|
1986-04-15 17:51:53 +00:00
|
|
|
sc->sc_scopeclosed = scopetype == CLOSEDSCOPE;
|
1986-05-16 17:15:36 +00:00
|
|
|
sc->sc_level = proclevel;
|
1986-10-06 20:36:30 +00:00
|
|
|
ls->sc_scope = sc;
|
|
|
|
ls->sc_encl = CurrVis;
|
1986-04-28 18:06:58 +00:00
|
|
|
if (scopetype == OPENSCOPE) {
|
1986-10-06 20:36:30 +00:00
|
|
|
ls->next = ls->sc_encl;
|
1986-03-26 15:11:02 +00:00
|
|
|
}
|
1986-04-28 18:06:58 +00:00
|
|
|
else ls->next = PervVis;
|
|
|
|
CurrVis = ls;
|
1986-03-26 15:11:02 +00:00
|
|
|
}
|
|
|
|
|
1986-06-06 02:22:09 +00:00
|
|
|
InitScope()
|
1986-03-26 15:11:02 +00:00
|
|
|
{
|
|
|
|
register struct scope *sc = new_scope();
|
1986-04-28 18:06:58 +00:00
|
|
|
register struct scopelist *ls = new_scopelist();
|
1986-03-26 15:11:02 +00:00
|
|
|
|
1986-04-15 17:51:53 +00:00
|
|
|
sc->sc_scopeclosed = 0;
|
1986-04-03 00:44:39 +00:00
|
|
|
sc->sc_forw = 0;
|
|
|
|
sc->sc_def = 0;
|
1986-05-16 17:15:36 +00:00
|
|
|
sc->sc_level = proclevel;
|
1986-04-15 17:51:53 +00:00
|
|
|
PervasiveScope = sc;
|
1986-04-28 18:06:58 +00:00
|
|
|
ls->next = 0;
|
|
|
|
ls->sc_encl = 0;
|
|
|
|
ls->sc_scope = PervasiveScope;
|
|
|
|
PervVis = ls;
|
|
|
|
CurrVis = ls;
|
1986-03-27 17:37:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
struct forwards {
|
|
|
|
struct forwards *next;
|
1986-08-26 14:33:24 +00:00
|
|
|
struct node *fo_tok;
|
1986-07-14 15:00:08 +00:00
|
|
|
struct type *fo_ptyp;
|
1986-03-27 17:37:41 +00:00
|
|
|
};
|
|
|
|
|
1986-10-06 20:36:30 +00:00
|
|
|
/* STATICALLOCDEF "forwards" 5 */
|
1986-03-27 17:37:41 +00:00
|
|
|
|
|
|
|
Forward(tk, ptp)
|
1986-08-26 14:33:24 +00:00
|
|
|
struct node *tk;
|
1986-07-14 15:00:08 +00:00
|
|
|
struct type *ptp;
|
1986-03-27 17:37:41 +00:00
|
|
|
{
|
1986-04-03 00:44:39 +00:00
|
|
|
/* Enter a forward reference into a list belonging to the
|
|
|
|
current scope. This is used for POINTER declarations, which
|
|
|
|
may have forward references that must howewer be declared in the
|
|
|
|
same scope.
|
|
|
|
*/
|
1986-03-27 17:37:41 +00:00
|
|
|
register struct forwards *f = new_forwards();
|
1986-10-06 20:36:30 +00:00
|
|
|
register struct scope *sc = CurrentScope;
|
1986-03-27 17:37:41 +00:00
|
|
|
|
1986-08-26 14:33:24 +00:00
|
|
|
f->fo_tok = tk;
|
1986-03-27 17:37:41 +00:00
|
|
|
f->fo_ptyp = ptp;
|
1986-10-06 20:36:30 +00:00
|
|
|
f->next = sc->sc_forw;
|
|
|
|
sc->sc_forw = f;
|
1986-03-27 17:37:41 +00:00
|
|
|
}
|
|
|
|
|
1986-06-17 12:04:05 +00:00
|
|
|
STATIC
|
1986-04-15 17:51:53 +00:00
|
|
|
chk_proc(df)
|
|
|
|
register struct def *df;
|
1986-04-08 18:15:46 +00:00
|
|
|
{
|
1986-04-15 17:51:53 +00:00
|
|
|
/* Called at scope closing. Check all definitions, and if one
|
1986-10-06 20:36:30 +00:00
|
|
|
is a D_PROCHEAD, the procedure was not defined.
|
1986-04-12 02:21:24 +00:00
|
|
|
*/
|
1986-04-15 17:51:53 +00:00
|
|
|
while (df) {
|
|
|
|
if (df->df_kind == D_PROCHEAD) {
|
|
|
|
/* A not defined procedure
|
|
|
|
*/
|
1986-10-06 20:36:30 +00:00
|
|
|
error("procedure \"%s\" not defined",
|
|
|
|
df->df_idf->id_text);
|
1986-04-15 17:51:53 +00:00
|
|
|
FreeNode(df->for_node);
|
|
|
|
}
|
|
|
|
df = df->df_nextinscope;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1986-06-17 12:04:05 +00:00
|
|
|
STATIC
|
1986-04-15 17:51:53 +00:00
|
|
|
chk_forw(pdf)
|
1986-10-06 20:36:30 +00:00
|
|
|
struct def **pdf;
|
1986-04-15 17:51:53 +00:00
|
|
|
{
|
|
|
|
/* Called at scope close. Look for all forward definitions and
|
|
|
|
if the scope was a closed scope, give an error message for
|
|
|
|
them, and otherwise move them to the enclosing scope.
|
|
|
|
*/
|
1986-10-06 20:36:30 +00:00
|
|
|
register struct def *df;
|
|
|
|
|
|
|
|
while (df = *pdf) {
|
|
|
|
if (df->df_kind & (D_FORWARD|D_FORWMODULE)) {
|
1986-04-15 17:51:53 +00:00
|
|
|
/* These definitions must be found in
|
|
|
|
the enclosing closed scope, which of course
|
|
|
|
may be the scope that is now closed!
|
|
|
|
*/
|
|
|
|
if (scopeclosed(CurrentScope)) {
|
|
|
|
/* Indeed, the scope was a closed
|
|
|
|
scope, so give error message
|
|
|
|
*/
|
1986-10-06 20:36:30 +00:00
|
|
|
node_error(df->for_node, "identifier \"%s\" has not been declared",
|
|
|
|
df->df_idf->id_text);
|
|
|
|
FreeNode(df->for_node);
|
1986-04-12 02:21:24 +00:00
|
|
|
}
|
1986-10-06 20:36:30 +00:00
|
|
|
else {
|
|
|
|
/* This scope was an open scope.
|
1986-04-15 17:51:53 +00:00
|
|
|
Maybe the definitions are in the
|
|
|
|
enclosing scope?
|
1986-04-12 02:21:24 +00:00
|
|
|
*/
|
1986-10-06 20:36:30 +00:00
|
|
|
register struct scopelist *ls =
|
|
|
|
nextvisible(CurrVis);
|
|
|
|
struct def *df1 = df->df_nextinscope;
|
|
|
|
|
|
|
|
if (df->df_kind == D_FORWMODULE) {
|
|
|
|
df->for_vis->next = ls;
|
1986-04-12 02:21:24 +00:00
|
|
|
}
|
1986-10-06 20:36:30 +00:00
|
|
|
df->df_nextinscope = ls->sc_scope->sc_def;
|
|
|
|
ls->sc_scope->sc_def = df;
|
|
|
|
df->df_scope = ls->sc_scope;
|
1986-04-15 17:51:53 +00:00
|
|
|
*pdf = df1;
|
1986-10-06 20:36:30 +00:00
|
|
|
continue;
|
1986-04-12 02:21:24 +00:00
|
|
|
}
|
|
|
|
}
|
1986-10-06 20:36:30 +00:00
|
|
|
pdf = &df->df_nextinscope;
|
1986-04-12 02:21:24 +00:00
|
|
|
}
|
1986-04-08 18:15:46 +00:00
|
|
|
}
|
|
|
|
|
1986-06-17 12:04:05 +00:00
|
|
|
STATIC
|
1986-03-27 17:37:41 +00:00
|
|
|
rem_forwards(fo)
|
1986-08-26 14:33:24 +00:00
|
|
|
register struct forwards *fo;
|
1986-03-27 17:37:41 +00:00
|
|
|
{
|
1986-04-03 00:44:39 +00:00
|
|
|
/* When closing a scope, all forward references must be resolved
|
|
|
|
*/
|
1986-03-27 17:37:41 +00:00
|
|
|
register struct def *df;
|
|
|
|
|
1986-08-26 14:33:24 +00:00
|
|
|
if (fo->next) rem_forwards(fo->next);
|
|
|
|
df = lookfor(fo->fo_tok, CurrVis, 0);
|
1986-10-06 20:36:30 +00:00
|
|
|
if (! is_type(df)) {
|
|
|
|
node_error(fo->fo_tok,
|
|
|
|
"identifier \"%s\" does not represent a type",
|
|
|
|
df->df_idf->id_text);
|
1986-03-27 17:37:41 +00:00
|
|
|
}
|
1986-08-26 14:33:24 +00:00
|
|
|
fo->fo_ptyp->next = df->df_type;
|
|
|
|
free_forwards(fo);
|
1986-03-26 15:11:02 +00:00
|
|
|
}
|
1986-04-15 17:51:53 +00:00
|
|
|
|
1986-04-17 09:28:09 +00:00
|
|
|
Reverse(pdf)
|
1986-10-06 20:36:30 +00:00
|
|
|
struct def **pdf;
|
1986-04-17 09:28:09 +00:00
|
|
|
{
|
|
|
|
/* Reverse the order in the list of definitions in a scope.
|
|
|
|
This is neccesary because this list is built in reverse.
|
1986-04-21 17:27:06 +00:00
|
|
|
Also, while we're at it, remove uninteresting definitions
|
1986-06-17 12:04:05 +00:00
|
|
|
from this list.
|
1986-04-17 09:28:09 +00:00
|
|
|
*/
|
|
|
|
register struct def *df, *df1;
|
1986-06-17 12:04:05 +00:00
|
|
|
#define INTERESTING D_MODULE|D_PROCEDURE|D_PROCHEAD|D_VARIABLE
|
1986-04-17 09:28:09 +00:00
|
|
|
|
|
|
|
df = 0;
|
|
|
|
df1 = *pdf;
|
1986-04-21 17:27:06 +00:00
|
|
|
|
|
|
|
while (df1) {
|
1986-10-06 20:36:30 +00:00
|
|
|
if (df1->df_kind & INTERESTING) {
|
|
|
|
struct def *prev = df;
|
|
|
|
|
|
|
|
df = df1;
|
1986-04-21 17:27:06 +00:00
|
|
|
df1 = df1->df_nextinscope;
|
1986-10-06 20:36:30 +00:00
|
|
|
df->df_nextinscope = prev;
|
1986-04-21 17:27:06 +00:00
|
|
|
}
|
1986-10-06 20:36:30 +00:00
|
|
|
else df1 = df1->df_nextinscope;
|
1986-04-17 09:28:09 +00:00
|
|
|
}
|
1986-10-06 20:36:30 +00:00
|
|
|
*pdf = df;
|
1986-04-17 09:28:09 +00:00
|
|
|
}
|
|
|
|
|
1986-04-15 17:51:53 +00:00
|
|
|
close_scope(flag)
|
|
|
|
{
|
|
|
|
/* Close a scope. If "flag" is set, check for forward declarations,
|
|
|
|
either POINTER declarations, or EXPORTs, or forward references
|
|
|
|
to MODULES
|
|
|
|
*/
|
|
|
|
register struct scope *sc = CurrentScope;
|
|
|
|
|
|
|
|
assert(sc != 0);
|
|
|
|
|
|
|
|
if (flag) {
|
|
|
|
if (sc->sc_forw) rem_forwards(sc->sc_forw);
|
1986-06-26 09:39:36 +00:00
|
|
|
DO_DEBUG(options['S'], PrScopeDef(sc->sc_def));
|
1986-04-15 17:51:53 +00:00
|
|
|
if (flag & SC_CHKPROC) chk_proc(sc->sc_def);
|
|
|
|
if (flag & SC_CHKFORW) chk_forw(&(sc->sc_def));
|
1986-04-22 22:36:16 +00:00
|
|
|
if (flag & SC_REVERSE) Reverse(&(sc->sc_def));
|
1986-04-15 17:51:53 +00:00
|
|
|
}
|
1986-04-28 18:06:58 +00:00
|
|
|
CurrVis = enclosing(CurrVis);
|
1986-04-15 17:51:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
PrScopeDef(df)
|
|
|
|
register struct def *df;
|
|
|
|
{
|
1986-05-01 19:06:53 +00:00
|
|
|
print("List of definitions in currently ended scope:\n");
|
1986-04-15 17:51:53 +00:00
|
|
|
while (df) {
|
|
|
|
PrDef(df);
|
|
|
|
df = df->df_nextinscope;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|