newer version
This commit is contained in:
parent
7d76f2829a
commit
426c273de8
|
@ -4,13 +4,16 @@ static char *RcsId = "$Header$";
|
|||
|
||||
#include <alloc.h>
|
||||
#include <em_arith.h>
|
||||
#include <em_label.h>
|
||||
#include <assert.h>
|
||||
#include "input.h"
|
||||
#include "f_info.h"
|
||||
#include "Lpars.h"
|
||||
#include "class.h"
|
||||
#include "idf.h"
|
||||
#include "type.h"
|
||||
#include "LLlex.h"
|
||||
#include "const.h"
|
||||
|
||||
#define IDFSIZE 256 /* Number of significant characters in an identifier */
|
||||
#define NUMSIZE 256 /* maximum number of characters in a number */
|
||||
|
@ -18,6 +21,7 @@ static char *RcsId = "$Header$";
|
|||
long str2long();
|
||||
|
||||
struct token dot, aside;
|
||||
struct type *numtype;
|
||||
struct string string;
|
||||
|
||||
static
|
||||
|
@ -102,6 +106,7 @@ LLlex()
|
|||
char buf[(IDFSIZE > NUMSIZE ? IDFSIZE : NUMSIZE) + 1];
|
||||
register int ch, nch;
|
||||
|
||||
numtype = error_type;
|
||||
if (ASIDE) { /* a token is put aside */
|
||||
*tk = aside;
|
||||
ASIDE = 0;
|
||||
|
@ -236,7 +241,7 @@ again:
|
|||
switch (ch) {
|
||||
case 'H':
|
||||
Shex: *np++ = '\0';
|
||||
/* Type is integer */
|
||||
numtype = card_type;
|
||||
tk->TOK_INT = str2long(&buf[1], 16);
|
||||
return tk->tk_symb = INTEGER;
|
||||
|
||||
|
@ -271,10 +276,10 @@ Shex: *np++ = '\0';
|
|||
PushBack(ch);
|
||||
ch = *--np;
|
||||
*np++ = '\0';
|
||||
/*
|
||||
* If (ch == 'C') type is a CHAR
|
||||
* else type is an INTEGER
|
||||
*/
|
||||
if (ch == 'C') {
|
||||
numtype = char_type;
|
||||
}
|
||||
else numtype = card_type;
|
||||
tk->TOK_INT = str2long(&buf[1], 8);
|
||||
return tk->tk_symb = INTEGER;
|
||||
|
||||
|
@ -369,8 +374,11 @@ Sreal:
|
|||
PushBack(ch);
|
||||
Sdec:
|
||||
*np++ = '\0';
|
||||
/* Type is an integer */
|
||||
tk->TOK_INT = str2long(&buf[1], 10);
|
||||
if (tk->TOK_INT < 0 || tk->TOK_INT > max_int) {
|
||||
numtype = card_type;
|
||||
}
|
||||
else numtype = intorcard_type;
|
||||
return tk->tk_symb = INTEGER;
|
||||
}
|
||||
/*NOTREACHED*/
|
||||
|
|
|
@ -28,6 +28,7 @@ struct token {
|
|||
#define TOK_REL tk_data.tk_real
|
||||
|
||||
extern struct token dot, aside;
|
||||
extern struct type *numtype;
|
||||
|
||||
#define DOT dot.tk_symb
|
||||
#define ASIDE aside.tk_symb
|
||||
|
|
|
@ -266,7 +266,9 @@ node_error(expp, "Size of type in type cast does not match size of operand");
|
|||
}
|
||||
arg->nd_type = left->nd_type;
|
||||
FreeNode(expp->nd_left);
|
||||
*expp = *(arg->nd_left);
|
||||
expp->nd_right->nd_left = 0;
|
||||
FreeNode(expp->nd_right);
|
||||
*expp = *arg;
|
||||
arg->nd_left = 0;
|
||||
arg->nd_right = 0;
|
||||
FreeNode(arg);
|
||||
|
@ -451,8 +453,6 @@ findname(expp)
|
|||
register struct def *df;
|
||||
struct def *lookfor();
|
||||
register struct type *tp;
|
||||
int scope;
|
||||
int module;
|
||||
|
||||
expp->nd_type = error_type;
|
||||
if (expp->nd_class == Name) {
|
||||
|
@ -596,7 +596,7 @@ node_error(expp, "IN operator: type of LHS not compatible with element type of R
|
|||
|
||||
if (!TstCompat(tpl, tpr)) {
|
||||
node_error(expp,
|
||||
"Incompatible types for operator \"%s\"",
|
||||
"incompatible types for operator \"%s\"",
|
||||
symbol2str(expp->nd_symb));
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -14,6 +14,8 @@ static char *RcsId = "$Header$";
|
|||
#include "scope.h"
|
||||
#include "node.h"
|
||||
#include "misc.h"
|
||||
|
||||
static int proclevel = 0; /* nesting level of procedures */
|
||||
}
|
||||
|
||||
ProcedureDeclaration
|
||||
|
@ -21,10 +23,13 @@ ProcedureDeclaration
|
|||
struct def *df;
|
||||
} :
|
||||
ProcedureHeading(&df, D_PROCEDURE)
|
||||
{ df->prc_level = proclevel++;
|
||||
}
|
||||
';' block IDENT
|
||||
{ match_id(dot.TOK_IDF, df->df_idf);
|
||||
df->prc_scope = CurrentScope->sc_scope;
|
||||
df->prc_scope = CurrentScope;
|
||||
close_scope(SC_CHKFORW);
|
||||
proclevel--;
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -36,38 +41,38 @@ ProcedureHeading(struct def **pdf; int type;)
|
|||
register struct def *df;
|
||||
} :
|
||||
PROCEDURE IDENT
|
||||
{ assert(type & (D_PROCEDURE | D_PROCHEAD));
|
||||
if (type == D_PROCHEAD) {
|
||||
df = define(dot.TOK_IDF, CurrentScope, type);
|
||||
df->for_node = MkNode(Name, NULLNODE, NULLNODE, &dot);
|
||||
}
|
||||
else {
|
||||
df = lookup(dot.TOK_IDF,
|
||||
CurrentScope->sc_scope);
|
||||
if (df && df->df_kind == D_PROCHEAD) {
|
||||
df->df_kind = type;
|
||||
tp1 = df->df_type;
|
||||
}
|
||||
else {
|
||||
df = define(dot.TOK_IDF,
|
||||
CurrentScope, type);
|
||||
}
|
||||
open_scope(OPENSCOPE, 0);
|
||||
}
|
||||
{ assert(type & (D_PROCEDURE | D_PROCHEAD));
|
||||
if (type == D_PROCHEAD) {
|
||||
df = define(dot.TOK_IDF, CurrentScope, type);
|
||||
df->for_node = MkNode(Name, NULLNODE, NULLNODE, &dot);
|
||||
}
|
||||
else {
|
||||
df = lookup(dot.TOK_IDF, CurrentScope);
|
||||
if (df && df->df_kind == D_PROCHEAD) {
|
||||
df->df_kind = type;
|
||||
tp1 = df->df_type;
|
||||
}
|
||||
FormalParameters(type == D_PROCEDURE, ¶ms, &tp)?
|
||||
{
|
||||
df->df_type = tp = construct_type(T_PROCEDURE, tp);
|
||||
tp->prc_params = params;
|
||||
if (tp1 && !TstTypeEquiv(tp, tp1)) {
|
||||
else df = define(dot.TOK_IDF, CurrentScope, type);
|
||||
df->prc_nbpar = 0;
|
||||
open_scope(OPENSCOPE);
|
||||
}
|
||||
}
|
||||
FormalParameters(type == D_PROCEDURE, ¶ms, &tp, &(df->prc_nbpar))?
|
||||
{
|
||||
df->df_type = tp = construct_type(T_PROCEDURE, tp);
|
||||
tp->prc_params = params;
|
||||
if (tp1 && !TstTypeEquiv(tp, tp1)) {
|
||||
error("inconsistent procedure declaration for \"%s\"", df->df_idf->id_text);
|
||||
}
|
||||
*pdf = df;
|
||||
}
|
||||
}
|
||||
*pdf = df;
|
||||
}
|
||||
;
|
||||
|
||||
block:
|
||||
declaration* [ BEGIN StatementSequence ]? END
|
||||
block
|
||||
{
|
||||
struct node *nd;
|
||||
}:
|
||||
declaration* [ BEGIN StatementSequence(&nd) ]? END
|
||||
;
|
||||
|
||||
declaration:
|
||||
|
@ -82,18 +87,21 @@ declaration:
|
|||
ModuleDeclaration ';'
|
||||
;
|
||||
|
||||
FormalParameters(int doparams; struct paramlist **pr; struct type **tp;)
|
||||
FormalParameters(int doparams;
|
||||
struct paramlist **pr;
|
||||
struct type **tp;
|
||||
arith *parmaddr;)
|
||||
{
|
||||
struct def *df;
|
||||
register struct paramlist *pr1;
|
||||
} :
|
||||
'('
|
||||
[
|
||||
FPSection(doparams, pr)
|
||||
FPSection(doparams, pr, parmaddr)
|
||||
{ pr1 = *pr; }
|
||||
[
|
||||
{ for (; pr1->next; pr1 = pr1->next) ; }
|
||||
';' FPSection(doparams, &(pr1->next))
|
||||
';' FPSection(doparams, &(pr1->next), &parmaddr)
|
||||
]*
|
||||
]?
|
||||
')'
|
||||
|
@ -109,7 +117,7 @@ FormalParameters(int doparams; struct paramlist **pr; struct type **tp;)
|
|||
because in this case we only read the header. The Implementation
|
||||
might contain different identifiers representing the same paramters.
|
||||
*/
|
||||
FPSection(int doparams; struct paramlist **ppr;)
|
||||
FPSection(int doparams; struct paramlist **ppr; arith *addr;)
|
||||
{
|
||||
struct node *FPList;
|
||||
struct paramlist *ParamList();
|
||||
|
@ -122,7 +130,8 @@ FPSection(int doparams; struct paramlist **ppr;)
|
|||
IdentList(&FPList) ':' FormalType(&tp)
|
||||
{
|
||||
if (doparams) {
|
||||
EnterIdList(FPList, D_VARIABLE, VARp, tp, CurrentScope);
|
||||
EnterIdList(FPList, D_VARIABLE, VARp,
|
||||
tp, CurrentScope, addr);
|
||||
}
|
||||
*ppr = ParamList(FPList, tp, VARp);
|
||||
FreeNode(FPList);
|
||||
|
@ -140,6 +149,9 @@ FormalType(struct type **tp;)
|
|||
{ if (ARRAYflag) {
|
||||
*tp = construct_type(T_ARRAY, NULLTYPE);
|
||||
(*tp)->arr_elem = df->df_type;
|
||||
(*tp)->tp_align = lcm(wrd_align, ptr_align);
|
||||
(*tp)->tp_size = align(ptr_size + 3*wrd_size,
|
||||
(*tp)->tp_align);
|
||||
}
|
||||
else *tp = df->df_type;
|
||||
}
|
||||
|
@ -209,11 +221,20 @@ enumeration(struct type **ptp;)
|
|||
} :
|
||||
'(' IdentList(&EnumList) ')'
|
||||
{
|
||||
*ptp = standard_type(T_ENUMERATION,int_align,int_size);
|
||||
EnterIdList(EnumList, D_ENUM, 0, *ptp, CurrentScope);
|
||||
*ptp = standard_type(T_ENUMERATION,1,1);
|
||||
EnterIdList(EnumList, D_ENUM, 0, *ptp,
|
||||
CurrentScope, (arith *) 0);
|
||||
FreeNode(EnumList);
|
||||
if ((*ptp)->enm_ncst > 256) {
|
||||
if (wrd_size == 1) {
|
||||
error("Too many enumeration literals");
|
||||
}
|
||||
else {
|
||||
(*ptp)->tp_size = wrd_size;
|
||||
(*ptp)->tp_align = wrd_align;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
IdentList(struct node **p;)
|
||||
|
@ -261,44 +282,52 @@ ArrayType(struct type **ptp;)
|
|||
construct_type(T_ARRAY, tp);
|
||||
}
|
||||
]* OF type(&tp)
|
||||
{ tp2->arr_elem = tp; }
|
||||
{ tp2->arr_elem = tp;
|
||||
ArraySizes(*ptp);
|
||||
}
|
||||
;
|
||||
|
||||
RecordType(struct type **ptp;)
|
||||
{
|
||||
struct scope scope;
|
||||
struct scope *scope;
|
||||
arith count;
|
||||
int xalign = record_align;
|
||||
}
|
||||
:
|
||||
RECORD
|
||||
{ scope.sc_scope = uniq_scope();
|
||||
scope.next = CurrentScope;
|
||||
{ open_scope(OPENSCOPE);
|
||||
scope = CurrentScope;
|
||||
close_scope(0);
|
||||
count = 0;
|
||||
}
|
||||
FieldListSequence(&scope)
|
||||
FieldListSequence(scope, &count, &xalign)
|
||||
{
|
||||
*ptp = standard_type(T_RECORD, record_align, (arith) 0 /* ???? */);
|
||||
(*ptp)->rec_scope = scope.sc_scope;
|
||||
*ptp = standard_type(T_RECORD, xalign, count);
|
||||
(*ptp)->rec_scope = scope;
|
||||
}
|
||||
END
|
||||
;
|
||||
|
||||
FieldListSequence(struct scope *scope;):
|
||||
FieldList(scope)
|
||||
FieldListSequence(struct scope *scope; arith *cnt; int *palign;):
|
||||
FieldList(scope, cnt, palign)
|
||||
[
|
||||
';' FieldList(scope)
|
||||
';' FieldList(scope, cnt, palign)
|
||||
]*
|
||||
;
|
||||
|
||||
FieldList(struct scope *scope;)
|
||||
FieldList(struct scope *scope; arith *cnt; int *palign;)
|
||||
{
|
||||
struct node *FldList;
|
||||
struct idf *id;
|
||||
struct def *df, *df1;
|
||||
struct def *df;
|
||||
struct type *tp;
|
||||
struct node *nd;
|
||||
arith tcnt, max;
|
||||
} :
|
||||
[
|
||||
IdentList(&FldList) ':' type(&tp)
|
||||
{ EnterIdList(FldList, D_FIELD, 0, tp, scope);
|
||||
{ *palign = lcm(*palign, tp->tp_align);
|
||||
EnterIdList(FldList, D_FIELD, 0, tp, scope, cnt);
|
||||
FreeNode(FldList);
|
||||
}
|
||||
|
|
||||
|
@ -309,8 +338,7 @@ FieldList(struct scope *scope;)
|
|||
[ /* This is good, in both kinds of Modula-2, if
|
||||
the first qualident is a single identifier.
|
||||
*/
|
||||
{
|
||||
if (nd->nd_class != Name) {
|
||||
{ if (nd->nd_class != Name) {
|
||||
error("illegal variant tag");
|
||||
id = gen_anon_idf();
|
||||
}
|
||||
|
@ -322,8 +350,7 @@ FieldList(struct scope *scope;)
|
|||
/* Old fashioned! the first qualident now represents
|
||||
the type
|
||||
*/
|
||||
{
|
||||
warning("Old fashioned Modula-2 syntax!");
|
||||
{ warning("Old fashioned Modula-2 syntax!");
|
||||
id = gen_anon_idf();
|
||||
findname(nd);
|
||||
assert(nd->nd_class == Def);
|
||||
|
@ -338,42 +365,62 @@ FieldList(struct scope *scope;)
|
|||
]
|
||||
|
|
||||
/* Aha, third edition? */
|
||||
':' qualident(D_TYPE|D_HTYPE|D_HIDDEN,
|
||||
&df,
|
||||
"type",
|
||||
(struct node **) 0)
|
||||
{
|
||||
id = gen_anon_idf();
|
||||
}
|
||||
':' qualident(D_TYPE|D_HTYPE|D_HIDDEN, &df, "type", (struct node **) 0)
|
||||
{ id = gen_anon_idf(); }
|
||||
]
|
||||
{
|
||||
df1 = define(id, scope, D_FIELD);
|
||||
df1->df_type = df->df_type;
|
||||
{ tp = df->df_type;
|
||||
df = define(id, scope, D_FIELD);
|
||||
df->df_type = tp;
|
||||
df->fld_off = align(*cnt, tp->tp_align);
|
||||
*cnt = tcnt = df->fld_off + tp->tp_size;
|
||||
}
|
||||
OF variant(scope)
|
||||
OF variant(scope, &tcnt, tp, palign)
|
||||
{ max = tcnt; tcnt = *cnt; }
|
||||
[
|
||||
'|' variant(scope)
|
||||
'|' variant(scope, &tcnt, tp, palign)
|
||||
{ if (tcnt > max) max = tcnt; }
|
||||
]*
|
||||
[ ELSE FieldListSequence(scope)
|
||||
[ ELSE FieldListSequence(scope, &tcnt, palign)
|
||||
{ if (tcnt > max) max = tcnt; }
|
||||
]?
|
||||
END
|
||||
{ *cnt = max; }
|
||||
]?
|
||||
;
|
||||
|
||||
variant(struct scope *scope;):
|
||||
[ CaseLabelList ':' FieldListSequence(scope) ]?
|
||||
variant(struct scope *scope; arith *cnt; struct type *tp; int *palign;)
|
||||
{
|
||||
struct type *tp1 = tp;
|
||||
} :
|
||||
[
|
||||
CaseLabelList(&tp1) ':' FieldListSequence(scope, cnt, palign)
|
||||
]?
|
||||
/* Changed rule in new modula-2 */
|
||||
;
|
||||
|
||||
CaseLabelList:
|
||||
CaseLabels [ ',' CaseLabels ]*
|
||||
CaseLabelList(struct type **ptp;):
|
||||
CaseLabels(ptp) [ ',' CaseLabels(ptp) ]*
|
||||
;
|
||||
|
||||
CaseLabels
|
||||
CaseLabels(struct type **ptp;)
|
||||
{
|
||||
struct node *nd1, *nd2 = 0;
|
||||
}:
|
||||
ConstExpression(&nd1) [ UPTO ConstExpression(&nd2) ]?
|
||||
ConstExpression(&nd1)
|
||||
[
|
||||
UPTO ConstExpression(&nd2)
|
||||
{ if (!TstCompat(nd1->nd_type, nd2->nd_type)) {
|
||||
node_error(nd2,"type incompatibility in case label");
|
||||
}
|
||||
nd1->nd_type = error_type;
|
||||
}
|
||||
]?
|
||||
{ if (*ptp != 0 &&
|
||||
!TstCompat(*ptp, nd1->nd_type)) {
|
||||
node_error(nd1,"type incompatibility in case label");
|
||||
}
|
||||
*ptp = nd1->nd_type;
|
||||
}
|
||||
;
|
||||
|
||||
SetType(struct type **ptp;)
|
||||
|
@ -398,7 +445,7 @@ PointerType(struct type **ptp;)
|
|||
struct node *nd;
|
||||
} :
|
||||
POINTER TO
|
||||
[ %if ( (df = lookup(dot.TOK_IDF, CurrentScope->sc_scope)))
|
||||
[ %if ( (df = lookup(dot.TOK_IDF, CurrentScope)))
|
||||
/* Either a Module or a Type, but in both cases defined
|
||||
in this scope, so this is the correct identification
|
||||
*/
|
||||
|
@ -489,14 +536,22 @@ VariableDeclaration
|
|||
{
|
||||
struct node *VarList;
|
||||
struct type *tp;
|
||||
struct node *nd = 0;
|
||||
} :
|
||||
IdentList(&VarList)
|
||||
[
|
||||
ConstExpression(&nd)
|
||||
]?
|
||||
IdentAddrList(&VarList)
|
||||
':' type(&tp)
|
||||
{ EnterIdList(VarList, D_VARIABLE, 0, tp, CurrentScope);
|
||||
{ EnterVarList(VarList, tp, proclevel > 0);
|
||||
FreeNode(VarList);
|
||||
}
|
||||
;
|
||||
|
||||
IdentAddrList(struct node **pnd;)
|
||||
{
|
||||
} :
|
||||
IDENT { *pnd = MkNode(Name, NULLNODE, NULLNODE, &dot); }
|
||||
ConstExpression(&(*pnd)->nd_left)?
|
||||
[ { pnd = &((*pnd)->nd_right); }
|
||||
',' IDENT
|
||||
{ *pnd = MkNode(Name, NULLNODE, NULLNODE, &dot); }
|
||||
ConstExpression(&(*pnd)->nd_left)?
|
||||
]*
|
||||
;
|
||||
|
|
|
@ -4,14 +4,16 @@
|
|||
|
||||
struct module {
|
||||
int mo_priority; /* priority of a module */
|
||||
int mo_scope; /* scope of this module */
|
||||
struct scope *mo_scope; /* scope of this module */
|
||||
#define mod_priority df_value.df_module.mo_priority
|
||||
#define mod_scope df_value.df_module.mo_scope
|
||||
};
|
||||
|
||||
struct variable {
|
||||
arith va_off; /* address or offset of variable */
|
||||
char va_addrgiven; /* an address was given in the program */
|
||||
#define var_off df_value.df_variable.va_off
|
||||
#define var_addrgiven df_value.df_variable.va_addrgiven
|
||||
};
|
||||
|
||||
struct constant {
|
||||
|
@ -38,8 +40,12 @@ struct field {
|
|||
};
|
||||
|
||||
struct dfproc {
|
||||
int pr_scope; /* scope number of procedure */
|
||||
struct scope *pr_scope; /* scope of procedure */
|
||||
int pr_level; /* depth level of this procedure */
|
||||
arith pr_nbpar; /* Number of bytes parameters */
|
||||
#define prc_scope df_value.df_proc.pr_scope
|
||||
#define prc_level df_value.df_proc.pr_level
|
||||
#define prc_nbpar df_value.df_proc.pr_nbpar
|
||||
};
|
||||
|
||||
struct import {
|
||||
|
@ -48,7 +54,7 @@ struct import {
|
|||
};
|
||||
|
||||
struct dforward {
|
||||
int fo_scope;
|
||||
struct scope *fo_scope;
|
||||
struct node *fo_node;
|
||||
#define for_node df_value.df_forward.fo_node
|
||||
#define for_scope df_value.df_forward.fo_scope
|
||||
|
@ -59,7 +65,7 @@ struct def { /* list of definitions for a name */
|
|||
struct def *df_nextinscope;
|
||||
/* link all definitions in a scope */
|
||||
struct idf *df_idf; /* link back to the name */
|
||||
int df_scope; /* scope in which this definition resides */
|
||||
struct scope *df_scope; /* scope in which this definition resides */
|
||||
short df_kind; /* the kind of this definition: */
|
||||
#define D_MODULE 0x0001 /* a module */
|
||||
#define D_PROCEDURE 0x0002 /* procedure of function */
|
||||
|
|
|
@ -18,7 +18,7 @@ static char *RcsId = "$Header$";
|
|||
struct def *h_def; /* Pointer to free list of def structures */
|
||||
|
||||
static struct def illegal_def =
|
||||
{0, 0, 0, -20 /* Illegal scope */, D_ERROR};
|
||||
{0, 0, 0, 0, D_ERROR};
|
||||
|
||||
struct def *ill_df = &illegal_def;
|
||||
|
||||
|
@ -32,17 +32,17 @@ define(id, scope, kind)
|
|||
*/
|
||||
register struct def *df;
|
||||
|
||||
DO_DEBUG(5, debug("Defining identifier \"%s\" in scope %d, kind = %d",
|
||||
id->id_text, scope->sc_scope, kind));
|
||||
df = lookup(id, scope->sc_scope);
|
||||
DO_DEBUG(5, debug("Defining identifier \"%s\", kind = %d",
|
||||
id->id_text, kind));
|
||||
df = lookup(id, scope);
|
||||
if ( /* Already in this scope */
|
||||
df
|
||||
|| /* A closed scope, and id defined in the pervasive scope */
|
||||
( CurrentScope == scope
|
||||
&&
|
||||
scopeclosed(CurrentScope)
|
||||
scopeclosed(scope)
|
||||
&&
|
||||
(df = lookup(id, 0)))
|
||||
(df = lookup(id, PervasiveScope)))
|
||||
) {
|
||||
switch(df->df_kind) {
|
||||
case D_PROCHEAD:
|
||||
|
@ -62,7 +62,6 @@ define(id, scope, kind)
|
|||
break;
|
||||
case D_FORWMODULE:
|
||||
if (kind == D_FORWMODULE) {
|
||||
df->df_kind = kind;
|
||||
return df;
|
||||
}
|
||||
if (kind == D_MODULE) {
|
||||
|
@ -89,8 +88,9 @@ error("identifier \"%s\" already declared", id->id_text);
|
|||
df = new_def();
|
||||
df->df_flags = 0;
|
||||
df->df_idf = id;
|
||||
df->df_scope = scope->sc_scope;
|
||||
df->df_scope = scope;
|
||||
df->df_kind = kind;
|
||||
df->df_type = 0;
|
||||
df->next = id->id_def;
|
||||
id->id_def = df;
|
||||
|
||||
|
@ -103,6 +103,7 @@ error("identifier \"%s\" already declared", id->id_text);
|
|||
struct def *
|
||||
lookup(id, scope)
|
||||
register struct idf *id;
|
||||
struct scope *scope;
|
||||
{
|
||||
/* Look up a definition of an identifier in scope "scope".
|
||||
Make the "def" list self-organizing.
|
||||
|
@ -114,7 +115,6 @@ lookup(id, scope)
|
|||
|
||||
df1 = 0;
|
||||
df = id->id_def;
|
||||
DO_DEBUG(5, debug("Looking for identifier \"%s\" in scope %d", id->id_text, scope));
|
||||
while (df) {
|
||||
if (df->df_scope == scope) {
|
||||
retval = df;
|
||||
|
@ -148,7 +148,7 @@ Export(ids, qualified)
|
|||
struct node *nd = ids;
|
||||
|
||||
while (ids) {
|
||||
df = lookup(ids->nd_IDF, CurrentScope->sc_scope);
|
||||
df = lookup(ids->nd_IDF, CurrentScope);
|
||||
if (df && (df->df_flags & (D_EXPORTED|D_QEXPORTED))) {
|
||||
node_error(ids, "Identifier \"%s\" occurs more than once in export list",
|
||||
df->df_idf->id_text);
|
||||
|
@ -163,8 +163,7 @@ df->df_idf->id_text);
|
|||
}
|
||||
else {
|
||||
df->df_flags |= D_EXPORTED;
|
||||
df1 = lookup(ids->nd_IDF,
|
||||
enclosing(CurrentScope)->sc_scope);
|
||||
df1 = lookup(ids->nd_IDF, enclosing(CurrentScope));
|
||||
if (! df1 || !(df1->df_kind & (D_PROCHEAD|D_HIDDEN))) {
|
||||
df1 = define(ids->nd_IDF,
|
||||
enclosing(CurrentScope),
|
||||
|
@ -185,6 +184,49 @@ df->df_idf->id_text);
|
|||
FreeNode(nd);
|
||||
}
|
||||
|
||||
static struct scope *
|
||||
ForwModule(df, idn)
|
||||
register struct def *df;
|
||||
struct node *idn;
|
||||
{
|
||||
/* An import is done from a not yet defined module "idn".
|
||||
Create a declaration and a scope for this module.
|
||||
*/
|
||||
struct scope *scope;
|
||||
|
||||
df->df_scope = enclosing(CurrentScope);
|
||||
df->df_kind = D_FORWMODULE;
|
||||
open_scope(CLOSEDSCOPE);
|
||||
scope = CurrentScope; /* The new scope, but watch out, it's "next"
|
||||
field is not set right. It must indicate the
|
||||
enclosing scope, but this must be done AFTER
|
||||
closing this one
|
||||
*/
|
||||
df->for_scope = scope;
|
||||
df->for_node = MkNode(Name, NULLNODE, NULLNODE, &(idn->nd_token));
|
||||
close_scope(0);
|
||||
scope->next = df->df_scope;
|
||||
/* Here ! */
|
||||
return scope;
|
||||
}
|
||||
|
||||
static struct def *
|
||||
ForwDef(ids, scope)
|
||||
register struct node *ids;
|
||||
struct scope *scope;
|
||||
{
|
||||
/* Enter a forward definition of "ids" in scope "scope",
|
||||
if it is not already defined.
|
||||
*/
|
||||
register struct def *df;
|
||||
|
||||
if (!(df = lookup(ids->nd_IDF, scope))) {
|
||||
df = define(ids->nd_IDF, scope, D_FORWARD);
|
||||
df->for_node = MkNode(Name,NULLNODE,NULLNODE,&(ids->nd_token));
|
||||
}
|
||||
return df;
|
||||
}
|
||||
|
||||
Import(ids, idn, local)
|
||||
register struct node *ids;
|
||||
struct node *idn;
|
||||
|
@ -203,63 +245,51 @@ Import(ids, idn, local)
|
|||
identifiers defined in this module.
|
||||
*/
|
||||
register struct def *df;
|
||||
struct def *df1 = 0;
|
||||
int scope;
|
||||
int kind;
|
||||
int imp_kind;
|
||||
struct scope *scope = enclosing(CurrentScope);
|
||||
int kind = D_IMPORT;
|
||||
int forwflag = 0;
|
||||
#define FROM_MODULE 0
|
||||
#define FROM_ENCLOSING 1
|
||||
int imp_kind = FROM_ENCLOSING;
|
||||
struct def *lookfor(), *GetDefinitionModule();
|
||||
|
||||
kind = D_IMPORT;
|
||||
scope = enclosing(CurrentScope)->sc_scope;
|
||||
|
||||
if (! idn) imp_kind = FROM_ENCLOSING;
|
||||
else {
|
||||
if (idn) {
|
||||
imp_kind = FROM_MODULE;
|
||||
if (local) {
|
||||
df = lookfor(idn, enclosing(CurrentScope), 0);
|
||||
if (df->df_kind == D_ERROR) {
|
||||
df = lookfor(idn, scope, 0);
|
||||
switch(df->df_kind) {
|
||||
case D_ERROR:
|
||||
/* The module from which the import was done
|
||||
is not yet declared. I'm not sure if I must
|
||||
accept this, but for the time being I will.
|
||||
???
|
||||
*/
|
||||
df->df_scope = scope;
|
||||
df->df_kind = D_FORWMODULE;
|
||||
open_scope(CLOSEDSCOPE, 0);
|
||||
df->for_scope = CurrentScope->sc_scope;
|
||||
df->for_node = MkNode(Name, NULLNODE,
|
||||
NULLNODE, &(idn->nd_token));
|
||||
close_scope();
|
||||
df1 = df;
|
||||
}
|
||||
}
|
||||
else df = GetDefinitionModule(idn->nd_IDF);
|
||||
|
||||
if (!(df->df_kind & (D_MODULE|D_FORWMODULE))) {
|
||||
/* enter all "ids" with type D_ERROR */
|
||||
kind = D_ERROR;
|
||||
if (df->df_kind != D_ERROR) {
|
||||
scope = ForwModule(df, idn);
|
||||
forwflag = 1;
|
||||
break;
|
||||
case D_FORWMODULE:
|
||||
scope = df->for_scope;
|
||||
break;
|
||||
case D_MODULE:
|
||||
scope = df->mod_scope;
|
||||
break;
|
||||
default:
|
||||
kind = D_ERROR;
|
||||
node_error(idn, "identifier \"%s\" does not represent a module",
|
||||
idn->nd_IDF->id_text);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else scope = df->mod_scope;
|
||||
else scope = GetDefinitionModule(idn->nd_IDF)->mod_scope;
|
||||
|
||||
FreeNode(idn);
|
||||
}
|
||||
|
||||
idn = ids;
|
||||
while (ids) {
|
||||
if (imp_kind == FROM_MODULE) {
|
||||
if (df1 != 0) {
|
||||
open_scope(CLOSEDSCOPE, df1->mod_scope);
|
||||
df = define(ids->nd_IDF,
|
||||
CurrentScope,
|
||||
D_FORWARD);
|
||||
df->for_node = MkNode(Name, NULLNODE,
|
||||
NULLNODE, &(ids->nd_token));
|
||||
close_scope(0);
|
||||
if (forwflag) {
|
||||
df = ForwDef(ids, scope);
|
||||
}
|
||||
else if (!(df = lookup(ids->nd_IDF, scope))) {
|
||||
node_error(ids, "identifier \"%s\" not declared in qualifying module",
|
||||
|
@ -272,29 +302,22 @@ ids->nd_IDF->id_text);
|
|||
}
|
||||
}
|
||||
else {
|
||||
if (local) {
|
||||
df = lookfor(ids, enclosing(CurrentScope), 0);
|
||||
} else df = GetDefinitionModule(ids->nd_IDF);
|
||||
if (df->df_kind == D_ERROR) {
|
||||
/* It was not yet defined in the enclosing
|
||||
scope.
|
||||
*/
|
||||
df->df_kind = D_FORWARD;
|
||||
df->for_node = MkNode(Name, NULLNODE, NULLNODE,
|
||||
&(ids->nd_token));
|
||||
}
|
||||
if (local) df = ForwDef(ids, scope);
|
||||
else df = GetDefinitionModule(ids->nd_IDF);
|
||||
}
|
||||
|
||||
DO_DEBUG(2, debug("importing \"%s\", kind %d", ids->nd_IDF->id_text,
|
||||
df->df_kind));
|
||||
define(ids->nd_IDF, CurrentScope, kind)->imp_def = df;
|
||||
if (df->df_kind == D_TYPE &&
|
||||
df->df_type->tp_fund == T_ENUMERATION) {
|
||||
/* Also import all enumeration literals */
|
||||
exprt_literals(df->df_type->enm_enums,
|
||||
CurrentScope);
|
||||
/* Also import all enumeration literals
|
||||
*/
|
||||
exprt_literals(df->df_type->enm_enums, CurrentScope);
|
||||
}
|
||||
ids = ids->next;
|
||||
}
|
||||
|
||||
FreeNode(idn);
|
||||
}
|
||||
|
||||
|
@ -305,9 +328,9 @@ exprt_literals(df, toscope)
|
|||
/* A list of enumeration literals is exported. This is implemented
|
||||
as an import from the scope "toscope".
|
||||
*/
|
||||
DO_DEBUG(2, debug("enumeration import:"));
|
||||
DO_DEBUG(3, debug("enumeration import:"));
|
||||
while (df) {
|
||||
DO_DEBUG(2, debug(df->df_idf->id_text));
|
||||
DO_DEBUG(3, debug(df->df_idf->id_text));
|
||||
define(df->df_idf, toscope, D_IMPORT)->imp_def = df;
|
||||
df = df->enm_next;
|
||||
}
|
||||
|
@ -353,3 +376,11 @@ RemFromId(df)
|
|||
df1->next = df->next;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
PrDef(df)
|
||||
register struct def *df;
|
||||
{
|
||||
debug("name: %s, kind: %d", df->df_idf->id_text, df->df_kind);
|
||||
}
|
||||
#endif DEBUG
|
||||
|
|
|
@ -49,7 +49,7 @@ GetDefinitionModule(id)
|
|||
*/
|
||||
struct def *df;
|
||||
|
||||
df = lookup(id, GlobalScope->sc_scope);
|
||||
df = lookup(id, GlobalScope);
|
||||
if (!df) {
|
||||
/* Read definition module. Make an exception for SYSTEM.
|
||||
*/
|
||||
|
@ -60,7 +60,7 @@ GetDefinitionModule(id)
|
|||
GetFile(id->id_text);
|
||||
DefModule();
|
||||
}
|
||||
df = lookup(id, GlobalScope->sc_scope);
|
||||
df = lookup(id, GlobalScope);
|
||||
}
|
||||
assert(df != 0 && df->df_kind == D_MODULE);
|
||||
return df;
|
||||
|
|
|
@ -35,10 +35,11 @@ Enter(name, kind, type, pnam)
|
|||
return df;
|
||||
}
|
||||
|
||||
EnterIdList(idlist, kind, flags, type, scope)
|
||||
EnterIdList(idlist, kind, flags, type, scope, addr)
|
||||
register struct node *idlist;
|
||||
struct type *type;
|
||||
struct scope *scope;
|
||||
arith *addr;
|
||||
{
|
||||
/* Put a list of identifiers in the symbol table.
|
||||
They all have kind "kind", and type "type", and are put
|
||||
|
@ -50,11 +51,29 @@ EnterIdList(idlist, kind, flags, type, scope)
|
|||
register struct def *df;
|
||||
struct def *first = 0, *last = 0;
|
||||
int assval = 0;
|
||||
arith off;
|
||||
|
||||
while (idlist) {
|
||||
df = define(idlist->nd_IDF, scope, kind);
|
||||
df->df_type = type;
|
||||
df->df_flags |= flags;
|
||||
if (addr) {
|
||||
if (*addr >= 0) {
|
||||
off = align(*addr, type->tp_align);
|
||||
*addr = off + type->tp_size;
|
||||
}
|
||||
else {
|
||||
off = -align(-*addr, type->tp_align);
|
||||
*addr = off - type->tp_size;
|
||||
}
|
||||
if (kind == D_VARIABLE) {
|
||||
df->var_off = off;
|
||||
}
|
||||
else {
|
||||
assert(kind == D_FIELD);
|
||||
df->fld_off = off;
|
||||
}
|
||||
}
|
||||
if (kind == D_ENUM) {
|
||||
if (!first) first = df;
|
||||
df->enm_val = assval++;
|
||||
|
@ -72,6 +91,45 @@ EnterIdList(idlist, kind, flags, type, scope)
|
|||
}
|
||||
}
|
||||
|
||||
EnterVarList(IdList, type, local)
|
||||
register struct node *IdList;
|
||||
struct type *type;
|
||||
{
|
||||
register struct def *df;
|
||||
struct scope *scope;
|
||||
|
||||
if (local) {
|
||||
/* Find the closest enclosing open scope. This
|
||||
is the procedure that we are dealing with
|
||||
*/
|
||||
scope = CurrentScope;
|
||||
while (scope->sc_scopeclosed) scope = scope->next;
|
||||
}
|
||||
|
||||
while (IdList) {
|
||||
df = define(IdList->nd_IDF, CurrentScope, D_VARIABLE);
|
||||
df->df_type = type;
|
||||
if (IdList->nd_left) {
|
||||
df->var_addrgiven = 1;
|
||||
if (IdList->nd_left->nd_type != card_type) {
|
||||
node_error(IdList->nd_left,"Illegal type for address");
|
||||
}
|
||||
df->var_off = IdList->nd_left->nd_INT;
|
||||
}
|
||||
else if (local) {
|
||||
arith off;
|
||||
|
||||
/* add aligned size of variable to the offset
|
||||
*/
|
||||
off = scope->sc_off - type->tp_size;
|
||||
off = -align(-off, type->tp_align);
|
||||
df->var_off = off;
|
||||
scope->sc_off = off;
|
||||
}
|
||||
IdList = IdList->nd_right;
|
||||
}
|
||||
}
|
||||
|
||||
struct def *
|
||||
lookfor(id, scope, give_error)
|
||||
struct node *id;
|
||||
|
@ -86,7 +144,7 @@ lookfor(id, scope, give_error)
|
|||
register struct scope *sc = scope;
|
||||
|
||||
while (sc) {
|
||||
df = lookup(id->nd_IDF, sc->sc_scope);
|
||||
df = lookup(id->nd_IDF, sc);
|
||||
if (df) return df;
|
||||
sc = nextvisible(sc);
|
||||
}
|
||||
|
|
|
@ -22,9 +22,7 @@ number(struct node **p;)
|
|||
struct type *tp;
|
||||
} :
|
||||
[
|
||||
INTEGER { tp = dot.TOK_INT <= max_int ?
|
||||
intorcard_type : card_type;
|
||||
}
|
||||
INTEGER { tp = numtype; }
|
||||
|
|
||||
REAL { tp = real_type; }
|
||||
] { *p = MkNode(Value, NULLNODE, NULLNODE, &dot);
|
||||
|
|
|
@ -74,7 +74,7 @@ Compile(src)
|
|||
if (options['L']) LexScan();
|
||||
else {
|
||||
#endif DEBUG
|
||||
(void) open_scope(CLOSEDSCOPE, 0);
|
||||
(void) open_scope(CLOSEDSCOPE);
|
||||
GlobalScope = CurrentScope;
|
||||
CompUnit();
|
||||
#ifdef DEBUG
|
||||
|
@ -192,7 +192,7 @@ PROCEDURE NEWPROCESS(P:PROC; A:ADDRESS; n:CARDINAL; VAR p1:ADDRESS);\n\
|
|||
PROCEDURE TRANSFER(VAR p1,p2:ADDRESS);\n\
|
||||
END SYSTEM.\n";
|
||||
|
||||
open_scope(CLOSEDSCOPE, 0);
|
||||
open_scope(CLOSEDSCOPE);
|
||||
(void) Enter("WORD", D_TYPE, word_type, 0);
|
||||
(void) Enter("ADDRESS", D_TYPE, address_type, 0);
|
||||
(void) Enter("ADR", D_PROCEDURE, std_type, S_ADR);
|
||||
|
@ -202,7 +202,7 @@ END SYSTEM.\n";
|
|||
}
|
||||
SYSTEMModule = 1;
|
||||
DefModule();
|
||||
close_scope();
|
||||
close_scope(0);
|
||||
SYSTEMModule = 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,6 @@ static int DEFofIMPL = 0; /* Flag indicating that we are currently
|
|||
implementation module currently being
|
||||
compiled
|
||||
*/
|
||||
static struct def *impl_df;
|
||||
}
|
||||
/*
|
||||
The grammar as given by Wirth is already almost LL(1); the
|
||||
|
@ -50,10 +49,10 @@ ModuleDeclaration
|
|||
id = dot.TOK_IDF;
|
||||
df = define(id, CurrentScope, D_MODULE);
|
||||
if (!df->mod_scope) {
|
||||
open_scope(CLOSEDSCOPE, 0);
|
||||
df->mod_scope = CurrentScope->sc_scope;
|
||||
open_scope(CLOSEDSCOPE);
|
||||
df->mod_scope = CurrentScope;
|
||||
}
|
||||
else open_scope(CLOSEDSCOPE, df->mod_scope);
|
||||
else CurrentScope = df->mod_scope;
|
||||
df->df_type =
|
||||
standard_type(T_RECORD, 0, (arith) 0);
|
||||
df->df_type->rec_scope = df->mod_scope;
|
||||
|
@ -123,8 +122,8 @@ DefinitionModule
|
|||
DEFINITION
|
||||
MODULE IDENT { id = dot.TOK_IDF;
|
||||
df = define(id, GlobalScope, D_MODULE);
|
||||
if (!SYSTEMModule) open_scope(CLOSEDSCOPE, 0);
|
||||
df->mod_scope = CurrentScope->sc_scope;
|
||||
if (!SYSTEMModule) open_scope(CLOSEDSCOPE);
|
||||
df->mod_scope = CurrentScope;
|
||||
df->df_type = standard_type(T_RECORD, 0, (arith) 0);
|
||||
df->df_type->rec_scope = df->mod_scope;
|
||||
DefinitionModule = 1;
|
||||
|
@ -144,7 +143,6 @@ DefinitionModule
|
|||
implementation module being compiled
|
||||
*/
|
||||
RemImports(&(CurrentScope->sc_def));
|
||||
impl_df = CurrentScope->sc_def;
|
||||
}
|
||||
df = CurrentScope->sc_def;
|
||||
while (df) {
|
||||
|
@ -174,7 +172,8 @@ definition
|
|||
The export is said to be opaque.
|
||||
It is restricted to pointer types.
|
||||
*/
|
||||
{ df->df_kind = D_HIDDEN; }
|
||||
{ df->df_kind = D_HIDDEN;
|
||||
}
|
||||
]
|
||||
';'
|
||||
]*
|
||||
|
@ -188,20 +187,19 @@ ProgramModule(int state;)
|
|||
{
|
||||
struct idf *id;
|
||||
struct def *df, *GetDefinitionModule();
|
||||
int scope = 0;
|
||||
struct scope *scope = 0;
|
||||
} :
|
||||
MODULE
|
||||
IDENT {
|
||||
id = dot.TOK_IDF;
|
||||
if (state == IMPLEMENTATION) {
|
||||
DEFofIMPL = 1;
|
||||
df = GetDefinitionModule(id);
|
||||
scope = df->mod_scope;
|
||||
DEFofIMPL = 0;
|
||||
DEFofIMPL = 1;
|
||||
df = GetDefinitionModule(id);
|
||||
CurrentScope = df->mod_scope;
|
||||
DEFofIMPL = 0;
|
||||
DefinitionModule = 0;
|
||||
}
|
||||
DefinitionModule = 0;
|
||||
open_scope(CLOSEDSCOPE, scope);
|
||||
CurrentScope->sc_def = impl_df;
|
||||
else open_scope(CLOSEDSCOPE);
|
||||
}
|
||||
priority?
|
||||
';' import(0)*
|
||||
|
|
|
@ -14,40 +14,28 @@ static char *RcsId = "$Header$";
|
|||
#include "node.h"
|
||||
#include "debug.h"
|
||||
|
||||
static int maxscope; /* maximum assigned scope number */
|
||||
|
||||
struct scope *CurrentScope, *GlobalScope;
|
||||
struct scope *CurrentScope, *PervasiveScope, *GlobalScope;
|
||||
|
||||
/* STATICALLOCDEF "scope" */
|
||||
|
||||
open_scope(scopetype, scope)
|
||||
open_scope(scopetype)
|
||||
{
|
||||
/* Open a scope that is either open (automatic imports) or closed.
|
||||
A closed scope is handled by adding an extra entry to the list
|
||||
with scope number 0. This has two purposes: it makes scope 0
|
||||
visible, and it marks the end of a visibility list.
|
||||
Scope 0 is the pervasive scope, the one that is always visible.
|
||||
A disadvantage of this method is that we cannot open scope 0
|
||||
explicitly.
|
||||
*/
|
||||
register struct scope *sc = new_scope();
|
||||
register struct scope *sc1;
|
||||
|
||||
sc->sc_scope = scope == 0 ? ++maxscope : scope;
|
||||
assert(scopetype == OPENSCOPE || scopetype == CLOSEDSCOPE);
|
||||
sc->sc_scopeclosed = scopetype == CLOSEDSCOPE;
|
||||
sc->sc_forw = 0;
|
||||
sc->sc_def = 0;
|
||||
assert(scopetype == OPENSCOPE || scopetype == CLOSEDSCOPE);
|
||||
sc->sc_off = 0;
|
||||
sc->next = 0;
|
||||
DO_DEBUG(1, debug("Opening a %s scope",
|
||||
scopetype == OPENSCOPE ? "open" : "closed"));
|
||||
sc1 = CurrentScope;
|
||||
if (scopetype == CLOSEDSCOPE) {
|
||||
sc1 = new_scope();
|
||||
sc1->sc_scope = 0; /* Pervasive scope nr */
|
||||
sc1->sc_forw = 0;
|
||||
sc1->sc_def = 0;
|
||||
sc1->next = CurrentScope;
|
||||
if (CurrentScope != PervasiveScope) {
|
||||
sc->next = CurrentScope;
|
||||
}
|
||||
sc->next = sc1;
|
||||
CurrentScope = sc;
|
||||
}
|
||||
|
||||
|
@ -55,18 +43,14 @@ init_scope()
|
|||
{
|
||||
register struct scope *sc = new_scope();
|
||||
|
||||
sc->sc_scope = 0;
|
||||
sc->sc_scopeclosed = 0;
|
||||
sc->sc_forw = 0;
|
||||
sc->sc_def = 0;
|
||||
sc->next = 0;
|
||||
PervasiveScope = sc;
|
||||
CurrentScope = sc;
|
||||
}
|
||||
|
||||
int
|
||||
uniq_scope()
|
||||
{
|
||||
return ++maxscope;
|
||||
}
|
||||
|
||||
struct forwards {
|
||||
struct forwards *next;
|
||||
struct node fo_tok;
|
||||
|
@ -92,73 +76,67 @@ Forward(tk, ptp)
|
|||
CurrentScope->sc_forw = f;
|
||||
}
|
||||
|
||||
close_scope(flag)
|
||||
static
|
||||
chk_proc(df)
|
||||
register struct def *df;
|
||||
{
|
||||
/* Close a scope. If "flag" is set, check for forward declarations,
|
||||
either POINTER declarations, or EXPORTs, or forward references
|
||||
to MODULES
|
||||
/* Called at scope closing. Check all definitions, and if one
|
||||
is a D_PROCHEAD, the procedure was not defined
|
||||
*/
|
||||
register struct scope *sc = CurrentScope;
|
||||
register struct def *df, *dfback = 0;
|
||||
|
||||
assert(sc != 0);
|
||||
DO_DEBUG(1, debug("Closing a scope"));
|
||||
|
||||
if (flag) {
|
||||
if (sc->sc_forw) rem_forwards(sc->sc_forw);
|
||||
df = sc->sc_def;
|
||||
while(df) {
|
||||
if (flag & SC_CHKPROC) {
|
||||
if (df->df_kind == D_PROCHEAD) {
|
||||
/* A not defined procedure
|
||||
*/
|
||||
while (df) {
|
||||
if (df->df_kind == D_PROCHEAD) {
|
||||
/* A not defined procedure
|
||||
*/
|
||||
node_error(df->for_node, "procedure \"%s\" not defined", df->df_idf->id_text);
|
||||
FreeNode(df->for_node);
|
||||
}
|
||||
}
|
||||
if ((flag & SC_CHKFORW) &&
|
||||
df->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!
|
||||
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
|
||||
*/
|
||||
struct def *df1 = df->df_nextinscope;
|
||||
|
||||
if (scopeclosed(CurrentScope)) {
|
||||
/* Indeed, the scope was a closed
|
||||
scope, so give error message
|
||||
*/
|
||||
node_error(df->for_node, "identifier \"%s\" not declared", df->df_idf->id_text);
|
||||
FreeNode(df->for_node);
|
||||
dfback = df;
|
||||
}
|
||||
else {
|
||||
/* This scope was an open scope.
|
||||
Maybe the definitions are in the
|
||||
enclosing scope?
|
||||
*/
|
||||
struct scope *sc;
|
||||
|
||||
sc = enclosing(CurrentScope);
|
||||
df->df_nextinscope = sc->sc_def;
|
||||
sc->sc_def = df;
|
||||
df->df_scope = sc->sc_scope;
|
||||
if (dfback) dfback->df_nextinscope = df1;
|
||||
else sc->sc_def = df1;
|
||||
}
|
||||
df = df1;
|
||||
node_error((*pdf)->for_node, "identifier \"%s\" has not been declared",
|
||||
(*pdf)->df_idf->id_text);
|
||||
FreeNode((*pdf)->for_node);
|
||||
pdf = &(*pdf)->df_nextinscope;
|
||||
}
|
||||
else {
|
||||
dfback = df;
|
||||
df = df->df_nextinscope;
|
||||
else { /* This scope was an open scope.
|
||||
Maybe the definitions are in the
|
||||
enclosing scope?
|
||||
*/
|
||||
struct scope *sc;
|
||||
|
||||
sc = enclosing(CurrentScope);
|
||||
if ((*pdf)->df_kind == D_FORWMODULE) {
|
||||
(*pdf)->for_scope->next = sc;
|
||||
}
|
||||
(*pdf)->df_nextinscope = sc->sc_def;
|
||||
sc->sc_def = *pdf;
|
||||
(*pdf)->df_scope = sc;
|
||||
*pdf = df1;
|
||||
}
|
||||
}
|
||||
else pdf = &(*pdf)->df_nextinscope;
|
||||
}
|
||||
|
||||
if (sc->next && (sc->next->sc_scope == 0)) {
|
||||
sc = sc->next;
|
||||
}
|
||||
CurrentScope = sc->next;
|
||||
}
|
||||
|
||||
static
|
||||
|
@ -182,3 +160,35 @@ rem_forwards(fo)
|
|||
free_forwards(f);
|
||||
}
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
CurrentScope = sc->next;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
PrScopeDef(df)
|
||||
register struct def *df;
|
||||
{
|
||||
debug("List of definitions in currently ended scope:");
|
||||
while (df) {
|
||||
PrDef(df);
|
||||
df = df->df_nextinscope;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -16,16 +16,15 @@ struct scope {
|
|||
struct scope *next;
|
||||
struct forwards *sc_forw;
|
||||
struct def *sc_def; /* list of definitions in this scope */
|
||||
int sc_scope; /* The scope number. Scope number 0 indicates
|
||||
both the pervasive scope and the end of a
|
||||
visibility range
|
||||
*/
|
||||
arith sc_off; /* offsets of variables in this scope */
|
||||
char sc_scopeclosed; /* flag indicating closed or open scope */
|
||||
};
|
||||
|
||||
extern struct scope
|
||||
*CurrentScope,
|
||||
*PervasiveScope,
|
||||
*GlobalScope;
|
||||
|
||||
#define nextvisible(x) ((x)->sc_scope ? (x)->next : (struct scope *) 0)
|
||||
#define scopeclosed(x) ((x)->next->sc_scope == 0)
|
||||
#define enclosing(x) (scopeclosed(x) ? (x)->next->next : (x)->next)
|
||||
#define enclosing(x) ((x)->next)
|
||||
#define scopeclosed(x) ((x)->sc_scopeclosed)
|
||||
#define nextvisible(x) (scopeclosed(x) ? PervasiveScope : enclosing(x))
|
||||
|
|
|
@ -6,12 +6,15 @@ static char *RcsId = "$Header$";
|
|||
#include <em_arith.h>
|
||||
#include "LLlex.h"
|
||||
#include "node.h"
|
||||
|
||||
static int loopcount = 0; /* Count nested loops */
|
||||
}
|
||||
|
||||
statement
|
||||
statement(struct node **pnd;)
|
||||
{
|
||||
struct node *nd1, *nd2 = 0;
|
||||
struct node *nd1;
|
||||
} :
|
||||
{ *pnd = 0; }
|
||||
[
|
||||
/*
|
||||
* This part is not in the reference grammar. The reference grammar
|
||||
|
@ -19,38 +22,45 @@ statement
|
|||
* but this gives LL(1) conflicts
|
||||
*/
|
||||
designator(&nd1)
|
||||
[
|
||||
ActualParameters(&nd2)?
|
||||
{ nd1 = MkNode(Call, nd1, nd2, &dot);
|
||||
[ { nd1 = MkNode(Call, nd1, NULLNODE, &dot);
|
||||
nd1->nd_symb = '(';
|
||||
}
|
||||
ActualParameters(&(nd1->nd_right))?
|
||||
|
|
||||
BECOMES { nd1 = MkNode(Stat, nd1, NULLNODE, &dot); }
|
||||
expression(&(nd1->nd_right))
|
||||
]
|
||||
{ *pnd = nd1; }
|
||||
/*
|
||||
* end of changed part
|
||||
*/
|
||||
|
|
||||
IfStatement
|
||||
IfStatement(pnd)
|
||||
|
|
||||
CaseStatement
|
||||
CaseStatement(pnd)
|
||||
|
|
||||
WhileStatement
|
||||
WhileStatement(pnd)
|
||||
|
|
||||
RepeatStatement
|
||||
RepeatStatement(pnd)
|
||||
|
|
||||
LoopStatement
|
||||
{ loopcount++; }
|
||||
LoopStatement(pnd)
|
||||
{ loopcount--; }
|
||||
|
|
||||
ForStatement
|
||||
ForStatement(pnd)
|
||||
|
|
||||
WithStatement
|
||||
WithStatement(pnd)
|
||||
|
|
||||
EXIT
|
||||
{ if (!loopcount) {
|
||||
error("EXIT not in a LOOP");
|
||||
}
|
||||
*pnd = MkNode(Stat, NULLNODE, NULLNODE, &dot);
|
||||
}
|
||||
|
|
||||
RETURN
|
||||
RETURN { *pnd = MkNode(Stat, NULLNODE, NULLNODE, &dot); }
|
||||
[
|
||||
expression(&nd1)
|
||||
expression(&((*pnd)->nd_right))
|
||||
]?
|
||||
]?
|
||||
;
|
||||
|
@ -67,66 +77,132 @@ ProcedureCall:
|
|||
;
|
||||
*/
|
||||
|
||||
StatementSequence:
|
||||
statement [ ';' statement ]*
|
||||
StatementSequence(struct node **pnd;):
|
||||
statement(pnd)
|
||||
[
|
||||
';' { *pnd = MkNode(Link, *pnd, NULLNODE, &dot);
|
||||
pnd = &((*pnd)->nd_right);
|
||||
}
|
||||
statement(pnd)
|
||||
]*
|
||||
;
|
||||
|
||||
IfStatement
|
||||
IfStatement(struct node **pnd;)
|
||||
{
|
||||
struct node *nd1;
|
||||
register struct node *nd;
|
||||
} :
|
||||
IF expression(&nd1) THEN StatementSequence
|
||||
[ ELSIF expression(&nd1) THEN StatementSequence ]*
|
||||
[ ELSE StatementSequence ]?
|
||||
IF { nd = MkNode(Stat, NULLNODE, NULLNODE, &dot);
|
||||
*pnd = nd;
|
||||
}
|
||||
expression(&(nd->nd_left))
|
||||
THEN { nd = MkNode(Link, NULLNODE, NULLNODE, &dot);
|
||||
(*pnd)->nd_right = nd;
|
||||
}
|
||||
StatementSequence(&(nd->nd_left))
|
||||
[
|
||||
ELSIF { nd->nd_right = MkNode(Stat,NULLNODE,NULLNODE,&dot);
|
||||
nd = nd->nd_right;
|
||||
nd->nd_symb = IF;
|
||||
}
|
||||
expression(&(nd->nd_left))
|
||||
THEN { nd->nd_right = MkNode(Link,NULLNODE,NULLNODE,&dot);
|
||||
nd = nd->nd_right;
|
||||
}
|
||||
StatementSequence(&(nd->nd_left))
|
||||
]*
|
||||
[
|
||||
ELSE
|
||||
StatementSequence(&(nd->nd_right))
|
||||
]?
|
||||
END
|
||||
;
|
||||
|
||||
CaseStatement
|
||||
CaseStatement(struct node **pnd;)
|
||||
{
|
||||
struct node *nd;
|
||||
register struct node *nd;
|
||||
struct type *tp = 0;
|
||||
} :
|
||||
CASE expression(&nd) OF case [ '|' case ]*
|
||||
[ ELSE StatementSequence ]?
|
||||
CASE { *pnd = nd = MkNode(Stat, NULLNODE, NULLNODE, &dot); }
|
||||
expression(&(nd->nd_left))
|
||||
OF
|
||||
case(&(nd->nd_right), &tp)
|
||||
{ nd = nd->nd_right; }
|
||||
[
|
||||
'|'
|
||||
case(&(nd->nd_right), &tp)
|
||||
{ nd = nd->nd_right; }
|
||||
]*
|
||||
[ ELSE StatementSequence(&(nd->nd_right)) ]?
|
||||
END
|
||||
;
|
||||
|
||||
case:
|
||||
[ CaseLabelList ':' StatementSequence ]?
|
||||
case(struct node **pnd; struct type **ptp;) :
|
||||
{ *pnd = 0; }
|
||||
[ CaseLabelList(ptp/*,pnd*/)
|
||||
':' { *pnd = MkNode(Link, *pnd, NULLNODE, &dot); }
|
||||
StatementSequence(&((*pnd)->nd_right))
|
||||
]?
|
||||
/* This rule is changed in new modula-2 */
|
||||
{ *pnd = MkNode(Link, *pnd, NULLNODE, &dot);
|
||||
(*pnd)->nd_symb = '|';
|
||||
}
|
||||
;
|
||||
|
||||
WhileStatement
|
||||
WhileStatement(struct node **pnd;)
|
||||
{
|
||||
struct node *nd;
|
||||
register struct node *nd;
|
||||
}:
|
||||
WHILE expression(&nd) DO StatementSequence END
|
||||
WHILE { *pnd = nd = MkNode(Stat, NULLNODE, NULLNODE, &dot); }
|
||||
expression(&(nd->nd_left))
|
||||
DO
|
||||
StatementSequence(&(nd->nd_right))
|
||||
END
|
||||
;
|
||||
|
||||
RepeatStatement
|
||||
RepeatStatement(struct node **pnd;)
|
||||
{
|
||||
struct node *nd;
|
||||
register struct node *nd;
|
||||
}:
|
||||
REPEAT StatementSequence UNTIL expression(&nd)
|
||||
REPEAT { *pnd = nd = MkNode(Stat, NULLNODE, NULLNODE, &dot); }
|
||||
StatementSequence(&(nd->nd_left))
|
||||
UNTIL
|
||||
expression(&(nd->nd_right))
|
||||
;
|
||||
|
||||
ForStatement
|
||||
ForStatement(struct node **pnd;)
|
||||
{
|
||||
struct node *nd1, *nd2, *nd3;
|
||||
register struct node *nd;
|
||||
}:
|
||||
FOR IDENT
|
||||
BECOMES expression(&nd1)
|
||||
TO expression(&nd2)
|
||||
[ BY ConstExpression(&nd3) ]?
|
||||
DO StatementSequence END
|
||||
FOR { *pnd = MkNode(Stat, NULLNODE, NULLNODE, &dot); }
|
||||
IDENT { nd = MkNode(Name, NULLNODE, NULLNODE, &dot); }
|
||||
BECOMES { nd = MkNode(BECOMES, nd, NULLNODE, &dot); }
|
||||
expression(&(nd->nd_right))
|
||||
TO { (*pnd)->nd_left=nd=MkNode(Link,nd,NULLNODE,&dot); }
|
||||
expression(&(nd->nd_right))
|
||||
[
|
||||
BY { nd->nd_right=MkNode(Link,NULLNODE,nd->nd_right,&dot);
|
||||
}
|
||||
ConstExpression(&(nd->nd_right->nd_left))
|
||||
|
|
||||
]
|
||||
DO
|
||||
StatementSequence(&((*pnd)->nd_right))
|
||||
END
|
||||
;
|
||||
|
||||
LoopStatement:
|
||||
LOOP StatementSequence END
|
||||
LoopStatement(struct node **pnd;):
|
||||
LOOP { *pnd = MkNode(Stat, NULLNODE, NULLNODE, &dot); }
|
||||
StatementSequence(&((*pnd)->nd_right))
|
||||
END
|
||||
;
|
||||
|
||||
WithStatement
|
||||
WithStatement(struct node **pnd;)
|
||||
{
|
||||
struct node *nd;
|
||||
register struct node *nd;
|
||||
}:
|
||||
WITH designator(&nd) DO StatementSequence END
|
||||
WITH { *pnd = nd = MkNode(Stat, NULLNODE, NULLNODE, &dot); }
|
||||
designator(&(nd->nd_left))
|
||||
DO
|
||||
StatementSequence(&(nd->nd_right))
|
||||
END
|
||||
;
|
||||
|
|
|
@ -38,8 +38,8 @@ struct array {
|
|||
};
|
||||
|
||||
struct record {
|
||||
int rc_scope; /* Scope number of this record */
|
||||
/* Members are in the symbol table */
|
||||
struct scope *rc_scope; /* scope of this record */
|
||||
/* members are in the symbol table */
|
||||
#define rec_scope tp_value.tp_record.rc_scope
|
||||
};
|
||||
|
||||
|
@ -71,6 +71,7 @@ struct type {
|
|||
#define T_INTORCARD (T_INTEGER|T_CARDINAL)
|
||||
#define T_DISCRETE (T_ENUMERATION|T_INTORCARD|T_CHAR)
|
||||
#define T_NUMERIC (T_INTORCARD|T_REAL)
|
||||
#define T_INDEX (T_ENUMERATION|T_CHAR|T_SUBRANGE)
|
||||
int tp_align; /* alignment requirement of this type */
|
||||
arith tp_size; /* size of this type */
|
||||
union {
|
||||
|
|
|
@ -151,24 +151,6 @@ init_types()
|
|||
error_type = standard_type(T_CHAR, 1, (arith) 1);
|
||||
}
|
||||
|
||||
int
|
||||
has_selectors(df)
|
||||
register struct def *df;
|
||||
{
|
||||
|
||||
switch(df->df_kind) {
|
||||
case D_MODULE:
|
||||
return df->df_value.df_module.mo_scope;
|
||||
case D_VARIABLE:
|
||||
if (df->df_type->tp_fund == T_RECORD) {
|
||||
return df->df_type->rec_scope;
|
||||
}
|
||||
break;
|
||||
}
|
||||
error("no selectors for \"%s\"", df->df_idf->id_text);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Create a parameterlist of a procedure and return a pointer to it.
|
||||
"ids" indicates the list of identifiers, "tp" their type, and
|
||||
"VARp" is set when the parameters are VAR-parameters.
|
||||
|
@ -226,6 +208,8 @@ chk_basesubrange(tp, base)
|
|||
error("Specified base does not conform");
|
||||
}
|
||||
tp->next = base;
|
||||
tp->tp_size = base->tp_size;
|
||||
tp->tp_align = base->tp_align;
|
||||
}
|
||||
|
||||
struct type *
|
||||
|
@ -236,7 +220,7 @@ subr_type(lb, ub)
|
|||
indicated by "lb" and "ub", but first perform some
|
||||
checks
|
||||
*/
|
||||
register struct type *tp = lb->nd_type;
|
||||
register struct type *tp = lb->nd_type, *res;
|
||||
|
||||
if (!TstCompat(lb->nd_type, ub->nd_type)) {
|
||||
node_error(ub, "Types of subrange bounds not compatible");
|
||||
|
@ -264,11 +248,13 @@ subr_type(lb, ub)
|
|||
|
||||
/* Now construct resulting type
|
||||
*/
|
||||
tp = construct_type(T_SUBRANGE, tp);
|
||||
tp->sub_lb = lb->nd_INT;
|
||||
tp->sub_ub = ub->nd_INT;
|
||||
res = construct_type(T_SUBRANGE, tp);
|
||||
res->sub_lb = lb->nd_INT;
|
||||
res->sub_ub = ub->nd_INT;
|
||||
res->tp_size = tp->tp_size;
|
||||
res->tp_align = tp->tp_align;
|
||||
DO_DEBUG(2,debug("Creating subrange type %ld-%ld", (long)lb->nd_INT,(long)ub->nd_INT));
|
||||
return tp;
|
||||
return res;
|
||||
}
|
||||
#define MAX_SET 1024 /* ??? Maximum number of elements in a set */
|
||||
|
||||
|
@ -302,3 +288,71 @@ set_type(tp)
|
|||
tp->tp_size = align(((ub - lb) + 7)/8, wrd_align);
|
||||
return tp;
|
||||
}
|
||||
|
||||
ArraySizes(tp)
|
||||
register struct type *tp;
|
||||
{
|
||||
/* Assign sizes to an array type
|
||||
*/
|
||||
arith elem_size;
|
||||
register struct type *itype = tp->next; /* the index type */
|
||||
|
||||
if (tp->arr_elem->tp_fund == T_ARRAY) {
|
||||
ArraySizes(tp->arr_elem);
|
||||
}
|
||||
|
||||
elem_size = align(tp->arr_elem->tp_size, tp->arr_elem->tp_align);
|
||||
tp->tp_align = tp->arr_elem->tp_align;
|
||||
|
||||
if (! (itype->tp_fund & T_INDEX)) {
|
||||
error("Illegal index type");
|
||||
tp->tp_size = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
switch(itype->tp_fund) {
|
||||
case T_SUBRANGE:
|
||||
tp->arr_lb = itype->sub_lb;
|
||||
tp->arr_ub = itype->sub_ub;
|
||||
tp->tp_size = elem_size * (itype->sub_ub - itype->sub_lb + 1);
|
||||
break;
|
||||
case T_CHAR:
|
||||
case T_ENUMERATION:
|
||||
tp->arr_lb = 0;
|
||||
tp->arr_ub = itype->enm_ncst - 1;
|
||||
tp->tp_size = elem_size * itype->enm_ncst;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
/* ??? overflow checking ??? */
|
||||
}
|
||||
|
||||
int
|
||||
gcd(m, n)
|
||||
register int m, n;
|
||||
{
|
||||
/* Greatest Common Divisor
|
||||
*/
|
||||
register int r;
|
||||
|
||||
while (n) {
|
||||
r = m % n;
|
||||
m = n;
|
||||
n = r;
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
int
|
||||
lcm(m, n)
|
||||
register int m, n;
|
||||
{
|
||||
/* Least Common Multiple
|
||||
*/
|
||||
while (m != n) {
|
||||
if (m < n) m = m + m;
|
||||
else n = n + n;
|
||||
}
|
||||
return n; /* or m */
|
||||
}
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
|
||||
static char *RcsId = "$Header$";
|
||||
|
||||
/* Routines for testing type equivalence, type compatibility, and
|
||||
assignment compatibility
|
||||
*/
|
||||
#include <em_arith.h>
|
||||
#include <em_label.h>
|
||||
#include "type.h"
|
||||
|
@ -15,8 +18,8 @@ TstTypeEquiv(tp1, tp2)
|
|||
from the fact that for some procedures two declarations may
|
||||
be given: one in the specification module and one in the
|
||||
definition module.
|
||||
A related problem is that two dynamic arrays with the
|
||||
same base type are also equivalent.
|
||||
A related problem is that two dynamic arrays with
|
||||
equivalent base types are also equivalent.
|
||||
*/
|
||||
|
||||
return tp1 == tp2
|
||||
|
@ -66,8 +69,7 @@ TstProcEquiv(tp1, tp2)
|
|||
p1 = p1->next;
|
||||
p2 = p2->next;
|
||||
}
|
||||
if (p1 != p2) return 0;
|
||||
return 1;
|
||||
return p1 == p2;
|
||||
}
|
||||
|
||||
int
|
||||
|
|
Loading…
Reference in a new issue