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