ack/lang/m2/comp/scope.C

245 lines
5.4 KiB
C++
Raw Normal View History

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
#ifndef NORCSID
1986-03-26 15:11:02 +00:00
static char *RcsId = "$Header$";
1986-05-01 19:06:53 +00:00
#endif
#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-04-18 17:53:47 +00:00
static int scp_level;
1986-04-28 18:06:58 +00:00
static struct scopelist *PervVis;
1986-03-26 15:11:02 +00:00
/* STATICALLOCDEF "scope" */
1986-04-28 18:06:58 +00:00
/* STATICALLOCDEF "scopelist" */
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-03-26 15:11:02 +00:00
1986-04-15 17:51:53 +00:00
assert(scopetype == OPENSCOPE || scopetype == CLOSEDSCOPE);
sc->sc_scopeclosed = scopetype == CLOSEDSCOPE;
1986-04-18 17:53:47 +00:00
sc->sc_level = scp_level++;
1986-04-08 18:15:46 +00:00
sc->sc_forw = 0;
sc->sc_def = 0;
1986-04-15 17:51:53 +00:00
sc->sc_off = 0;
1986-04-28 18:06:58 +00:00
if (scopetype == OPENSCOPE) {
ls->next = CurrVis;
1986-03-26 15:11:02 +00:00
}
1986-04-28 18:06:58 +00:00
else ls->next = PervVis;
ls->sc_scope = sc;
ls->sc_encl = CurrVis;
CurrVis = ls;
1986-03-26 15:11:02 +00:00
}
init_scope()
{
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-04-18 17:53:47 +00:00
sc->sc_level = scp_level++;
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-04-08 18:15:46 +00:00
struct node fo_tok;
1986-03-27 17:37:41 +00:00
struct type **fo_ptyp;
};
/* STATICALLOCDEF "forwards" */
Forward(tk, ptp)
struct token *tk;
struct type **ptp;
{
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-04-08 18:15:46 +00:00
f->fo_tok.nd_token = *tk;
1986-03-27 17:37:41 +00:00
f->fo_ptyp = ptp;
1986-04-03 00:44:39 +00:00
f->next = CurrentScope->sc_forw;
CurrentScope->sc_forw = f;
1986-03-27 17:37:41 +00:00
}
1986-04-15 17:51:53 +00:00
static
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
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-04-12 02:21:24 +00:00
node_error(df->for_node, "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;
}
}
static
chk_forw(pdf)
register struct def **pdf;
{
/* 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.
*/
while (*pdf) {
if ((*pdf)->df_kind & (D_FORWARD|D_FORWMODULE)) {
/* These definitions must be found in
the enclosing closed scope, which of course
may be the scope that is now closed!
*/
struct def *df1 = (*pdf)->df_nextinscope;
if (scopeclosed(CurrentScope)) {
/* Indeed, the scope was a closed
scope, so give error message
*/
node_error((*pdf)->for_node, "identifier \"%s\" has not been declared",
(*pdf)->df_idf->id_text);
FreeNode((*pdf)->for_node);
pdf = &(*pdf)->df_nextinscope;
1986-04-12 02:21:24 +00:00
}
1986-04-15 17:51:53 +00:00
else { /* This scope was an open scope.
Maybe the definitions are in the
enclosing scope?
1986-04-12 02:21:24 +00:00
*/
1986-04-28 18:06:58 +00:00
struct scopelist *ls;
1986-04-15 17:51:53 +00:00
1986-04-28 18:06:58 +00:00
ls = nextvisible(CurrVis);
1986-04-15 17:51:53 +00:00
if ((*pdf)->df_kind == D_FORWMODULE) {
1986-04-28 18:06:58 +00:00
(*pdf)->for_vis->next = ls;
1986-04-12 02:21:24 +00:00
}
1986-04-28 18:06:58 +00:00
(*pdf)->df_nextinscope = ls->sc_scope->sc_def;
ls->sc_scope->sc_def = *pdf;
(*pdf)->df_scope = ls->sc_scope;
1986-04-15 17:51:53 +00:00
*pdf = df1;
1986-04-12 02:21:24 +00:00
}
}
1986-04-15 17:51:53 +00:00
else pdf = &(*pdf)->df_nextinscope;
1986-04-12 02:21:24 +00:00
}
1986-04-08 18:15:46 +00:00
}
1986-03-27 17:37:41 +00:00
static
rem_forwards(fo)
struct forwards *fo;
{
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 forwards *f;
register struct def *df;
struct def *lookfor();
while (f = fo) {
1986-04-28 18:06:58 +00:00
df = lookfor(&(f->fo_tok), CurrVis, 1);
1986-04-12 02:21:24 +00:00
if (!(df->df_kind & (D_TYPE|D_HTYPE|D_ERROR))) {
1986-04-08 18:15:46 +00:00
node_error(&(f->fo_tok), "identifier \"%s\" not a type",
1986-04-03 00:44:39 +00:00
df->df_idf->id_text);
1986-03-27 17:37:41 +00:00
}
*(f->fo_ptyp) = df->df_type;
fo = f->next;
free_forwards(f);
}
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)
register struct def **pdf;
{
/* 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
from this list. The only interesting definitions are:
D_MODULE, D_PROCEDURE, and D_PROCHEAD.
1986-04-17 09:28:09 +00:00
*/
register struct def *df, *df1;
1986-04-21 17:27:06 +00:00
#define INTERESTING D_MODULE|D_PROCEDURE|D_PROCHEAD
1986-04-17 09:28:09 +00:00
df = 0;
df1 = *pdf;
while (df1) {
1986-04-21 17:27:06 +00:00
if (df1->df_kind & INTERESTING) break;
1986-04-17 09:28:09 +00:00
df1 = df1->df_nextinscope;
1986-04-21 17:27:06 +00:00
}
if (!(*pdf = df1)) return;
while (df1) {
*pdf = df1;
df1 = df1->df_nextinscope;
while (df1) {
if (df1->df_kind & INTERESTING) break;
df1 = df1->df_nextinscope;
}
1986-04-17 09:28:09 +00:00
(*pdf)->df_nextinscope = df;
df = *pdf;
}
}
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);
DO_DEBUG(1, debug("Closing a scope"));
if (flag) {
if (sc->sc_forw) rem_forwards(sc->sc_forw);
DO_DEBUG(2, PrScopeDef(sc->sc_def));
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-18 17:53:47 +00:00
scp_level = CurrentScope->sc_level;
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