ack/lang/m2/comp/declar.g

569 lines
10 KiB
Plaintext
Raw Normal View History

/*
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright".
*
* Author: Ceriel J.H. Jacobs
*/
1986-03-26 15:11:02 +00:00
/* D E C L A R A T I O N S */
1986-03-20 14:52:03 +00:00
/* $Header$ */
1986-03-26 15:11:02 +00:00
{
1986-05-01 19:06:53 +00:00
#include "debug.h"
1986-03-20 14:52:03 +00:00
1986-03-26 15:11:02 +00:00
#include <em_arith.h>
#include <em_label.h>
1986-04-08 18:15:46 +00:00
#include <alloc.h>
1986-03-26 22:46:48 +00:00
#include <assert.h>
1986-04-22 22:36:16 +00:00
#include "strict3rd.h"
1986-03-26 15:11:02 +00:00
#include "idf.h"
#include "LLlex.h"
#include "def.h"
#include "type.h"
#include "scope.h"
1986-04-06 17:42:56 +00:00
#include "node.h"
#include "misc.h"
1986-04-18 17:53:47 +00:00
#include "main.h"
1986-06-26 09:39:36 +00:00
#include "chk_expr.h"
1986-11-05 14:33:00 +00:00
#include "warning.h"
1987-11-09 16:11:04 +00:00
#include "nostrict.h"
1986-04-15 17:51:53 +00:00
1986-06-20 14:36:49 +00:00
int proclevel = 0; /* nesting level of procedures */
1986-10-06 20:36:30 +00:00
int return_occurred; /* set if a return occurs in a block */
extern t_node *EmptyStatement;
#define needs_static_link() (proclevel > 1)
1986-03-26 15:11:02 +00:00
}
1986-03-20 14:52:03 +00:00
/* inline in declaration: need space
* ProcedureDeclaration
* {
* t_def *df;
* } :
* { ++proclevel; }
* ProcedureHeading(&df, D_PROCEDURE)
* ';' block(&(df->prc_body))
* IDENT
* { EndProc(df, dot.TOK_IDF);
* --proclevel;
* }
* ;
*/
1986-03-26 15:11:02 +00:00
ProcedureHeading(t_def **pdf; int type;)
1986-03-26 15:11:02 +00:00
{
t_type *tp = 0;
arith parmaddr = needs_static_link() ? pointer_size : 0;
t_param *pr = 0;
1986-03-26 15:11:02 +00:00
} :
PROCEDURE IDENT
1986-10-06 20:36:30 +00:00
{ *pdf = DeclProc(type, dot.TOK_IDF); }
[
'('
[
FPSection(&pr, &parmaddr)
[
';' FPSection(&pr, &parmaddr)
]*
1988-02-10 14:06:34 +00:00
|
]
')'
[ ':' qualtype(&tp)
1988-02-10 14:06:34 +00:00
|
]
|
]
1986-12-09 17:41:06 +00:00
{ CheckWithDef(*pdf, proc_type(tp, pr, parmaddr));
1987-11-09 16:11:04 +00:00
#ifndef NOSTRICT
1986-12-09 17:41:06 +00:00
if (tp && IsConstructed(tp)) {
warning(W_STRICT, "procedure \"%s\" has a constructed result type",
(*pdf)->df_idf->id_text);
}
1987-11-09 10:17:20 +00:00
#endif
1986-12-09 17:41:06 +00:00
}
1986-03-20 14:52:03 +00:00
;
block(t_node **pnd;) :
[ %persistent
declaration
]*
{ return_occurred = 0; }
[ %default
1986-04-17 09:28:09 +00:00
BEGIN
StatementSequence(pnd)
|
{ *pnd = EmptyStatement; }
]
1986-04-17 09:28:09 +00:00
END
1986-03-20 14:52:03 +00:00
;
declaration
{
t_def *df;
} :
CONST [ ConstantDeclaration ';' ]*
1986-03-20 14:52:03 +00:00
|
TYPE [ TypeDeclaration ';' ]*
1986-03-20 14:52:03 +00:00
|
VAR [ VariableDeclaration ';' ]*
1986-03-20 14:52:03 +00:00
|
{ ++proclevel; }
ProcedureHeading(&df, D_PROCEDURE)
1990-07-30 15:56:25 +00:00
{ if (options['g']) stb_string(df, D_PROCEDURE); }
';'
block(&(df->prc_body))
IDENT
1990-07-30 15:56:25 +00:00
{ if (options['g']) stb_string(df, D_PEND);
EndProc(df, dot.TOK_IDF);
--proclevel;
}
';'
1986-03-20 14:52:03 +00:00
|
ModuleDeclaration ';'
;
/* inline in procedureheading: need space
* FormalParameters(t_param **ppr; arith *parmaddr; t_type **ptp;):
* '('
* [
* FPSection(ppr, parmaddr)
* [
* ';' FPSection(ppr, parmaddr)
* ]*
1988-02-10 14:06:34 +00:00
* |
* ]
* ')'
* [ ':' qualtype(ptp)
1988-02-10 14:06:34 +00:00
* |
* ]
* ;
*/
1986-03-20 14:52:03 +00:00
FPSection(t_param **ppr; arith *parmaddr;)
1986-03-20 14:52:03 +00:00
{
t_node *FPList;
t_type *tp;
int VARp;
1986-03-20 14:52:03 +00:00
} :
1986-08-26 14:33:24 +00:00
var(&VARp) IdentList(&FPList) ':' FormalType(&tp)
{ EnterParamList(ppr, FPList, tp, VARp, parmaddr); }
1986-03-20 14:52:03 +00:00
;
FormalType(t_type **ptp;)
/* index type of conformant array is "CARDINAL".
Recognize a conformant array by size 0.
*/
{ register t_type *tp;
} :
ARRAY OF
{ tp = construct_type(T_ARRAY, card_type); }
qualtype(&(tp->arr_elem))
{ ArrayElSize(tp);
1986-10-06 20:36:30 +00:00
*ptp = tp;
1986-04-21 17:27:06 +00:00
}
1986-08-26 14:33:24 +00:00
|
qualtype(ptp)
1986-03-20 14:52:03 +00:00
;
1986-03-26 15:11:02 +00:00
TypeDeclaration
{
t_def *df;
t_type *tp;
register t_node *nd;
1986-03-26 15:11:02 +00:00
}:
1986-12-01 10:06:53 +00:00
IDENT { df = define(dot.TOK_IDF, CurrentScope, D_TYPE);
nd = dot2leaf(Name);
1986-12-01 10:06:53 +00:00
}
1986-03-27 17:37:41 +00:00
'=' type(&tp)
1986-12-01 10:06:53 +00:00
{ DeclareType(nd, df, tp);
FreeNode(nd);
1990-07-30 15:56:25 +00:00
if (options['g']) stb_string(df, D_TYPE);
1986-12-01 10:06:53 +00:00
}
1986-03-20 14:52:03 +00:00
;
type(register t_type **ptp;):
1986-08-26 14:33:24 +00:00
%default SimpleType(ptp)
1986-03-20 14:52:03 +00:00
|
1986-03-27 17:37:41 +00:00
ArrayType(ptp)
1986-03-20 14:52:03 +00:00
|
1986-03-27 17:37:41 +00:00
RecordType(ptp)
1986-03-20 14:52:03 +00:00
|
1986-03-27 17:37:41 +00:00
SetType(ptp)
1986-03-20 14:52:03 +00:00
|
1986-03-27 17:37:41 +00:00
PointerType(ptp)
1986-03-20 14:52:03 +00:00
|
1986-03-27 17:37:41 +00:00
ProcedureType(ptp)
1986-03-20 14:52:03 +00:00
;
1988-10-21 17:24:34 +00:00
SimpleType(register t_type **ptp;) :
1986-07-08 14:59:02 +00:00
qualtype(ptp)
1986-03-20 14:52:03 +00:00
[
1986-03-29 01:04:49 +00:00
/* nothing */
1986-03-20 14:52:03 +00:00
|
1988-10-21 17:24:34 +00:00
SubrangeType(ptp)
1986-03-29 01:04:49 +00:00
/* The subrange type is given a base type by the
qualident (this is new modula-2).
*/
1986-03-20 14:52:03 +00:00
]
|
1986-03-27 17:37:41 +00:00
enumeration(ptp)
| { *ptp = 0; /* no qualification */ }
1986-03-27 17:37:41 +00:00
SubrangeType(ptp)
1986-03-20 14:52:03 +00:00
;
enumeration(t_type **ptp;)
1986-03-20 14:52:03 +00:00
{
t_node *EnumList;
1986-03-20 14:52:03 +00:00
} :
'(' IdentList(&EnumList) ')'
{ *ptp = enum_type(EnumList); }
1986-03-20 14:52:03 +00:00
;
IdentList(t_node **p;)
1986-03-20 14:52:03 +00:00
{
register t_node *q;
1986-03-20 14:52:03 +00:00
} :
IDENT { *p = q = dot2leaf(Value); }
1986-08-26 14:33:24 +00:00
[ %persistent
1986-04-06 17:42:56 +00:00
',' IDENT
{ q->nd_left = dot2leaf(Value);
1987-07-16 19:51:40 +00:00
q = q->nd_left;
1986-04-06 17:42:56 +00:00
}
1986-03-20 14:52:03 +00:00
]*
1987-07-16 19:51:40 +00:00
{ q->nd_left = 0; }
1986-03-20 14:52:03 +00:00
;
SubrangeType(t_type **ptp;)
1986-03-27 17:37:41 +00:00
{
t_node *nd1, *nd2;
1986-03-27 17:37:41 +00:00
}:
1986-03-20 14:52:03 +00:00
/*
This is not exactly the rule in the new report, but see
the rule for "SimpleType".
*/
1986-04-06 17:42:56 +00:00
'[' ConstExpression(&nd1)
UPTO ConstExpression(&nd2)
1986-03-27 17:37:41 +00:00
']'
1988-10-21 17:24:34 +00:00
{ *ptp = subr_type(nd1, nd2, *ptp);
FreeNode(nd1);
FreeNode(nd2);
1986-10-06 20:36:30 +00:00
}
1986-03-20 14:52:03 +00:00
;
ArrayType(t_type **ptp;)
1986-03-27 17:37:41 +00:00
{
t_type *tp;
register t_type *tp1, *tp2;
1986-03-27 17:37:41 +00:00
} :
ARRAY SimpleType(&tp)
{ tp1 = tp2 = construct_type(T_ARRAY, tp); }
1986-03-27 17:37:41 +00:00
[
',' SimpleType(&tp)
1986-05-28 18:36:51 +00:00
{ tp2->arr_elem = construct_type(T_ARRAY, tp);
tp2 = tp2->arr_elem;
1986-03-27 17:37:41 +00:00
}
]* OF type(&tp)
1986-04-15 17:51:53 +00:00
{ tp2->arr_elem = tp;
ArraySizes(tp1);
*ptp = tp1;
1986-04-15 17:51:53 +00:00
}
1986-03-20 14:52:03 +00:00
;
RecordType(t_type **ptp;)
1986-03-27 17:37:41 +00:00
{
register t_scope *scope;
1986-10-22 15:38:24 +00:00
arith size = 0;
1986-04-17 09:28:09 +00:00
int xalign = struct_align;
1986-03-27 17:37:41 +00:00
}
:
RECORD
{ scope = open_and_close_scope(OPENSCOPE); }
1986-10-06 20:36:30 +00:00
FieldListSequence(scope, &size, &xalign)
1986-12-01 10:06:53 +00:00
{ if (size == 0) {
warning(W_ORDINARY, "empty record declaration");
size = 1;
}
*ptp = standard_type(T_RECORD, xalign, align(size, xalign));
1986-04-15 17:51:53 +00:00
(*ptp)->rec_scope = scope;
1990-07-30 15:56:25 +00:00
Reverse(&(scope->sc_def));
1986-04-10 01:08:49 +00:00
}
1986-03-27 17:37:41 +00:00
END
1986-03-20 14:52:03 +00:00
;
FieldListSequence(t_scope *scope; arith *cnt; int *palign;):
1986-04-15 17:51:53 +00:00
FieldList(scope, cnt, palign)
1986-03-27 17:37:41 +00:00
[
1986-04-15 17:51:53 +00:00
';' FieldList(scope, cnt, palign)
1986-03-27 17:37:41 +00:00
]*
1986-03-20 14:52:03 +00:00
;
FieldList(t_scope *scope; arith *cnt; int *palign;)
1986-03-20 14:52:03 +00:00
{
t_node *FldList;
t_type *tp;
t_node *nd;
register t_def *df;
1986-04-15 17:51:53 +00:00
arith tcnt, max;
1986-03-20 14:52:03 +00:00
} :
[
1986-03-27 17:37:41 +00:00
IdentList(&FldList) ':' type(&tp)
{
*palign = lcm(*palign, tp->tp_align);
1986-06-10 13:18:52 +00:00
EnterFieldList(FldList, tp, scope, cnt);
1986-04-04 13:47:04 +00:00
}
1986-03-20 14:52:03 +00:00
|
1986-03-27 17:37:41 +00:00
CASE
1986-10-06 20:36:30 +00:00
/* Also accept old fashioned Modula-2 syntax, but give a warning.
Sorry for the complicated code.
1986-04-11 11:57:19 +00:00
*/
[ qualident(&nd)
1986-10-06 20:36:30 +00:00
[ ':' qualtype(&tp)
1986-07-08 14:59:02 +00:00
/* This is correct, in both kinds of Modula-2, if
1986-10-06 20:36:30 +00:00
the first qualident is a single identifier.
1986-04-11 11:57:19 +00:00
*/
1986-10-06 20:36:30 +00:00
{ if (nd->nd_class != Name) {
error("illegal variant tag");
}
1987-05-18 15:57:33 +00:00
else {
df = define(nd->nd_IDF, scope, D_FIELD);
*palign = lcm(*palign, tp->tp_align);
if (!(tp->tp_fund & T_DISCRETE)) {
error("illegal type in variant");
}
df->df_type = tp;
df->fld_off = align(*cnt, tp->tp_align);
*cnt = df->fld_off + tp->tp_size;
df->df_flags |= D_QEXPORTED;
}
1986-10-06 20:36:30 +00:00
FreeNode(nd);
}
| /* Old fashioned! the first qualident now represents
1986-04-11 11:57:19 +00:00
the type
*/
{
#ifndef STRICT_3RD_ED
if (! options['3']) warning(W_OLDFASHIONED,
"old fashioned Modula-2 syntax; ':' missing");
else
#endif
error("':' missing");
tp = qualified_type(nd);
1986-10-06 20:36:30 +00:00
}
]
| ':' qualtype(&tp)
/* Aha, third edition. Well done! */
1986-04-11 11:57:19 +00:00
]
1987-05-18 15:57:33 +00:00
{ tcnt = *cnt; }
1986-04-15 17:51:53 +00:00
OF variant(scope, &tcnt, tp, palign)
1986-10-06 20:36:30 +00:00
{ max = tcnt; tcnt = *cnt; }
1986-03-27 17:37:41 +00:00
[
1986-10-06 20:36:30 +00:00
'|' variant(scope, &tcnt, tp, palign)
{ if (tcnt > max) max = tcnt; tcnt = *cnt; }
1986-03-27 17:37:41 +00:00
]*
1986-04-15 17:51:53 +00:00
[ ELSE FieldListSequence(scope, &tcnt, palign)
1986-10-06 20:36:30 +00:00
{ if (tcnt > max) max = tcnt; }
1988-02-10 14:06:34 +00:00
|
]
1986-03-20 14:52:03 +00:00
END
1986-10-06 20:36:30 +00:00
{ *cnt = max; }
1988-02-10 14:06:34 +00:00
|
]
1986-03-20 14:52:03 +00:00
;
variant(t_scope *scope; arith *cnt; t_type *tp; int *palign;)
1986-04-15 17:51:53 +00:00
{
t_node *nd;
1986-04-15 17:51:53 +00:00
} :
[
1986-10-06 20:36:30 +00:00
CaseLabelList(&tp, &nd)
{ /* Ignore the cases for the time being.
Maybe a checking version will be supplied
later ???
1986-10-06 20:36:30 +00:00
*/
FreeNode(nd);
}
1986-04-17 09:28:09 +00:00
':' FieldListSequence(scope, cnt, palign)
1988-02-10 14:06:34 +00:00
|
]
1986-10-06 20:36:30 +00:00
/* Changed rule in new modula-2 */
1986-03-20 14:52:03 +00:00
;
CaseLabelList(t_type **ptp; t_node **pnd;):
1986-04-17 09:28:09 +00:00
CaseLabels(ptp, pnd)
[
{ *pnd = dot2node(Link, *pnd, NULLNODE); }
1986-04-17 09:28:09 +00:00
',' CaseLabels(ptp, &((*pnd)->nd_right))
{ pnd = &((*pnd)->nd_right); }
]*
1986-03-20 14:52:03 +00:00
;
CaseLabels(t_type **ptp; register t_node **pnd;)
1986-04-06 17:42:56 +00:00
{
register t_node *nd;
1986-04-06 17:42:56 +00:00
}:
1986-10-06 20:36:30 +00:00
ConstExpression(pnd)
{
if (*ptp != 0) {
t_type *tp = intorcard(*ptp,
BaseType((*pnd)->nd_type));
if (tp) *ptp = tp;
ChkCompat(pnd, *ptp, "case label");
}
nd = *pnd;
1988-04-29 09:16:51 +00:00
nd->nd_type = BaseType(nd->nd_type); /* ??? */
1987-11-26 14:15:24 +00:00
if (! (nd->nd_type->tp_fund & T_DISCRETE) ||
nd->nd_type->tp_size > word_size) {
node_error(nd, "illegal type in case label");
}
}
1986-04-15 17:51:53 +00:00
[
UPTO { *pnd = nd = dot2node(Link,nd,NULLNODE);
nd->nd_type = nd->nd_left->nd_type;
}
1986-10-06 20:36:30 +00:00
ConstExpression(&(*pnd)->nd_right)
{ if (!ChkCompat(&((*pnd)->nd_right), nd->nd_type,
"case label")) {
1987-05-18 15:57:33 +00:00
nd->nd_type = error_type;
1986-10-06 20:36:30 +00:00
}
else if (! chk_bounds(nd->nd_left->nd_INT,
nd->nd_right->nd_INT,
1988-04-29 09:16:51 +00:00
nd->nd_type->tp_fund)) {
node_error(nd,
"lower bound exceeds upper bound in case label range");
}
1986-10-06 20:36:30 +00:00
}
1988-02-10 14:06:34 +00:00
|
]
{
1987-05-18 15:57:33 +00:00
*ptp = nd->nd_type;
1986-10-06 20:36:30 +00:00
}
1986-03-20 14:52:03 +00:00
;
SetType(t_type **ptp;)
{ t_type *tp;
} :
SET OF SimpleType(&tp)
{ *ptp = set_type(tp); }
1986-03-20 14:52:03 +00:00
;
1986-03-29 01:04:49 +00:00
/* In a pointer type definition, the type pointed at does not
have to be declared yet, so be careful about identifying
type-identifiers.
1986-03-29 01:04:49 +00:00
*/
PointerType(register t_type **ptp;)
{ register t_type *tp;
} :
{ tp = construct_type(T_POINTER, NULLTYPE); }
1986-03-27 17:37:41 +00:00
POINTER TO
[ %if (type_or_forward(tp))
type(&(tp->tp_next))
1986-03-27 17:37:41 +00:00
|
IDENT
1986-03-27 17:37:41 +00:00
]
{ *ptp = tp; }
1986-03-20 14:52:03 +00:00
;
qualtype(t_type **ptp;)
1986-07-08 14:59:02 +00:00
{
t_node *nd;
1986-07-08 14:59:02 +00:00
} :
qualident(&nd)
{ *ptp = qualified_type(nd); }
;
1986-07-08 14:59:02 +00:00
ProcedureType(t_type **ptp;)
{
t_param *pr = 0;
arith parmaddr = 0;
t_type *tp = 0;
} :
1986-10-06 20:36:30 +00:00
PROCEDURE
[
FormalTypeList(&pr, &parmaddr, &tp)
1987-07-13 10:30:37 +00:00
|
]
{ *ptp = proc_type(tp, pr, parmaddr); }
1986-03-20 14:52:03 +00:00
;
FormalTypeList(t_param **ppr; arith *pparmaddr; t_type **ptp;) :
1986-10-06 20:36:30 +00:00
'('
1986-03-29 01:04:49 +00:00
[
VarFormalType(ppr, pparmaddr)
1986-03-29 01:04:49 +00:00
[
',' VarFormalType(ppr, pparmaddr)
1986-03-29 01:04:49 +00:00
]*
1988-02-10 14:06:34 +00:00
|
]
1986-03-29 01:04:49 +00:00
')'
1986-07-08 14:59:02 +00:00
[ ':' qualtype(ptp)
|
1987-08-03 09:09:07 +00:00
]
1986-03-20 14:52:03 +00:00
;
VarFormalType(t_param **ppr; arith *pparmaddr;)
1987-05-18 15:57:33 +00:00
{
t_type *tp;
1987-05-18 15:57:33 +00:00
int isvar;
} :
var(&isvar)
FormalType(&tp)
{ EnterParamList(ppr,NULLNODE,tp,isvar,pparmaddr); }
1987-05-18 15:57:33 +00:00
;
var(int *VARp;) :
[
VAR { *VARp = D_VARPAR; }
|
/* empty */ { *VARp = D_VALPAR; }
]
1986-07-08 14:59:02 +00:00
;
1986-03-26 15:11:02 +00:00
ConstantDeclaration
{
t_idf *id;
t_node *nd;
register t_def *df;
1986-03-26 15:11:02 +00:00
}:
1986-07-08 14:59:02 +00:00
IDENT { id = dot.TOK_IDF; }
'=' ConstExpression(&nd)
{ df = define(id,CurrentScope,D_CONST);
df->con_const = nd->nd_token;
df->df_type = nd->nd_type;
FreeNode(nd);
1990-07-30 15:56:25 +00:00
if (options['g']) stb_string(df, D_CONST);
}
1986-03-20 14:52:03 +00:00
;
VariableDeclaration
{
t_node *VarList;
register t_node *nd;
t_type *tp;
1986-03-20 14:52:03 +00:00
} :
1986-06-06 02:22:09 +00:00
IdentAddr(&VarList)
{ nd = VarList; }
1986-08-26 14:33:24 +00:00
[ %persistent
1986-06-06 02:22:09 +00:00
',' IdentAddr(&(nd->nd_right))
{ nd = nd->nd_right; }
]*
1986-03-27 17:37:41 +00:00
':' type(&tp)
1986-06-10 13:18:52 +00:00
{ EnterVarList(VarList, tp, proclevel > 0); }
1986-03-20 14:52:03 +00:00
;
1986-04-15 17:51:53 +00:00
IdentAddr(t_node **pnd;)
{
register t_node *nd;
} :
IDENT { nd = dot2leaf(Name); }
[ '['
ConstExpression(&(nd->nd_left))
']'
1988-02-10 14:06:34 +00:00
|
]
{ *pnd = nd; }
1986-04-15 17:51:53 +00:00
;