newer version
This commit is contained in:
parent
6382054ae5
commit
db795bc07a
|
@ -182,6 +182,10 @@ again:
|
|||
if (nch == '=') {
|
||||
return tk->tk_symb = LESSEQUAL;
|
||||
}
|
||||
if (nch == '>') {
|
||||
lexwarning("'<>' is old-fashioned; use '#'");
|
||||
return tk->tk_symb = '#';
|
||||
}
|
||||
PushBack(nch);
|
||||
return tk->tk_symb = ch;
|
||||
|
||||
|
|
|
@ -54,7 +54,6 @@ tokenfile.g: tokenname.c make.tokfile
|
|||
symbol2str.c: tokenname.c make.tokcase
|
||||
make.tokcase <tokenname.c >symbol2str.c
|
||||
|
||||
misc.h: misc.H make.allocd
|
||||
def.h: def.H make.allocd
|
||||
type.h: type.H make.allocd
|
||||
node.h: node.H make.allocd
|
||||
|
@ -90,13 +89,13 @@ symbol2str.o: Lpars.h
|
|||
tokenname.o: Lpars.h idf.h tokenname.h
|
||||
idf.o: idf.h
|
||||
input.o: f_info.h input.h inputtype.h
|
||||
type.o: LLlex.h const.h debug.h def.h idf.h maxset.h node.h target_sizes.h type.h
|
||||
type.o: LLlex.h const.h debug.h def.h idf.h maxset.h node.h scope.h target_sizes.h type.h
|
||||
def.o: LLlex.h Lpars.h debug.h def.h idf.h main.h node.h scope.h type.h
|
||||
scope.o: LLlex.h debug.h def.h idf.h node.h scope.h type.h
|
||||
misc.o: LLlex.h f_info.h idf.h misc.h node.h
|
||||
enter.o: LLlex.h debug.h def.h idf.h main.h node.h scope.h type.h
|
||||
defmodule.o: LLlex.h debug.h def.h f_info.h idf.h input.h inputtype.h main.h scope.h
|
||||
typequiv.o: def.h type.h
|
||||
typequiv.o: LLlex.h def.h node.h type.h
|
||||
node.o: LLlex.h debug.h def.h node.h type.h
|
||||
cstoper.o: LLlex.h Lpars.h debug.h idf.h node.h standards.h target_sizes.h type.h
|
||||
chk_expr.o: LLlex.h Lpars.h const.h debug.h def.h idf.h node.h scope.h standards.h type.h
|
||||
|
@ -104,7 +103,7 @@ options.o: idfsize.h main.h ndir.h type.h
|
|||
walk.o: LLlex.h Lpars.h debug.h def.h desig.h f_info.h idf.h main.h node.h scope.h type.h
|
||||
casestat.o: LLlex.h Lpars.h debug.h density.h desig.h node.h type.h
|
||||
desig.o: LLlex.h debug.h def.h desig.h node.h scope.h type.h
|
||||
code.o: LLlex.h Lpars.h debug.h def.h desig.h node.h scope.h type.h
|
||||
code.o: LLlex.h Lpars.h debug.h def.h desig.h node.h scope.h standards.h type.h
|
||||
tmpvar.o: debug.h def.h scope.h type.h
|
||||
tokenfile.o: Lpars.h
|
||||
program.o: LLlex.h Lpars.h debug.h def.h idf.h main.h node.h scope.h type.h
|
||||
|
|
|
@ -254,47 +254,53 @@ rem_set(set)
|
|||
|
||||
struct node *
|
||||
getarg(argp, bases, designator)
|
||||
struct node *argp;
|
||||
struct node **argp;
|
||||
{
|
||||
struct type *tp;
|
||||
register struct node *arg = *argp;
|
||||
|
||||
if (!argp->nd_right) {
|
||||
node_error(argp, "too few arguments supplied");
|
||||
if (!arg->nd_right) {
|
||||
node_error(arg, "too few arguments supplied");
|
||||
return 0;
|
||||
}
|
||||
argp = argp->nd_right;
|
||||
if ((!designator && !chk_expr(argp->nd_left)) ||
|
||||
(designator && !chk_designator(argp->nd_left, DESIGNATOR, D_REFERRED))) {
|
||||
arg = arg->nd_right;
|
||||
if ((!designator && !chk_expr(arg->nd_left)) ||
|
||||
(designator && !chk_designator(arg->nd_left, DESIGNATOR, D_REFERRED))) {
|
||||
return 0;
|
||||
}
|
||||
tp = argp->nd_left->nd_type;
|
||||
tp = arg->nd_left->nd_type;
|
||||
if (tp->tp_fund == T_SUBRANGE) tp = tp->next;
|
||||
if (bases && !(tp->tp_fund & bases)) {
|
||||
node_error(argp, "unexpected type");
|
||||
node_error(arg, "unexpected type");
|
||||
return 0;
|
||||
}
|
||||
return argp;
|
||||
|
||||
*argp = arg;
|
||||
return arg->nd_left;
|
||||
}
|
||||
|
||||
struct node *
|
||||
getname(argp, kinds)
|
||||
struct node *argp;
|
||||
struct node **argp;
|
||||
{
|
||||
if (!argp->nd_right) {
|
||||
node_error(argp, "too few arguments supplied");
|
||||
register struct node *arg = *argp;
|
||||
|
||||
if (!arg->nd_right) {
|
||||
node_error(arg, "too few arguments supplied");
|
||||
return 0;
|
||||
}
|
||||
argp = argp->nd_right;
|
||||
if (! chk_designator(argp->nd_left, 0, D_REFERRED)) return 0;
|
||||
arg = arg->nd_right;
|
||||
if (! chk_designator(arg->nd_left, 0, D_REFERRED)) return 0;
|
||||
|
||||
assert(argp->nd_left->nd_class == Def);
|
||||
assert(arg->nd_left->nd_class == Def);
|
||||
|
||||
if (!(argp->nd_left->nd_def->df_kind & kinds)) {
|
||||
node_error(argp, "unexpected type");
|
||||
if (!(arg->nd_left->nd_def->df_kind & kinds)) {
|
||||
node_error(arg, "unexpected type");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return argp;
|
||||
*argp = arg;
|
||||
return arg->nd_left;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -314,44 +320,20 @@ chk_call(expp)
|
|||
left = expp->nd_left;
|
||||
if (! chk_designator(left, 0, D_USED)) return 0;
|
||||
|
||||
if (left->nd_class == Def && is_type(left->nd_def)) {
|
||||
if (IsCast(left)) {
|
||||
/* It was a type cast. This is of course not portable.
|
||||
*/
|
||||
arg = expp->nd_right;
|
||||
if ((! arg) || arg->nd_right) {
|
||||
node_error(expp, "only one parameter expected in type cast");
|
||||
return 0;
|
||||
}
|
||||
arg = arg->nd_left;
|
||||
if (! chk_expr(arg)) return 0;
|
||||
if (arg->nd_type->tp_size != left->nd_type->tp_size) {
|
||||
node_error(expp, "unequal sizes in type cast");
|
||||
}
|
||||
if (arg->nd_class == Value) {
|
||||
struct type *tp = left->nd_type;
|
||||
|
||||
FreeNode(expp->nd_left);
|
||||
expp->nd_right->nd_left = 0;
|
||||
FreeNode(expp->nd_right);
|
||||
expp->nd_left = expp->nd_right = 0;
|
||||
*expp = *arg;
|
||||
expp->nd_type = tp;
|
||||
}
|
||||
else expp->nd_type = left->nd_type;
|
||||
|
||||
return 1;
|
||||
return chk_cast(expp, left);
|
||||
}
|
||||
|
||||
if ((left->nd_class == Def && left->nd_def->df_kind == D_PROCEDURE) ||
|
||||
left->nd_type->tp_fund == T_PROCEDURE) {
|
||||
if (IsProcCall(left)) {
|
||||
/* A procedure call. it may also be a call to a
|
||||
standard procedure
|
||||
*/
|
||||
arg = expp;
|
||||
if (left->nd_type == std_type) {
|
||||
/* A standard procedure
|
||||
*/
|
||||
return chk_std(expp, left, arg);
|
||||
return chk_std(expp, left);
|
||||
}
|
||||
/* Here, we have found a real procedure call. The left hand
|
||||
side may also represent a procedure variable.
|
||||
|
@ -363,12 +345,12 @@ node_error(expp, "unequal sizes in type cast");
|
|||
}
|
||||
|
||||
chk_proccall(expp)
|
||||
struct node *expp;
|
||||
register struct node *expp;
|
||||
{
|
||||
/* Check a procedure call
|
||||
*/
|
||||
register struct node *left;
|
||||
register struct node *arg;
|
||||
struct node *arg;
|
||||
register struct paramlist *param;
|
||||
|
||||
left = 0;
|
||||
|
@ -383,20 +365,21 @@ chk_proccall(expp)
|
|||
|
||||
left = expp->nd_left;
|
||||
arg = expp;
|
||||
arg->nd_type = left->nd_type->next;
|
||||
expp->nd_type = left->nd_type->next;
|
||||
param = left->nd_type->prc_params;
|
||||
|
||||
while (param) {
|
||||
if (!(arg = getarg(arg, 0, param->par_var))) return 0;
|
||||
if (!(left = getarg(&arg, 0, IsVarParam(param)))) return 0;
|
||||
|
||||
if (! TstParCompat(param->par_type,
|
||||
arg->nd_left->nd_type,
|
||||
param->par_var)) {
|
||||
node_error(arg->nd_left, "type incompatibility in parameter");
|
||||
if (! TstParCompat(TypeOfParam(param),
|
||||
left->nd_type,
|
||||
IsVarParam(param),
|
||||
left)) {
|
||||
node_error(left, "type incompatibility in parameter");
|
||||
return 0;
|
||||
}
|
||||
if (param->par_var && arg->nd_left->nd_class == Def) {
|
||||
arg->nd_left->nd_def->df_flags |= D_NOREG;
|
||||
if (IsVarParam(param) && left->nd_class == Def) {
|
||||
left->nd_def->df_flags |= D_NOREG;
|
||||
}
|
||||
|
||||
param = param->next;
|
||||
|
@ -475,7 +458,6 @@ chk_designator(expp, flag, dflags)
|
|||
|
||||
if (expp->nd_class == Link) {
|
||||
assert(expp->nd_symb == '.');
|
||||
assert(expp->nd_right->nd_class == Name);
|
||||
|
||||
if (! chk_designator(expp->nd_left,
|
||||
flag|HASSELECTORS,
|
||||
|
@ -485,19 +467,17 @@ chk_designator(expp, flag, dflags)
|
|||
|
||||
assert(tp->tp_fund == T_RECORD);
|
||||
|
||||
df = lookup(expp->nd_right->nd_IDF, tp->rec_scope);
|
||||
df = lookup(expp->nd_IDF, tp->rec_scope);
|
||||
|
||||
if (!df) {
|
||||
id_not_declared(expp->nd_right);
|
||||
id_not_declared(expp);
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
expp->nd_right->nd_class = Def;
|
||||
expp->nd_right->nd_def = df;
|
||||
expp->nd_def = df;
|
||||
expp->nd_type = df->df_type;
|
||||
if (!(df->df_flags & (D_EXPORTED|D_QEXPORTED))) {
|
||||
node_error(expp->nd_right,
|
||||
"identifier \"%s\" not exported from qualifying module",
|
||||
node_error(expp, "identifier \"%s\" not exported from qualifying module",
|
||||
df->df_idf->id_text);
|
||||
return 0;
|
||||
}
|
||||
|
@ -508,11 +488,10 @@ df->df_idf->id_text);
|
|||
expp->nd_class = Def;
|
||||
expp->nd_def = df;
|
||||
FreeNode(expp->nd_left);
|
||||
FreeNode(expp->nd_right);
|
||||
expp->nd_left = expp->nd_right = 0;
|
||||
expp->nd_left = 0;
|
||||
}
|
||||
else {
|
||||
return FlagCheck(expp->nd_right, df, flag);
|
||||
return FlagCheck(expp, df, flag);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -869,10 +848,11 @@ chk_uoper(expp)
|
|||
}
|
||||
|
||||
struct node *
|
||||
getvariable(arg)
|
||||
register struct node *arg;
|
||||
getvariable(argp)
|
||||
struct node **argp;
|
||||
{
|
||||
struct def *df;
|
||||
register struct node *arg = *argp;
|
||||
register struct def *df;
|
||||
register struct node *left;
|
||||
|
||||
arg = arg->nd_right;
|
||||
|
@ -885,62 +865,65 @@ getvariable(arg)
|
|||
|
||||
if (! chk_designator(left, DESIGNATOR, D_REFERRED)) return 0;
|
||||
if (left->nd_class == Oper || left->nd_class == Uoper) {
|
||||
return arg;
|
||||
*argp = arg;
|
||||
return left;
|
||||
}
|
||||
|
||||
df = 0;
|
||||
if (left->nd_class == Link) df = left->nd_right->nd_def;
|
||||
else if (left->nd_class == Def) df = left->nd_def;
|
||||
if (left->nd_class == Link || left->nd_class == Def) {
|
||||
df = left->nd_def;
|
||||
}
|
||||
|
||||
if (!df || !(df->df_kind & (D_VARIABLE|D_FIELD))) {
|
||||
node_error(arg, "variable expected");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return arg;
|
||||
*argp = arg;
|
||||
return left;
|
||||
}
|
||||
|
||||
int
|
||||
chk_std(expp, left, arg)
|
||||
register struct node *expp, *left, *arg;
|
||||
chk_std(expp, left)
|
||||
register struct node *expp, *left;
|
||||
{
|
||||
/* Check a call of a standard procedure or function
|
||||
*/
|
||||
struct node *arg = expp;
|
||||
int std;
|
||||
|
||||
assert(left->nd_class == Def);
|
||||
DO_DEBUG(3, debug("standard name \"%s\", %d",
|
||||
left->nd_def->df_idf->id_text, left->nd_def->df_value.df_stdname));
|
||||
std = left->nd_def->df_value.df_stdname;
|
||||
|
||||
switch(left->nd_def->df_value.df_stdname) {
|
||||
DO_DEBUG(3,debug("standard name \"%s\", %d",left->nd_def->df_idf->id_text,std));
|
||||
|
||||
switch(std) {
|
||||
case S_ABS:
|
||||
if (!(arg = getarg(arg, T_NUMERIC, 0))) return 0;
|
||||
left = arg->nd_left;
|
||||
if (!(left = getarg(&arg, T_NUMERIC, 0))) return 0;
|
||||
expp->nd_type = left->nd_type;
|
||||
if (left->nd_class == Value) cstcall(expp, S_ABS);
|
||||
break;
|
||||
|
||||
case S_CAP:
|
||||
expp->nd_type = char_type;
|
||||
if (!(arg = getarg(arg, T_CHAR, 0))) return 0;
|
||||
left = arg->nd_left;
|
||||
if (!(left = getarg(&arg, T_CHAR, 0))) return 0;
|
||||
if (left->nd_class == Value) cstcall(expp, S_CAP);
|
||||
break;
|
||||
|
||||
case S_CHR:
|
||||
expp->nd_type = char_type;
|
||||
if (!(arg = getarg(arg, T_INTORCARD, 0))) return 0;
|
||||
left = arg->nd_left;
|
||||
if (!(left = getarg(&arg, T_INTORCARD, 0))) return 0;
|
||||
if (left->nd_class == Value) cstcall(expp, S_CHR);
|
||||
break;
|
||||
|
||||
case S_FLOAT:
|
||||
expp->nd_type = real_type;
|
||||
if (!(arg = getarg(arg, T_INTORCARD, 0))) return 0;
|
||||
if (!(left = getarg(&arg, T_INTORCARD, 0))) return 0;
|
||||
break;
|
||||
|
||||
case S_HIGH:
|
||||
if (!(arg = getarg(arg, T_ARRAY, 0))) return 0;
|
||||
expp->nd_type = arg->nd_left->nd_type->next;
|
||||
if (!(left = getarg(&arg, T_ARRAY, 0))) return 0;
|
||||
expp->nd_type = left->nd_type->next;
|
||||
if (!expp->nd_type) {
|
||||
/* A dynamic array has no explicit index type
|
||||
*/
|
||||
|
@ -951,68 +934,75 @@ left->nd_def->df_idf->id_text, left->nd_def->df_value.df_stdname));
|
|||
|
||||
case S_MAX:
|
||||
case S_MIN:
|
||||
if (!(arg = getarg(arg, T_DISCRETE, 0))) return 0;
|
||||
expp->nd_type = arg->nd_left->nd_type;
|
||||
cstcall(expp,left->nd_def->df_value.df_stdname);
|
||||
if (!(left = getarg(&arg, T_DISCRETE, 0))) return 0;
|
||||
expp->nd_type = left->nd_type;
|
||||
cstcall(expp,std);
|
||||
break;
|
||||
|
||||
case S_ODD:
|
||||
if (!(arg = getarg(arg, T_INTORCARD, 0))) return 0;
|
||||
if (!(left = getarg(&arg, T_INTORCARD, 0))) return 0;
|
||||
expp->nd_type = bool_type;
|
||||
if (arg->nd_left->nd_class == Value) cstcall(expp, S_ODD);
|
||||
if (left->nd_class == Value) cstcall(expp, S_ODD);
|
||||
break;
|
||||
|
||||
case S_ORD:
|
||||
if (!(arg = getarg(arg, T_DISCRETE, 0))) return 0;
|
||||
if (!(left = getarg(&arg, T_DISCRETE, 0))) return 0;
|
||||
if (left->nd_type->tp_size > word_size) {
|
||||
node_error(left, "illegal type in argument of ORD");
|
||||
return 0;
|
||||
}
|
||||
expp->nd_type = card_type;
|
||||
if (arg->nd_left->nd_class == Value) cstcall(expp, S_ORD);
|
||||
if (left->nd_class == Value) cstcall(expp, S_ORD);
|
||||
break;
|
||||
|
||||
case S_TSIZE: /* ??? */
|
||||
case S_SIZE:
|
||||
expp->nd_type = intorcard_type;
|
||||
arg = getname(arg, D_FIELD|D_VARIABLE|D_ISTYPE);
|
||||
if (!arg) return 0;
|
||||
if (! getname(&arg, D_FIELD|D_VARIABLE|D_ISTYPE)) return 0;
|
||||
cstcall(expp, S_SIZE);
|
||||
break;
|
||||
|
||||
case S_TRUNC:
|
||||
expp->nd_type = card_type;
|
||||
if (!(arg = getarg(arg, T_REAL, 0))) return 0;
|
||||
if (!(left = getarg(&arg, T_REAL, 0))) return 0;
|
||||
break;
|
||||
|
||||
case S_VAL:
|
||||
{
|
||||
struct type *tp;
|
||||
|
||||
if (!(arg = getname(arg, D_ISTYPE))) return 0;
|
||||
tp = arg->nd_left->nd_def->df_type;
|
||||
if (!(left = getname(&arg, D_ISTYPE))) return 0;
|
||||
tp = left->nd_def->df_type;
|
||||
if (tp->tp_fund == T_SUBRANGE) tp = tp->next;
|
||||
if (!(tp->tp_fund & T_DISCRETE)) {
|
||||
node_error(arg, "unexpected type");
|
||||
return 0;
|
||||
}
|
||||
expp->nd_type = arg->nd_left->nd_def->df_type;
|
||||
expp->nd_type = left->nd_def->df_type;
|
||||
expp->nd_right = arg->nd_right;
|
||||
arg->nd_right = 0;
|
||||
FreeNode(arg);
|
||||
arg = getarg(expp, T_INTORCARD, 0);
|
||||
if (!arg) return 0;
|
||||
if (arg->nd_left->nd_class == Value) cstcall(expp, S_VAL);
|
||||
arg = expp;
|
||||
if (!(left = getarg(&arg, T_INTORCARD, 0))) return 0;
|
||||
if (left->nd_class == Value) cstcall(expp, S_VAL);
|
||||
break;
|
||||
}
|
||||
|
||||
case S_ADR:
|
||||
expp->nd_type = address_type;
|
||||
if (!(arg = getarg(arg, 0, 1))) return 0;
|
||||
if (!(left = getarg(&arg, 0, 1))) return 0;
|
||||
break;
|
||||
|
||||
case S_DEC:
|
||||
case S_INC:
|
||||
expp->nd_type = 0;
|
||||
if (!(arg = getvariable(arg))) return 0;
|
||||
if (! (left = getvariable(&arg))) return 0;
|
||||
if (! (left->nd_type->tp_fund & T_DISCRETE)) {
|
||||
node_error(left, "illegal type in argument of INC or DEC");
|
||||
return 0;
|
||||
}
|
||||
if (arg->nd_right) {
|
||||
if (!(arg = getarg(arg, T_INTORCARD, 0))) return 0;
|
||||
if (! getarg(&arg, T_INTORCARD, 0)) return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1026,14 +1016,14 @@ left->nd_def->df_idf->id_text, left->nd_def->df_value.df_stdname));
|
|||
struct type *tp;
|
||||
|
||||
expp->nd_type = 0;
|
||||
if (!(arg = getvariable(arg))) return 0;
|
||||
tp = arg->nd_left->nd_type;
|
||||
if (!(left = getvariable(&arg))) return 0;
|
||||
tp = left->nd_type;
|
||||
if (tp->tp_fund != T_SET) {
|
||||
node_error(arg, "EXCL and INCL expect a SET parameter");
|
||||
return 0;
|
||||
}
|
||||
if (!(arg = getarg(arg, T_DISCRETE, 0))) return 0;
|
||||
if (!TstAssCompat(tp->next, arg->nd_left->nd_type)) {
|
||||
if (!(left = getarg(&arg, T_DISCRETE, 0))) return 0;
|
||||
if (!TstAssCompat(tp->next, left->nd_type)) {
|
||||
/* What type of compatibility do we want here?
|
||||
apparently assignment compatibility! ??? ???
|
||||
*/
|
||||
|
@ -1044,7 +1034,7 @@ node_error(arg, "EXCL and INCL expect a SET parameter");
|
|||
}
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
crash("(chk_std)");
|
||||
}
|
||||
|
||||
if (arg->nd_right) {
|
||||
|
@ -1054,3 +1044,44 @@ node_error(arg, "EXCL and INCL expect a SET parameter");
|
|||
|
||||
return 1;
|
||||
}
|
||||
|
||||
chk_cast(expp, left)
|
||||
register struct node *expp, *left;
|
||||
{
|
||||
/* Check a cast and perform it if the argument is constant.
|
||||
If the sizes don't match, only complain if at least one of them
|
||||
has a size larger than the word size.
|
||||
If both sizes are equal to or smaller than the word size, there
|
||||
is no problem as such values take a word on the EM stack
|
||||
anyway.
|
||||
*/
|
||||
register struct node *arg = expp->nd_right;
|
||||
|
||||
if ((! arg) || arg->nd_right) {
|
||||
node_error(expp, "only one parameter expected in type cast");
|
||||
return 0;
|
||||
}
|
||||
|
||||
arg = arg->nd_left;
|
||||
if (! chk_expr(arg)) return 0;
|
||||
|
||||
if (arg->nd_type->tp_size != left->nd_type->tp_size &&
|
||||
(arg->nd_type->tp_size > word_size ||
|
||||
left->nd_type->tp_size > word_size)) {
|
||||
node_error(expp, "unequal sizes in type cast");
|
||||
}
|
||||
|
||||
if (arg->nd_class == Value) {
|
||||
struct type *tp = left->nd_type;
|
||||
|
||||
FreeNode(left);
|
||||
expp->nd_right->nd_left = 0;
|
||||
FreeNode(expp->nd_right);
|
||||
expp->nd_left = expp->nd_right = 0;
|
||||
*expp = *arg;
|
||||
expp->nd_type = tp;
|
||||
}
|
||||
else expp->nd_type = left->nd_type;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ static char *RcsId = "$Header$";
|
|||
#include "LLlex.h"
|
||||
#include "node.h"
|
||||
#include "Lpars.h"
|
||||
#include "standards.h"
|
||||
|
||||
extern label data_label();
|
||||
extern label text_label();
|
||||
|
@ -81,6 +82,11 @@ CodeExpr(nd, ds, true_label, false_label)
|
|||
|
||||
switch(nd->nd_class) {
|
||||
case Def:
|
||||
if (nd->nd_def->df_kind == D_PROCEDURE) {
|
||||
C_lpi(nd->nd_def->prc_vis->sc_scope->sc_name);
|
||||
ds->dsg_kind = DSG_LOADED;
|
||||
break;
|
||||
}
|
||||
CodeDesig(nd, ds);
|
||||
break;
|
||||
|
||||
|
@ -102,8 +108,7 @@ CodeExpr(nd, ds, true_label, false_label)
|
|||
CodeDesig(nd, ds);
|
||||
break;
|
||||
}
|
||||
CodeExpr(nd->nd_right, ds, NO_LABEL, NO_LABEL);
|
||||
CodeValue(ds, nd->nd_right->nd_type->tp_size);
|
||||
CodePExpr(nd->nd_right);
|
||||
CodeUoper(nd);
|
||||
ds->dsg_kind = DSG_LOADED;
|
||||
break;
|
||||
|
@ -181,6 +186,7 @@ CodeCoercion(t1, t2)
|
|||
if ((fund2 = t2->tp_fund) == T_WORD) fund2 = T_INTEGER;
|
||||
switch(fund1) {
|
||||
case T_INTEGER:
|
||||
case T_INTORCARD:
|
||||
switch(fund2) {
|
||||
case T_INTEGER:
|
||||
if (t2->tp_size != t1->tp_size) {
|
||||
|
@ -274,7 +280,6 @@ CodeCall(nd)
|
|||
register struct paramlist *param;
|
||||
struct type *tp;
|
||||
arith pushed = 0;
|
||||
struct desig Des;
|
||||
|
||||
if (left->nd_type == std_type) {
|
||||
CodeStd(nd);
|
||||
|
@ -282,32 +287,27 @@ CodeCall(nd)
|
|||
}
|
||||
tp = left->nd_type;
|
||||
|
||||
if (left->nd_class == Def && is_type(left->nd_def)) {
|
||||
if (IsCast(left)) {
|
||||
/* it was just a cast. Simply ignore it
|
||||
*/
|
||||
Des = InitDesig;
|
||||
CodeExpr(nd->nd_right->nd_left, &Des, NO_LABEL, NO_LABEL);
|
||||
CodeValue(&Des, tp->tp_size);
|
||||
CodePExpr(nd->nd_right->nd_left);
|
||||
*nd = *(nd->nd_right->nd_left);
|
||||
nd->nd_type = left->nd_def->df_type;
|
||||
return;
|
||||
}
|
||||
|
||||
assert(tp->tp_fund == T_PROCEDURE);
|
||||
assert(IsProcCall(left));
|
||||
|
||||
for (param = left->nd_type->prc_params; param; param = param->next) {
|
||||
Des = InitDesig;
|
||||
arg = arg->nd_right;
|
||||
assert(arg != 0);
|
||||
if (param->par_var) {
|
||||
CodeDesig(arg->nd_left, &Des);
|
||||
CodeAddress(&Des);
|
||||
if (IsVarParam(param)) {
|
||||
CodeDAddress(arg->nd_left);
|
||||
pushed += pointer_size;
|
||||
}
|
||||
else {
|
||||
CodeExpr(arg->nd_left, &Des, NO_LABEL, NO_LABEL);
|
||||
CodeValue(&Des, arg->nd_left->nd_type->tp_size);
|
||||
CheckAssign(arg->nd_left->nd_type, param->par_type);
|
||||
CodePExpr(arg->nd_left);
|
||||
CheckAssign(arg->nd_left->nd_type, TypeOfParam(param));
|
||||
pushed += align(arg->nd_left->nd_type->tp_size, word_align);
|
||||
}
|
||||
/* ??? Conformant arrays */
|
||||
|
@ -324,9 +324,7 @@ CodeCall(nd)
|
|||
C_cal(left->nd_def->for_name);
|
||||
}
|
||||
else {
|
||||
Des = InitDesig;
|
||||
CodeDesig(left, &Des);
|
||||
CodeAddress(&Des);
|
||||
CodePExpr(left);
|
||||
C_cai();
|
||||
}
|
||||
C_asp(pushed);
|
||||
|
@ -338,7 +336,141 @@ CodeCall(nd)
|
|||
CodeStd(nd)
|
||||
struct node *nd;
|
||||
{
|
||||
/* ??? */
|
||||
register struct node *arg = nd->nd_right;
|
||||
register struct node *left = 0;
|
||||
register struct type *tp = 0;
|
||||
int std;
|
||||
|
||||
if (arg) {
|
||||
left = arg->nd_left;
|
||||
tp = left->nd_type;
|
||||
if (tp->tp_fund == T_SUBRANGE) tp = tp->next;
|
||||
arg = arg->nd_right;
|
||||
}
|
||||
Desig = InitDesig;
|
||||
|
||||
switch(std = nd->nd_left->nd_def->df_value.df_stdname) {
|
||||
case S_ABS:
|
||||
CodePExpr(left);
|
||||
if (tp->tp_fund == T_INTEGER) {
|
||||
if (tp->tp_size == int_size) {
|
||||
C_cal("_absi");
|
||||
}
|
||||
else C_cal("_absl");
|
||||
}
|
||||
else if (tp->tp_fund == T_REAL) {
|
||||
if (tp->tp_size == float_size) {
|
||||
C_cal("_absf");
|
||||
}
|
||||
else C_cal("_absd");
|
||||
}
|
||||
C_lfr(tp->tp_size);
|
||||
break;
|
||||
|
||||
case S_CAP:
|
||||
CodePExpr(left);
|
||||
C_loc((arith) 0137);
|
||||
C_and(word_size);
|
||||
break;
|
||||
|
||||
case S_CHR:
|
||||
CodePExpr(left);
|
||||
CheckAssign(char_type, tp);
|
||||
break;
|
||||
|
||||
case S_FLOAT:
|
||||
CodePExpr(left);
|
||||
CodeCoercion(tp, real_type);
|
||||
break;
|
||||
|
||||
case S_HIGH:
|
||||
assert(IsConformantArray(tp));
|
||||
/* ??? */
|
||||
break;
|
||||
|
||||
case S_ODD:
|
||||
if (tp->tp_size == word_size) {
|
||||
C_loc((arith) 1);
|
||||
C_and(word_size);
|
||||
}
|
||||
else {
|
||||
assert(tp->tp_size == dword_size);
|
||||
C_ldc((arith) 1);
|
||||
C_and(dword_size);
|
||||
C_ior(word_size);
|
||||
}
|
||||
break;
|
||||
|
||||
case S_ORD:
|
||||
CodePExpr(left);
|
||||
break;
|
||||
|
||||
case S_TRUNC:
|
||||
CodePExpr(left);
|
||||
CodeCoercion(tp, card_type);
|
||||
break;
|
||||
|
||||
case S_VAL:
|
||||
CodePExpr(left);
|
||||
CheckAssign(nd->nd_type, tp);
|
||||
break;
|
||||
|
||||
case S_ADR:
|
||||
CodeDAddress(left);
|
||||
break;
|
||||
|
||||
case S_DEC:
|
||||
case S_INC:
|
||||
CodePExpr(left);
|
||||
if (arg) CodePExpr(arg->nd_left);
|
||||
else C_loc((arith) 1);
|
||||
if (tp->tp_size <= word_size) {
|
||||
if (std == S_DEC) {
|
||||
if (tp->tp_fund == T_INTEGER) C_sbi(word_size);
|
||||
else C_sbu(word_size);
|
||||
}
|
||||
else {
|
||||
if (tp->tp_fund == T_INTEGER) C_adi(word_size);
|
||||
else C_adu(word_size);
|
||||
}
|
||||
CheckAssign(tp, int_type);
|
||||
}
|
||||
else {
|
||||
CodeCoercion(int_type, tp);
|
||||
if (std == S_DEC) {
|
||||
if (tp->tp_fund==T_INTEGER) C_sbi(tp->tp_size);
|
||||
else C_sbu(tp->tp_size);
|
||||
}
|
||||
else {
|
||||
if (tp->tp_fund==T_INTEGER) C_adi(tp->tp_size);
|
||||
else C_adu(tp->tp_size);
|
||||
}
|
||||
}
|
||||
CodeDStore(left);
|
||||
break;
|
||||
|
||||
case S_HALT:
|
||||
C_cal("_halt");
|
||||
break;
|
||||
|
||||
case S_INCL:
|
||||
case S_EXCL:
|
||||
CodePExpr(left);
|
||||
CodePExpr(arg->nd_left);
|
||||
C_set(tp->tp_size);
|
||||
if (std == S_INCL) {
|
||||
C_ior(tp->tp_size);
|
||||
}
|
||||
else {
|
||||
C_com(tp->tp_size);
|
||||
C_and(tp->tp_size);
|
||||
}
|
||||
CodeDStore(left);
|
||||
break;
|
||||
|
||||
default:
|
||||
crash("(CodeStd)");
|
||||
}
|
||||
}
|
||||
|
||||
CodeAssign(nd, dss, dst)
|
||||
|
@ -353,6 +485,7 @@ CodeAssign(nd, dss, dst)
|
|||
CodeStore(dst, nd->nd_left->nd_type->tp_size);
|
||||
}
|
||||
else {
|
||||
CodeAddress(dss);
|
||||
CodeAddress(dst);
|
||||
C_blm(nd->nd_left->nd_type->tp_size);
|
||||
}
|
||||
|
@ -395,12 +528,8 @@ CheckAssign(tpl, tpr)
|
|||
Operands(leftop, rightop)
|
||||
register struct node *leftop, *rightop;
|
||||
{
|
||||
struct desig Des;
|
||||
|
||||
Des = InitDesig;
|
||||
CodeExpr(leftop, &Des, NO_LABEL, NO_LABEL);
|
||||
CodeValue(&Des, leftop->nd_type->tp_size);
|
||||
Des = InitDesig;
|
||||
CodePExpr(leftop);
|
||||
|
||||
if (rightop->nd_type->tp_fund == T_POINTER &&
|
||||
leftop->nd_type->tp_size != pointer_size) {
|
||||
|
@ -408,8 +537,7 @@ Operands(leftop, rightop)
|
|||
leftop->nd_type = rightop->nd_type;
|
||||
}
|
||||
|
||||
CodeExpr(rightop, &Des, NO_LABEL, NO_LABEL);
|
||||
CodeValue(&Des, rightop->nd_type->tp_size);
|
||||
CodePExpr(rightop);
|
||||
}
|
||||
|
||||
CodeOper(expr, true_label, false_label)
|
||||
|
@ -787,11 +915,48 @@ CodeEl(nd, tp)
|
|||
C_asp(2 * word_size + pointer_size);
|
||||
}
|
||||
else {
|
||||
struct desig Des;
|
||||
|
||||
Des = InitDesig;
|
||||
CodeExpr(nd, &Des, NO_LABEL, NO_LABEL);
|
||||
CodeValue(&Des, word_size);
|
||||
CodePExpr(nd);
|
||||
C_set(tp->tp_size);
|
||||
}
|
||||
}
|
||||
|
||||
CodePExpr(nd)
|
||||
struct node *nd;
|
||||
{
|
||||
/* Generate code to push the value of the expression "nd"
|
||||
on the stack.
|
||||
*/
|
||||
struct desig designator;
|
||||
|
||||
designator = InitDesig;
|
||||
CodeExpr(nd, &designator, NO_LABEL, NO_LABEL);
|
||||
CodeValue(&designator, nd->nd_type->tp_size);
|
||||
}
|
||||
|
||||
CodeDAddress(nd)
|
||||
struct node *nd;
|
||||
{
|
||||
/* Generate code to push the address of the designator "nd"
|
||||
on the stack.
|
||||
*/
|
||||
|
||||
struct desig designator;
|
||||
|
||||
designator = InitDesig;
|
||||
CodeDesig(nd, &designator);
|
||||
CodeAddress(&designator);
|
||||
}
|
||||
|
||||
CodeDStore(nd)
|
||||
register struct node *nd;
|
||||
{
|
||||
/* Generate code to store the expression on the stack into the
|
||||
designator "nd".
|
||||
*/
|
||||
|
||||
struct desig designator;
|
||||
|
||||
designator = InitDesig;
|
||||
CodeDesig(nd, &designator);
|
||||
CodeStore(&designator, nd->nd_type->tp_size);
|
||||
}
|
||||
|
|
|
@ -23,25 +23,23 @@ static char *RcsId = "$Header$";
|
|||
|
||||
int proclevel = 0; /* nesting level of procedures */
|
||||
extern char *sprint();
|
||||
extern struct def *currentdef;
|
||||
}
|
||||
|
||||
ProcedureDeclaration
|
||||
{
|
||||
struct def *df;
|
||||
struct def *savecurr = currentdef;
|
||||
} :
|
||||
{ proclevel++; }
|
||||
ProcedureHeading(&df, D_PROCEDURE)
|
||||
{
|
||||
currentdef = df;
|
||||
CurrentScope->sc_definedby = df;
|
||||
df->prc_vis = CurrVis;
|
||||
}
|
||||
';' block(&(df->prc_body)) IDENT
|
||||
{
|
||||
match_id(dot.TOK_IDF, df->df_idf);
|
||||
df->prc_vis = CurrVis;
|
||||
close_scope(SC_CHKFORW|SC_REVERSE);
|
||||
proclevel--;
|
||||
currentdef = savecurr;
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -54,17 +52,16 @@ ProcedureHeading(struct def **pdf; int type;)
|
|||
} :
|
||||
PROCEDURE IDENT
|
||||
{
|
||||
if (type == D_PROCEDURE) proclevel++;
|
||||
df = DeclProc(type);
|
||||
tp = construct_type(T_PROCEDURE, tp);
|
||||
if (proclevel > 1) {
|
||||
if (proclevel) {
|
||||
/* Room for static link
|
||||
*/
|
||||
tp->prc_nbpar = pointer_size;
|
||||
}
|
||||
else tp->prc_nbpar = 0;
|
||||
}
|
||||
FormalParameters(type == D_PROCEDURE, ¶ms, &(tp->next), &(tp->prc_nbpar))?
|
||||
FormalParameters(¶ms, &(tp->next), &(tp->prc_nbpar))?
|
||||
{
|
||||
tp->prc_params = params;
|
||||
if (df->df_type) {
|
||||
|
@ -79,6 +76,8 @@ error("inconsistent procedure declaration for \"%s\"", df->df_idf->id_text);
|
|||
df->df_type = tp;
|
||||
*pdf = df;
|
||||
|
||||
if (type == D_PROCHEAD) close_scope(0);
|
||||
|
||||
DO_DEBUG(1, type == D_PROCEDURE &&
|
||||
(print("proc %s:", df->df_idf->id_text),
|
||||
DumpType(tp), print("\n")));
|
||||
|
@ -110,20 +109,17 @@ declaration:
|
|||
ModuleDeclaration ';'
|
||||
;
|
||||
|
||||
FormalParameters(int doparams;
|
||||
struct paramlist **pr;
|
||||
FormalParameters(struct paramlist **pr;
|
||||
struct type **tp;
|
||||
arith *parmaddr;)
|
||||
{
|
||||
struct def *df;
|
||||
register struct paramlist *pr1;
|
||||
} :
|
||||
'('
|
||||
[
|
||||
FPSection(doparams, pr, parmaddr)
|
||||
FPSection(pr, parmaddr)
|
||||
[
|
||||
{ for (pr1 = *pr; pr1->next; pr1 = pr1->next) ; }
|
||||
';' FPSection(doparams, &(pr1->next), parmaddr)
|
||||
';' FPSection(pr, parmaddr)
|
||||
]*
|
||||
]?
|
||||
')'
|
||||
|
@ -134,16 +130,9 @@ FormalParameters(int doparams;
|
|||
]?
|
||||
;
|
||||
|
||||
/* In the next nonterminal, "doparams" is a flag indicating whether
|
||||
the identifiers representing the parameters must be added to the
|
||||
symbol table. We must not do so when reading a Definition Module,
|
||||
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; arith *addr;)
|
||||
FPSection(struct paramlist **ppr; arith *parmaddr;)
|
||||
{
|
||||
struct node *FPList;
|
||||
struct paramlist *ParamList();
|
||||
struct type *tp;
|
||||
int VARp = 0;
|
||||
} :
|
||||
|
@ -152,11 +141,7 @@ FPSection(int doparams; struct paramlist **ppr; arith *addr;)
|
|||
]?
|
||||
IdentList(&FPList) ':' FormalType(&tp)
|
||||
{
|
||||
if (doparams) {
|
||||
EnterIdList(FPList, D_VARIABLE, VARp,
|
||||
tp, CurrentScope, addr);
|
||||
}
|
||||
*ppr = ParamList(FPList, tp, VARp);
|
||||
ParamList(ppr, FPList, tp, VARp, parmaddr);
|
||||
FreeNode(FPList);
|
||||
}
|
||||
;
|
||||
|
@ -530,27 +515,29 @@ FormalTypeList(struct paramlist **ppr; struct type **ptp;)
|
|||
} :
|
||||
'(' { *ppr = 0; }
|
||||
[
|
||||
[ VAR { VARp = 1; }
|
||||
| { VARp = 0; }
|
||||
[ VAR { VARp = D_VARPAR; }
|
||||
| { VARp = D_VALPAR; }
|
||||
]
|
||||
FormalType(&tp)
|
||||
{ *ppr = p = new_paramlist();
|
||||
p->par_type = tp;
|
||||
p->par_var = VARp;
|
||||
p->next = 0;
|
||||
p->par_def = df = new_def();
|
||||
df->df_type = tp;
|
||||
df->df_flags = VARp;
|
||||
}
|
||||
[
|
||||
','
|
||||
[ VAR {VARp = 1; }
|
||||
| {VARp = 0; }
|
||||
[ VAR {VARp = D_VARPAR; }
|
||||
| {VARp = D_VALPAR; }
|
||||
]
|
||||
FormalType(&tp)
|
||||
{ p->next = new_paramlist();
|
||||
p = p->next;
|
||||
p->par_type = tp;
|
||||
p->par_var = VARp;
|
||||
{ p = new_paramlist();
|
||||
p->next = *ppr; *ppr = p;
|
||||
p->par_def = df = new_def();
|
||||
df->df_type = tp;
|
||||
df->df_flags = VARp;
|
||||
}
|
||||
]*
|
||||
{ p->next = 0; }
|
||||
]?
|
||||
')'
|
||||
[ ':' qualident(D_TYPE, &df, "type", (struct node **) 0)
|
||||
|
|
|
@ -20,7 +20,10 @@ static char *RcsId = "$Header$";
|
|||
#include "node.h"
|
||||
#include "Lpars.h"
|
||||
|
||||
struct def *h_def; /* Pointer to free list of def structures */
|
||||
struct def *h_def; /* pointer to free list of def structures */
|
||||
#ifdef DEBUG
|
||||
int cnt_def; /* count number of allocated ones */
|
||||
#endif
|
||||
|
||||
struct def *ill_df;
|
||||
|
||||
|
@ -455,6 +458,7 @@ DeclProc(type)
|
|||
df->for_name = Malloc((unsigned) (strlen(buf)+1));
|
||||
strcpy(df->for_name, buf);
|
||||
C_exp(df->for_name);
|
||||
open_scope(OPENSCOPE);
|
||||
}
|
||||
else {
|
||||
df = lookup(dot.TOK_IDF, CurrentScope);
|
||||
|
|
|
@ -326,10 +326,9 @@ CodeDesig(nd, ds)
|
|||
|
||||
case Link:
|
||||
assert(nd->nd_symb == '.');
|
||||
assert(nd->nd_right->nd_class == Def);
|
||||
|
||||
CodeDesig(nd->nd_left, ds);
|
||||
CodeFieldDesig(nd->nd_right->nd_def, ds);
|
||||
CodeFieldDesig(nd->nd_def, ds);
|
||||
break;
|
||||
|
||||
case Oper:
|
||||
|
|
|
@ -73,15 +73,6 @@ EnterIdList(idlist, kind, flags, type, scope, addr)
|
|||
}
|
||||
|
||||
if (*addr >= 0) {
|
||||
if (scope->sc_level && kind != D_FIELD) {
|
||||
/* alignment of parameters is on
|
||||
word boundaries. We cannot do any
|
||||
better, because we don't know the
|
||||
alignment of the stack pointer when
|
||||
starting to push parameters
|
||||
*/
|
||||
xalign = word_align;
|
||||
}
|
||||
off = align(*addr, xalign);
|
||||
*addr = off + type->tp_size;
|
||||
}
|
||||
|
|
|
@ -72,7 +72,7 @@ node_error(nd,"identifier \"%s\" is not a %s", df->df_idf->id_text, str);
|
|||
|
||||
selector(struct node **pnd;):
|
||||
'.' { *pnd = MkNode(Link,*pnd,NULLNODE,&dot); }
|
||||
IDENT { (*pnd)->nd_right = MkNode(Name,NULLNODE,NULLNODE,&dot); }
|
||||
IDENT { (*pnd)->nd_IDF = dot.TOK_IDF; }
|
||||
;
|
||||
|
||||
ExpList(struct node **pnd;)
|
||||
|
|
|
@ -101,6 +101,9 @@ Compile(src, dst)
|
|||
}
|
||||
WalkModule(Defined);
|
||||
C_close();
|
||||
#ifdef DEBUG
|
||||
if (options['m']) MemUse();
|
||||
#endif
|
||||
if (err_occurred) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
@ -217,3 +220,19 @@ AtEoIT()
|
|||
*/
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
MemUse()
|
||||
{
|
||||
extern int cnt_def, cnt_node, cnt_paramlist, cnt_type,
|
||||
cnt_switch_hdr, cnt_case_entry,
|
||||
cnt_scope, cnt_scopelist, cnt_forwards, cnt_tmpvar;
|
||||
|
||||
print("\
|
||||
%6d def\n%6d node\n%6d paramlist\n%6d type\n%6d switch_hdr\n\
|
||||
%6d case_entry\n%6d scope\n%6d scopelist\n%6d forwards\n%6d tmpvar\n",
|
||||
cnt_def, cnt_node, cnt_paramlist, cnt_type,
|
||||
cnt_switch_hdr, cnt_case_entry,
|
||||
cnt_scope, cnt_scopelist, cnt_forwards, cnt_tmpvar);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -3,15 +3,23 @@ s:^.*[ ]ALLOCDEF[ ].*"\(.*\)".*$:\
|
|||
/* allocation definitions of struct \1 */\
|
||||
extern char *st_alloc();\
|
||||
extern struct \1 *h_\1;\
|
||||
#define new_\1() ((struct \1 *) \\\
|
||||
st_alloc((char **)\&h_\1, sizeof(struct \1)))\
|
||||
#ifdef DEBUG\
|
||||
extern int cnt_\1;\
|
||||
#define new_\1() ((struct \1 *) std_alloc((char **)\&h_\1, sizeof(struct \1), \&cnt_\1))\
|
||||
#else\
|
||||
#define new_\1() ((struct \1 *) st_alloc((char **)\&h_\1, sizeof(struct \1)))\
|
||||
#endif\
|
||||
#define free_\1(p) st_free(p, h_\1, sizeof(struct \1))\
|
||||
:' -e '
|
||||
s:^.*[ ]STATICALLOCDEF[ ].*"\(.*\)".*$:\
|
||||
/* allocation definitions of struct \1 */\
|
||||
extern char *st_alloc();\
|
||||
static struct \1 *h_\1;\
|
||||
#define new_\1() ((struct \1 *) \\\
|
||||
st_alloc((char **)\&h_\1, sizeof(struct \1)))\
|
||||
struct \1 *h_\1;\
|
||||
#ifdef DEBUG\
|
||||
int cnt_\1;\
|
||||
#define new_\1() ((struct \1 *) std_alloc((char **)\&h_\1, sizeof(struct \1), \&cnt_\1))\
|
||||
#else\
|
||||
#define new_\1() ((struct \1 *) st_alloc((char **)\&h_\1, sizeof(struct \1)))\
|
||||
#endif\
|
||||
#define free_\1(p) st_free(p, h_\1, sizeof(struct \1))\
|
||||
:'
|
||||
|
|
8
lang/m2/comp/misc.h
Normal file
8
lang/m2/comp/misc.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
/* M I S C E L L A N E O U S */
|
||||
|
||||
/* $Header$ */
|
||||
|
||||
#define is_anon_idf(x) ((x)->id_text[0] == '#')
|
||||
|
||||
extern struct idf
|
||||
*gen_anon_idf();
|
|
@ -41,3 +41,6 @@ extern struct node *MkNode();
|
|||
#define HASSELECTORS 2
|
||||
#define VARIABLE 4
|
||||
#define VALUE 8
|
||||
|
||||
#define IsCast(lnd) ((lnd)->nd_class == Def && is_type((lnd)->nd_def))
|
||||
#define IsProcCall(lnd) ((lnd)->nd_type->tp_fund == T_PROCEDURE)
|
||||
|
|
|
@ -17,6 +17,9 @@ static char *RcsId = "$Header$";
|
|||
#include "node.h"
|
||||
|
||||
struct node *h_node; /* header of free list */
|
||||
#ifdef DEBUG
|
||||
int cnt_node; /* count number of allocated ones */
|
||||
#endif
|
||||
|
||||
struct node *
|
||||
MkNode(class, left, right, token)
|
||||
|
|
|
@ -25,8 +25,8 @@ DoOption(text)
|
|||
options[text[-1]] = 1; /* flags, debug options etc. */
|
||||
break;
|
||||
|
||||
case 'L' :
|
||||
warning("-L: default no EM profiling; use -p for EM profiling");
|
||||
case 'L' : /* don't generate fil/lin */
|
||||
options['L'] = 1;
|
||||
break;
|
||||
|
||||
case 'M': /* maximum identifier length */
|
||||
|
@ -37,7 +37,7 @@ DoOption(text)
|
|||
fatal("maximum identifier length is %d", IDFSIZE);
|
||||
break;
|
||||
|
||||
case 'p' : /* generate profiling code (fil/lin) */
|
||||
case 'p' : /* generate profiling code procentry/procexit ???? */
|
||||
options['p'] = 1;
|
||||
break;
|
||||
|
||||
|
|
|
@ -24,7 +24,6 @@ static int DEFofIMPL = 0; /* Flag indicating that we are currently
|
|||
implementation module currently being
|
||||
compiled
|
||||
*/
|
||||
struct def *currentdef; /* current definition of module or procedure */
|
||||
}
|
||||
/*
|
||||
The grammar as given by Wirth is already almost LL(1); the
|
||||
|
@ -49,7 +48,6 @@ ModuleDeclaration
|
|||
{
|
||||
struct idf *id;
|
||||
register struct def *df;
|
||||
struct def *savecurr = currentdef;
|
||||
extern int proclevel;
|
||||
static int modulecount = 0;
|
||||
char buf[256];
|
||||
|
@ -61,7 +59,6 @@ ModuleDeclaration
|
|||
MODULE IDENT {
|
||||
id = dot.TOK_IDF;
|
||||
df = define(id, CurrentScope, D_MODULE);
|
||||
currentdef = df;
|
||||
|
||||
if (!df->mod_vis) {
|
||||
open_scope(CLOSEDSCOPE);
|
||||
|
@ -71,6 +68,7 @@ ModuleDeclaration
|
|||
CurrVis = df->mod_vis;
|
||||
CurrentScope->sc_level = proclevel;
|
||||
}
|
||||
CurrentScope->sc_definedby = df;
|
||||
|
||||
df->df_type = standard_type(T_RECORD, 0, (arith) 0);
|
||||
df->df_type->rec_scope = df->mod_vis->sc_scope;
|
||||
|
@ -93,7 +91,6 @@ ModuleDeclaration
|
|||
}
|
||||
close_scope(SC_CHKFORW|SC_CHKPROC|SC_REVERSE);
|
||||
match_id(id, dot.TOK_IDF);
|
||||
currentdef = savecurr;
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -244,7 +241,6 @@ ProgramModule
|
|||
if (state == IMPLEMENTATION) {
|
||||
DEFofIMPL = 1;
|
||||
df = GetDefinitionModule(id);
|
||||
currentdef = df;
|
||||
CurrVis = df->mod_vis;
|
||||
CurrentScope = CurrVis->sc_scope;
|
||||
DEFofIMPL = 0;
|
||||
|
@ -256,6 +252,7 @@ ProgramModule
|
|||
df->mod_vis = CurrVis;
|
||||
CurrentScope->sc_name = id->id_text;
|
||||
}
|
||||
CurrentScope->sc_definedby = df;
|
||||
}
|
||||
priority(&(df->mod_priority))?
|
||||
';' import(0)*
|
||||
|
|
|
@ -33,13 +33,12 @@ open_scope(scopetype)
|
|||
*/
|
||||
register struct scope *sc = new_scope();
|
||||
register struct scopelist *ls = new_scopelist();
|
||||
|
||||
|
||||
assert(scopetype == OPENSCOPE || scopetype == CLOSEDSCOPE);
|
||||
|
||||
clear((char *) sc, sizeof (*sc));
|
||||
sc->sc_scopeclosed = scopetype == CLOSEDSCOPE;
|
||||
sc->sc_level = proclevel;
|
||||
sc->sc_forw = 0;
|
||||
sc->sc_def = 0;
|
||||
sc->sc_off = 0;
|
||||
if (scopetype == OPENSCOPE) {
|
||||
ls->next = CurrVis;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ struct scope {
|
|||
arith sc_off; /* offsets of variables in this scope */
|
||||
char sc_scopeclosed; /* flag indicating closed or open scope */
|
||||
int sc_level; /* level of this scope */
|
||||
struct def *sc_definedby; /* The def structure defining this scope */
|
||||
};
|
||||
|
||||
struct scopelist {
|
||||
|
|
|
@ -16,7 +16,6 @@ static char *RcsId = "$Header$";
|
|||
#include "node.h"
|
||||
|
||||
static int loopcount = 0; /* Count nested loops */
|
||||
extern struct def *currentdef;
|
||||
}
|
||||
|
||||
statement(struct node **pnd;)
|
||||
|
@ -61,28 +60,11 @@ statement(struct node **pnd;)
|
|||
WithStatement(pnd)
|
||||
|
|
||||
EXIT
|
||||
{ if (!loopcount) {
|
||||
error("EXIT not in a LOOP");
|
||||
}
|
||||
{ if (!loopcount) error("EXIT not in a LOOP");
|
||||
*pnd = MkNode(Stat, NULLNODE, NULLNODE, &dot);
|
||||
}
|
||||
|
|
||||
RETURN { *pnd = nd = MkNode(Stat, NULLNODE, NULLNODE, &dot); }
|
||||
[
|
||||
expression(&(nd->nd_right))
|
||||
{ if (scopeclosed(CurrentScope)) {
|
||||
error("a module body has no result value");
|
||||
}
|
||||
else if (! currentdef->df_type->next) {
|
||||
error("procedure \"%s\" has no result value", currentdef->df_idf->id_text);
|
||||
}
|
||||
}
|
||||
|
|
||||
{ if (currentdef->df_type->next) {
|
||||
error("procedure \"%s\" must return a value", currentdef->df_idf->id_text);
|
||||
}
|
||||
}
|
||||
]
|
||||
ReturnStatement(pnd)
|
||||
]?
|
||||
;
|
||||
|
||||
|
@ -193,18 +175,28 @@ RepeatStatement(struct node **pnd;)
|
|||
ForStatement(struct node **pnd;)
|
||||
{
|
||||
register struct node *nd;
|
||||
struct node *dummy;
|
||||
}:
|
||||
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); }
|
||||
IDENT { (*pnd)->nd_IDF = dot.TOK_IDF; }
|
||||
BECOMES { nd = MkNode(Stat, NULLNODE, NULLNODE, &dot);
|
||||
(*pnd)->nd_left = nd;
|
||||
}
|
||||
expression(&(nd->nd_left))
|
||||
TO
|
||||
expression(&(nd->nd_right))
|
||||
[
|
||||
BY { nd->nd_right=MkNode(Link,NULLNODE,nd->nd_right,&dot);
|
||||
BY
|
||||
ConstExpression(&dummy)
|
||||
{
|
||||
if (!(dummy->nd_type->tp_fund & T_INTORCARD)) {
|
||||
error("illegal type in BY clause");
|
||||
}
|
||||
nd->nd_INT = dummy->nd_INT;
|
||||
FreeNode(dummy);
|
||||
}
|
||||
ConstExpression(&(nd->nd_right->nd_left))
|
||||
|
|
||||
{ nd->nd_INT = 1; }
|
||||
]
|
||||
DO
|
||||
StatementSequence(&((*pnd)->nd_right))
|
||||
|
@ -227,3 +219,27 @@ WithStatement(struct node **pnd;)
|
|||
StatementSequence(&(nd->nd_right))
|
||||
END
|
||||
;
|
||||
|
||||
ReturnStatement(struct node **pnd;)
|
||||
{
|
||||
register struct def *df = CurrentScope->sc_definedby;
|
||||
register struct node *nd;
|
||||
} :
|
||||
|
||||
RETURN { *pnd = nd = MkNode(Stat, NULLNODE, NULLNODE, &dot); }
|
||||
[
|
||||
expression(&(nd->nd_right))
|
||||
{ if (scopeclosed(CurrentScope)) {
|
||||
error("a module body has no result value");
|
||||
}
|
||||
else if (! df->df_type->next) {
|
||||
error("procedure \"%s\" has no result value", df->df_idf->id_text);
|
||||
}
|
||||
}
|
||||
|
|
||||
{ if (df->df_type->next) {
|
||||
error("procedure \"%s\" must return a value", df->df_idf->id_text);
|
||||
}
|
||||
}
|
||||
]
|
||||
;
|
||||
|
|
|
@ -4,8 +4,9 @@
|
|||
|
||||
struct paramlist { /* structure for parameterlist of a PROCEDURE */
|
||||
struct paramlist *next;
|
||||
struct type *par_type; /* Parameter type */
|
||||
int par_var; /* flag, set if VAR parameter */
|
||||
struct def *par_def; /* "df" of parameter */
|
||||
#define IsVarParam(xpar) ((xpar)->par_def->df_flags & D_VARPAR)
|
||||
#define TypeOfParam(xpar) ((xpar)->par_def->df_type)
|
||||
};
|
||||
|
||||
/* ALLOCDEF "paramlist" */
|
||||
|
|
|
@ -19,6 +19,7 @@ static char *RcsId = "$Header$";
|
|||
#include "LLlex.h"
|
||||
#include "node.h"
|
||||
#include "const.h"
|
||||
#include "scope.h"
|
||||
|
||||
/* To be created dynamically in main() from defaults or from command
|
||||
line parameters.
|
||||
|
@ -58,8 +59,14 @@ struct type
|
|||
*error_type;
|
||||
|
||||
struct paramlist *h_paramlist;
|
||||
#ifdef DEBUG
|
||||
int cnt_paramlist;
|
||||
#endif
|
||||
|
||||
struct type *h_type;
|
||||
#ifdef DEBUG
|
||||
int cnt_type;
|
||||
#endif
|
||||
|
||||
extern label data_label();
|
||||
|
||||
|
@ -215,31 +222,33 @@ init_types()
|
|||
error_type = standard_type(T_CHAR, 1, (arith) 1);
|
||||
}
|
||||
|
||||
/* 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.
|
||||
Actually, "ids" is only used because it tells us how many parameters
|
||||
there were with this type.
|
||||
*/
|
||||
struct paramlist *
|
||||
ParamList(ids, tp, VARp)
|
||||
ParamList(ppr, ids, tp, VARp, off)
|
||||
register struct node *ids;
|
||||
struct paramlist **ppr;
|
||||
struct type *tp;
|
||||
arith *off;
|
||||
{
|
||||
/* Create (part of) a parameterlist of a procedure.
|
||||
"ids" indicates the list of identifiers, "tp" their type, and
|
||||
"VARp" is set when the parameters are VAR-parameters.
|
||||
*/
|
||||
register struct paramlist *pr;
|
||||
register struct def *df;
|
||||
struct paramlist *pstart;
|
||||
|
||||
pstart = pr = new_paramlist();
|
||||
pr->par_type = tp;
|
||||
pr->par_var = VARp;
|
||||
for (ids = ids->next; ids; ids = ids->next) {
|
||||
pr->next = new_paramlist();
|
||||
pr = pr->next;
|
||||
pr->par_type = tp;
|
||||
pr->par_var = VARp;
|
||||
while (ids) {
|
||||
pr = new_paramlist();
|
||||
pr->next = *ppr;
|
||||
*ppr = pr;
|
||||
df = define(ids->nd_IDF, CurrentScope, D_VARIABLE);
|
||||
pr->par_def = df;
|
||||
df->df_type = tp;
|
||||
if (VARp) df->df_flags = D_VARPAR;
|
||||
else df->df_flags = D_VALPAR;
|
||||
df->var_off = align(*off, word_align);
|
||||
*off = df->var_off + tp->tp_size;
|
||||
ids = ids->next;
|
||||
}
|
||||
pr->next = 0;
|
||||
return pstart;
|
||||
}
|
||||
|
||||
chk_basesubrange(tp, base)
|
||||
|
@ -551,8 +560,8 @@ DumpType(tp)
|
|||
if (par) {
|
||||
print("; p:");
|
||||
while(par) {
|
||||
if (par->par_var) print("VAR ");
|
||||
DumpType(par->par_type);
|
||||
if (IsVarParam(par)) print("VAR ");
|
||||
DumpType(TypeOfParam(par));
|
||||
par = par->next;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,8 @@ static char *RcsId = "$Header$";
|
|||
|
||||
#include "type.h"
|
||||
#include "def.h"
|
||||
#include "LLlex.h"
|
||||
#include "node.h"
|
||||
|
||||
int
|
||||
TstTypeEquiv(tp1, tp2)
|
||||
|
@ -70,8 +72,8 @@ TstProcEquiv(tp1, tp2)
|
|||
/* Now check the parameters
|
||||
*/
|
||||
while (p1 && p2) {
|
||||
if (p1->par_var != p2->par_var ||
|
||||
!TstParEquiv(p1->par_type, p2->par_type)) return 0;
|
||||
if (IsVarParam(p1) != IsVarParam(p2) ||
|
||||
!TstParEquiv(TypeOfParam(p1), TypeOfParam(p2))) return 0;
|
||||
p1 = p1->next;
|
||||
p2 = p2->next;
|
||||
}
|
||||
|
@ -172,11 +174,11 @@ TstAssCompat(tp1, tp2)
|
|||
}
|
||||
|
||||
int
|
||||
TstParCompat(formaltype, actualtype, VARflag)
|
||||
TstParCompat(formaltype, actualtype, VARflag, nd)
|
||||
struct type *formaltype, *actualtype;
|
||||
struct node *nd;
|
||||
{
|
||||
/* Check type compatibility for a parameter in a procedure
|
||||
call. Ordinary type compatibility is sufficient in any case.
|
||||
/* Check type compatibility for a parameter in a procedure call.
|
||||
Assignment compatibility may do if the parameter is
|
||||
a value parameter.
|
||||
Otherwise, a conformant array may do, or an ARRAY OF WORD
|
||||
|
@ -185,11 +187,20 @@ TstParCompat(formaltype, actualtype, VARflag)
|
|||
*/
|
||||
|
||||
return
|
||||
TstCompat(formaltype, actualtype)
|
||||
TstTypeEquiv(formaltype, actualtype)
|
||||
||
|
||||
( !VARflag && TstAssCompat(formaltype, actualtype))
|
||||
||
|
||||
( formaltype == word_type && actualtype->tp_size == word_size)
|
||||
( formaltype == word_type
|
||||
&&
|
||||
( actualtype->tp_size == word_size
|
||||
||
|
||||
( !VARflag
|
||||
&&
|
||||
actualtype->tp_size <= word_size
|
||||
)
|
||||
)
|
||||
)
|
||||
||
|
||||
( IsConformantArray(formaltype)
|
||||
&&
|
||||
|
@ -203,5 +214,21 @@ TstParCompat(formaltype, actualtype, VARflag)
|
|||
&& TstTypeEquiv(formaltype->arr_elem, char_type)
|
||||
)
|
||||
)
|
||||
);
|
||||
)
|
||||
||
|
||||
( VARflag && OldCompat(formaltype, actualtype, nd))
|
||||
;
|
||||
}
|
||||
|
||||
int
|
||||
OldCompat(ft, at, nd)
|
||||
struct type *ft, *at;
|
||||
struct node *nd;
|
||||
{
|
||||
if (TstCompat(ft, at)) {
|
||||
node_warning(nd, "oldfashioned! types of formal and actual must be identical");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ DoProfil()
|
|||
{
|
||||
static label filename_label = 0;
|
||||
|
||||
if (options['p']) {
|
||||
if (! options['L']) {
|
||||
if (!filename_label) {
|
||||
filename_label = data_label();
|
||||
C_df_dlb(filename_label);
|
||||
|
@ -278,10 +278,16 @@ WalkStat(nd, lab)
|
|||
return;
|
||||
}
|
||||
|
||||
if (options['p']) C_lin((arith) nd->nd_lineno);
|
||||
if (options['L']) C_lin((arith) nd->nd_lineno);
|
||||
|
||||
if (nd->nd_class == Call) {
|
||||
if (chk_call(nd)) CodeCall(nd);
|
||||
if (chk_call(nd)) {
|
||||
if (nd->nd_type != 0) {
|
||||
node_error(nd, "procedure call expected");
|
||||
return;
|
||||
}
|
||||
CodeCall(nd);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -289,7 +295,7 @@ WalkStat(nd, lab)
|
|||
|
||||
switch(nd->nd_symb) {
|
||||
case BECOMES:
|
||||
DoAssign(nd, left, right, 0);
|
||||
DoAssign(nd, left, right);
|
||||
break;
|
||||
|
||||
case IF:
|
||||
|
@ -362,51 +368,27 @@ WalkStat(nd, lab)
|
|||
struct node *fnd;
|
||||
label l1 = instructionlabel++;
|
||||
label l2 = instructionlabel++;
|
||||
arith incr = 1;
|
||||
arith size;
|
||||
|
||||
assert(left->nd_symb == TO);
|
||||
assert(left->nd_left->nd_symb == BECOMES);
|
||||
|
||||
DoAssign(left->nd_left,
|
||||
left->nd_left->nd_left,
|
||||
left->nd_left->nd_right, 1);
|
||||
if (! DoForInit(nd, left)) break;
|
||||
fnd = left->nd_right;
|
||||
if (fnd->nd_symb == BY) {
|
||||
incr = fnd->nd_left->nd_INT;
|
||||
fnd = fnd->nd_right;
|
||||
}
|
||||
if (! chk_expr(fnd)) return;
|
||||
size = fnd->nd_type->tp_size;
|
||||
if (fnd->nd_class != Value) {
|
||||
*pds = InitDesig;
|
||||
CodeExpr(fnd, pds, NO_LABEL, NO_LABEL);
|
||||
CodeValue(pds, size);
|
||||
CodePExpr(fnd);
|
||||
tmp = NewInt();
|
||||
C_stl(tmp);
|
||||
}
|
||||
if (!TstCompat(left->nd_left->nd_left->nd_type,
|
||||
fnd->nd_type)) {
|
||||
node_error(fnd, "type incompatibility in limit of FOR loop");
|
||||
break;
|
||||
}
|
||||
C_bra(l1);
|
||||
C_df_ilb(l2);
|
||||
WalkNode(right, lab);
|
||||
*pds = InitDesig;
|
||||
C_loc(incr);
|
||||
CodeDesig(left->nd_left->nd_left, pds);
|
||||
CodeValue(pds, size);
|
||||
C_loc(left->nd_INT);
|
||||
CodePExpr(nd);
|
||||
C_adi(int_size);
|
||||
*pds = InitDesig;
|
||||
CodeDesig(left->nd_left->nd_left, pds);
|
||||
CodeStore(pds, size);
|
||||
CodeDStore(nd);
|
||||
C_df_ilb(l1);
|
||||
*pds = InitDesig;
|
||||
CodeDesig(left->nd_left->nd_left, pds);
|
||||
CodeValue(pds, size);
|
||||
CodePExpr(nd);
|
||||
if (tmp) C_lol(tmp); else C_loc(fnd->nd_INT);
|
||||
if (incr > 0) {
|
||||
if (left->nd_INT > 0) {
|
||||
C_ble(l2);
|
||||
}
|
||||
else C_bge(l2);
|
||||
|
@ -461,8 +443,7 @@ node_error(fnd, "type incompatibility in limit of FOR loop");
|
|||
case RETURN:
|
||||
if (right) {
|
||||
WalkExpr(right, NO_LABEL, NO_LABEL);
|
||||
/* What kind of compatibility do we need here ???
|
||||
assignment compatibility?
|
||||
/* Assignment compatibility? Yes, see Rep. 9.11
|
||||
*/
|
||||
if (!TstAssCompat(func_type, right->nd_type)) {
|
||||
node_error(right, "type incompatibility in RETURN statement");
|
||||
|
@ -519,27 +500,51 @@ WalkDesignator(nd)
|
|||
|
||||
Desig = InitDesig;
|
||||
CodeDesig(nd, &Desig);
|
||||
|
||||
}
|
||||
|
||||
DoAssign(nd, left, right, forloopass)
|
||||
DoForInit(nd, left)
|
||||
register struct node *nd, *left;
|
||||
{
|
||||
|
||||
nd->nd_left = nd->nd_right = 0;
|
||||
nd->nd_class = Name;
|
||||
nd->nd_symb = IDENT;
|
||||
|
||||
if (! chk_designator(nd, VARIABLE, D_DEFINED) ||
|
||||
! chk_expr(left->nd_left) ||
|
||||
! chk_expr(left->nd_right)) return;
|
||||
|
||||
if (nd->nd_type->tp_size > word_size ||
|
||||
!(nd->nd_type->tp_fund & T_DISCRETE)) {
|
||||
node_error(nd, "illegal type of FOR loop variable");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!TstCompat(nd->nd_type, left->nd_left->nd_type) ||
|
||||
!TstCompat(nd->nd_type, left->nd_right->nd_type)) {
|
||||
if (!TstAssCompat(nd->nd_type, left->nd_left->nd_type) ||
|
||||
!TstAssCompat(nd->nd_type, left->nd_right->nd_type)) {
|
||||
node_error(nd, "type incompatibility in FOR statement");
|
||||
return 0;
|
||||
}
|
||||
node_warning(nd, "old-fashioned! compatibility required in FOR statement");
|
||||
}
|
||||
|
||||
CodePExpr(left->nd_left);
|
||||
CodeDStore(nd);
|
||||
}
|
||||
|
||||
DoAssign(nd, left, right)
|
||||
struct node *nd;
|
||||
register struct node *left, *right;
|
||||
{
|
||||
/* May we do it in this order (expression first) ??? */
|
||||
/* May we do it in this order (expression first) ??? */
|
||||
struct desig ds;
|
||||
|
||||
WalkExpr(right, NO_LABEL, NO_LABEL);
|
||||
if (! chk_designator(left, DESIGNATOR|VARIABLE, D_DEFINED)) return;
|
||||
|
||||
if (forloopass) {
|
||||
if (! TstCompat(left->nd_type, right->nd_type)) {
|
||||
node_error(nd, "type incompatibility in FOR loop");
|
||||
return;
|
||||
}
|
||||
/* Test if the left hand side may be a for loop variable ??? */
|
||||
}
|
||||
else if (! TstAssCompat(left->nd_type, right->nd_type)) {
|
||||
if (! TstAssCompat(left->nd_type, right->nd_type)) {
|
||||
node_error(nd, "type incompatibility in assignment");
|
||||
return;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue